java抽奖算法


前言

根据时间区间生成的抽奖算法,这种算法适用于各种抽奖场景,例如:大转盘,老虎机,刮刮乐等。
在这里插入图片描述


一、抽奖规则

如:活动时间为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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值