SpringBoot實現(xiàn)抽獎算法的示例代碼
前言
當我們參加各種活動和抽獎時,抽獎環(huán)節(jié)總是能引起極大興趣和關注。抽獎的公正性和隨機性是保證活動公平和成功的重要因素。
本文將介紹抽獎算法的實現(xiàn)原理及其在Java編程語言中的應用,以幫助讀者了解抽獎程序的實現(xiàn)細節(jié),同時也為讀者提供一些有用的參考和借鑒。
創(chuàng)建抽獎表
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 '上下架狀態(tài):0下架1上架', `position` tinyint(1) DEFAULT NULL COMMENT '位置', `day_max_times` tinyint unsigned DEFAULT '0' COMMENT '每天最多中獎次數(shù),大于0時生效', `month_max_times` tinyint unsigned DEFAULT '0' COMMENT '每月最多中獎次數(shù),大于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 '關聯(lián)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.將獎品按集合中順序概率計算成所占比例區(qū)間,放入比例集合。并產(chǎn)生一個隨機數(shù)加入其中,排序。
2.排序后,隨機數(shù)落在哪個區(qū)間,就表示那個區(qū)間的獎品被抽中。
3.返回的隨機數(shù)在集合中的索引,該索引就是獎品集合中的索引。
4.比例區(qū)間的計算通過概率相加獲得。
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) { //判斷當天中獎次數(shù) 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) { //判斷當月中獎次數(shù) 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實現(xiàn)抽獎算法的示例代碼的文章就介紹到這了,更多相關SpringBoot抽獎算法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot 使用Prometheus采集自定義指標數(shù)據(jù)的方案
這篇文章主要介紹了SpringBoot 使用Prometheus采集自定義指標數(shù)據(jù),我們在k8s集群成功搭建了Prometheus服務,今天,我們將在springboot2.x中使用prometheus記錄指標,需要的朋友可以參考下2022-10-10java 重載(overload)與重寫(override)詳解及實例
這篇文章主要介紹了java 重載(overload)與重寫(override)詳解及實例的相關資料,并附實例代碼,需要的朋友可以參考下2016-10-10Security中的@PostAuthorize、@PreFilter和@PostFilter詳解
這篇文章主要介紹了Security中的@PostAuthorize、@PreFilter和@PostFilter詳解,@PostAuthorize是在方法調用完成后進行權限檢查,它不能控制方法是否能被調用,只能在方法調用完成后檢查權限決定是否要拋出AccessDeniedException,需要的朋友可以參考下2023-11-11