前言
根据时间区间生成的抽奖算法,这种算法适用于各种抽奖场景,例如:大转盘,老虎机,刮刮乐等。
一、抽奖规则
如:活动时间为1-15号
1.把1号到15号,所有的秒加起来,15* 24* 60* 60 = 1339200
2.从1到1339200随机取几个数字作为中奖项
3.中奖的时间点已经固定了,只有在这个时间抽奖才能中
4.加个误差处理,例如中奖时间是08-10 12:00:00,但是这个时间点没人抽奖,那就然后顺排,这个时间点之后,第一个抽奖的人就中奖
5.把凌晨0点到8点,这个时间段排除掉
6.按照奖项的个数取随机数。
二、抽奖算法
1.获取活动时间的总时长
代码如下(示例):
public static void main(String[] args) throws ParseException {
List<ActivityPrizes> apList = new ArrayList<ActivityPrizes>();
ActivityPrizes activityPrizes = new ActivityPrizes();
activityPrizes.setPrizeNum(3);
apList.add(activityPrizes);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//抽奖开始时间
Date startTime= sdf.parse("2021-09-01 00:00:00");
//抽奖结束时间
Date endTime = sdf.parse("2021-09-15 23:59:59");
//中奖最大时间点(精确到秒)
int interval = (int) ((endTime .getTime() - startTime.getTime())/1000);
List<Integer> numList = new ArrayList<Integer>();
//根据奖项个数生成对应的中奖时间点
Long sum = apList.stream().mapToLong(ActivityPrizes::getPrizeNum).sum();
for (int i = 0; i < sum; i++) {
//生成随机中奖时间点
int random = getRandom(0, interval,"2021-09-01 00:00:00");
numList = addNumList(random, numList);
}
System.out.println(numList);
}
2.生成随机时间点,过滤抽奖规则
代码如下(示例):
/**
* 获取区间随机数
* @author yuqz
* @date 2021年9月24日
* @param min
* @param max
* @param startDate
* @return
* @throws ParseException
*/
public static int getRandom(int min, int max,String startDate) throws ParseException {
Random random = new Random();
int s = random.nextInt(max) % (max - min + 1) + min;
//加上秒后的时间
String time = timePastTenSecond(startDate, s);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Boolean bol = true;
//排除当天0-8点.
String sTime = sdf.format(sdf.parseObject(time))+" 00:00:00";
String eTime = sdf.format(sdf.parseObject(time))+" 08:00:00";
while(bol) {
if( sf.parse(time).after(sf.parse(sTime)) && sf.parse(time).before(sf.parse(eTime))) {
s = random.nextInt(max) % (max - min + 1) + min;
time = timePastTenSecond(startDate, s);
}else{
bol = false;
}
}
return s;
}
/**
* 日期+秒
* @author yuqz
* @date 2021年9月24日
* @param otime
* @param second
* @return
*/
public static String timePastTenSecond(String otime,int second) {
try {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dt=sdf.parse(otime);
Calendar newTime = Calendar.getInstance();
newTime.setTime(dt);
newTime.add(Calendar.SECOND,second);
Date dt1=newTime.getTime();
String retval = sdf.format(dt1);
return retval;
}
catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 添加随机数并排序
* @author yuqz
* @date 2021年9月24日
* @param e
* @param sSorted
* @return
*/
public List<Integer> addNumList(int e,List<Integer> sSorted) {
boolean inserted = false;
// 非首次插入需要遍历list,找到比插入值大的数所在索引并插入,后面的元素后移
for (int i = 0; i < sSorted.size(); i++) {
if (e < sSorted.get(i)) {
sSorted.add(i, e);
inserted = true;
break;
}
}
// 没找到值比自己大的插入点,追加到最后
if (!inserted) {
sSorted.add(e);
}
return sSorted;
}