java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot抽奖算法

SpringBoot实现抽奖算法的示例代码

作者:越走越远的风

这篇文章主要为大家详细介绍了如何通过SpringBoot实现抽奖算法,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以了解一下

前言

当我们参加各种活动和抽奖时,抽奖环节总是能引起极大兴趣和关注。抽奖的公正性和随机性是保证活动公平和成功的重要因素。

本文将介绍抽奖算法的实现原理及其在Java编程语言中的应用,以帮助读者了解抽奖程序的实现细节,同时也为读者提供一些有用的参考和借鉴。

创建抽奖表

CREATE TABLE `app_draw_prize` (
  `id` bigint NOT NULL,
  `activity_id` int unsigned DEFAULT NULL COMMENT '活动id',
  `name` varchar(50) DEFAULT NULL COMMENT '奖品名称',
  `url` varchar(200) DEFAULT NULL COMMENT '图片地址(未使用)',
  `value` varchar(10) DEFAULT '0' COMMENT '值',
  `probability` double unsigned DEFAULT '0' COMMENT '概率',
  `type` tinyint unsigned DEFAULT NULL COMMENT '类型',
  `status` tinyint unsigned DEFAULT '0' COMMENT '上下架状态:0下架1上架',
  `position` tinyint(1) DEFAULT NULL COMMENT '位置',
  `day_max_times` tinyint unsigned DEFAULT '0' COMMENT '每天最多中奖次数,大于0时生效',
  `month_max_times` tinyint unsigned DEFAULT '0' COMMENT '每月最多中奖次数,大于0时生效',
  `show` tinyint unsigned DEFAULT '0' COMMENT '是否首页展示中奖记录0否1是',
  `default_prize` tinyint(1) DEFAULT '0' COMMENT '抽奖上限时直接返回默认奖品',
  `ref_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '关联id',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='抽奖奖品表';

抽奖代码

算法思路

1.将奖品按集合中顺序概率计算成所占比例区间,放入比例集合。并产生一个随机数加入其中,排序。

2.排序后,随机数落在哪个区间,就表示那个区间的奖品被抽中。

3.返回的随机数在集合中的索引,该索引就是奖品集合中的索引。

4.比例区间的计算通过概率相加获得。

private DrawPrize doDrawPrize(Long activityId, Long userId) {  
    List<DrawPrize> drawPrizes = drawPrizeMapper.selectList(new LambdaQueryWrapper<DrawPrize>()  
            .eq(DrawPrize::getActivityId, activityId)
            .eq(DrawPrize::getStatus, 1)
            .orderByDesc(DrawPrize::getProbability));  
    List<Double> probLists = new ArrayList<>(drawPrizes.size());  
    Double sumProb = 0D;  
    for (DrawPrize drawPrize : drawPrizes) {  
        sumProb += drawPrize.getProbability();  
    }  
    if (sumProb <= 0) {  
        throw new IllegalArgumentException("抽奖概率设置错误");  
    }  
    Double rate = 0D;  
    for (DrawPrize drawPrize : drawPrizes) {  
        rate += drawPrize.getProbability();  
        probLists.add(rate / sumProb);  
    }  
    double random = Math.random();  
    probLists.add(random);  
    Collections.sort(probLists);  
    DrawPrize drawPrize = drawPrizes.get(probLists.indexOf(random));  
    if (drawPrize.getDayMaxTimes() > 0) {  
        //判断当天中奖次数  
        String daily = DateUtil.formatDate(new Date());  
        Long count = drawRecordMapper.selectCount(new LambdaQueryWrapper<DrawRecord>()  
                .eq(DrawRecord::getMemberId, userId)  
                .eq(DrawRecord::getPrizeId, drawPrize.getId())  
                .eq(DrawRecord::getDaily, daily));  
        if (count >= drawPrize.getDayMaxTimes()) {  
        //直接返回谢谢参与  
            return drawPrizes.stream()  
                    .filter(d -> d.getDefaultPrize() == 1)  
                    .findFirst()  
                    .orElseThrow(() -> new IllegalArgumentException("抽奖错误"));  
        }  
    }  
    if (drawPrize.getMonthMaxTimes() > 0) {  
        //判断当月中奖次数  
        Long count = drawRecordMapper.selectCount(new LambdaQueryWrapper<DrawRecord>()  
                .eq(DrawRecord::getMemberId, userId)  
                .eq(DrawRecord::getPrizeId, drawPrize.getId())  
                .eq(DrawRecord::getMonth, DateUtil.month(new Date())));  
        if (count >= drawPrize.getMonthMaxTimes()) {  
        //直接返回谢谢参与  
            return drawPrizes.stream()  
                    .filter(d -> d.getDefaultPrize() == 1)  
                    .findFirst()  
                    .orElseThrow(() -> new IllegalArgumentException("抽奖错误"));  
        }  
    }  
    return drawPrize;  
}

到此这篇关于SpringBoot实现抽奖算法的示例代码的文章就介绍到这了,更多相关SpringBoot抽奖算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文