It takes about 5 minutes to read this article.

From: blog.csdn.net/wang258533488/article/details/78901303

1 overview

Project development often has the demand of such marketing activities as lottery, such as: integral big turntable, scratch-off, slot machines and so on, in fact, the backstage implementation method is the same, this paper introduces a common lottery implementation method. The whole drawing process includes the following aspects:

  • The prize
  • The prize pool
  • Lottery algorithm
  • The prize limit
  • The prize distribution

2 the prize

Prizes include prizes, prize probabilities and limits, and prize records. The prize list:

CREATE TABLE `points_luck_draw_prize` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, 'name' varchar(50) DEFAULT NULL COMMENT '表 示 ',' url 'varchar(50) DEFAULT NULL COMMENT' 表 示 ', 'value' varchar(20) DEFAULT NULL, 'type' tinyint(4) DEFAULT NULL COMMENT ' 'status' tinyint(4) DEFAULT NULL COMMENT' status ', 'is_del' bit(1) DEFAULT NULL COMMENT 'delete ', 'position' int(5) DEFAULT NULL COMMENT ' ', 'phase' int(10) DEFAULT NULL COMMENT ' ', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (' id ') ENGINE=InnoDB AUTO_INCREMENT=164 DEFAULT CHARSET= UTf8MB4 COMMENT=' table ';Copy the code

Table of prize Probability Limits:

CREATE TABLE `points_luck_draw_probability` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, 'points_prize_id' bigint(20) DEFAULT NULL COMMENT '主 位 名 ',' points_prize_phase 'int(10) DEFAULT NULL COMMENT' 主 位 名 ', 'probability' float(4,2) DEFAULT NULL COMMENT 'probability ',' frozen 'int(11) DEFAULT NULL COMMENT' frozen ', 'prize_day_max_times' int(11) DEFAULT NULL COMMENT' 'user_prize_month_MAX_times' int(11) DEFAULT NULL COMMENT' Maximum number of entries per user per month ', 'create_time' datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (' id ') ENGINE=InnoDB AUTO_INCREMENT= 100 DEFAULT CHARSET= UTf8MB4 COMMENT=' 1 ';Copy the code

Prize Record Sheet:

CREATE TABLE `points_luck_draw_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, 'member_id' bigint(20) DEFAULT NULL COMMENT 'ID',' member_mobile 'varchar(11) DEFAULT NULL COMMENT' mobile ID', 'points' int(11) DEFAULT NULL COMMENT' 表 示 ', 'prize_id' bigint(20) DEFAULT NULL COMMENT '表 示 ', 'result' smallint(4) DEFAULT NULL COMMENT '1: smallint 2: smallint ', 'month' varchar(10) DEFAULT NULL COMMENT 'smallint ', 'daily' date DEFAULT NULL COMMENT '表 名 ',' create_time 'datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (' id ') ENGINE=InnoDB AUTO_INCREMENT=3078 DEFAULT CHARSET= UTf8MB4 COMMENT=' unsigned ';Copy the code

3 the prize pool

A prize pool is a pool assembled according to the probability and limits of the prize. It mainly includes two dimensions: the total pool value of prizes and the pool value of each prize (divided into start value and end value).

  • Prize pool value: The sum of all prize pool values.

  • Pool value per prize: The algorithm can be flexible, commonly used in the following two ways:

  • Probability of prizes *10000 (guaranteed to be an integer)

    Probability of prizes 10,000 prizes remaining number

Prize pool bean:

Public class implements Serializable{/** * private int total; Private List<PrizePoolBean> poolBeanList; private List<PrizePoolBean> poolBeanList; }Copy the code

Prize beans in the pool:

Public class PrizePoolBean implements Serializable{/** * private Long ID; /** ** private int begin; /** * private int end; }Copy the code

Prize pool assembly code:

/** * Obtaining Mega Millionaire Prize Pool * @param zillionaireProductMap Mega Millionaire Prize Map * @Param Flag True: With cash False: Without cash * @Return */ private PrizePool getZillionairePrizePool(Map<Long, ActivityProduct> zillionaireProductMap, Boolean flag) {// Total prize pool value int total = 0; List<PrizePoolBean> poolBeanList = new ArrayList<>(); for(Entry<Long, ActivityProduct> entry : zillionaireProductMap.entrySet()){ ActivityProduct product = entry.getValue(); // No cash prize pool, filter out cash prizes if(! flag && product.getCategoryId() == ActivityPrizeTypeEnums.XJ.getType()){ continue; } PrizePoolBean PrizePoolBean = new PrizePoolBean(); prizePoolBean.setId(product.getProductDescriptionId()); prizePoolBean.setBengin(total); total = total + product.getEarnings().multiply(new BigDecimal("10000")).intValue(); prizePoolBean.setEnd(total); poolBeanList.add(prizePoolBean); } PrizePool prizePool = new PrizePool(); prizePool.setTotal(total); prizePool.setPoolBeanList(poolBeanList); return prizePool; }Copy the code

4. Lottery algorithm

The whole lottery algorithm is:

  1. An integer within the total value of the random prize pool
  2. Cyclic comparison of all prizes in the prize pool, random number falls to which prize pool interval is which prize win.

Lucky draw code:

Public static PrizePoolBean getPrize(PrizePool PrizePool){int total = prizepol.getTotal (); Rand =new Random(); int random=rand.nextInt(total); PrizePoolBean PrizePoolBean: prizePool.getPoolBeanList()){ if(random >= prizePoolBean.getBengin() && random < prizePoolBean.getEnd()){ return prizePoolBean; } } return null; }Copy the code

5 Restrictions on Prizes

In the actual lottery for some of the larger prizes often have a number of restrictions, such as: a day prize is selected up to 5 times, a prize each user can only be selected once. Similar restrictions, and so on, for such restrictions we divided into two cases to differentiate between:

  1. Limited prizes are relatively small, usually no more than 3: in this case we can reassemble the prize pool by filtering out the ineligible prizes so that all the winners are eligible. For example, in the Super Monopoly lottery code above, we specify that cash prizes can only be drawn 5 times a day, so we can assemble cash prizes and no cash prizes according to the criteria.
  2. There are more limited prizes, so if you want to use the first way, it will lead to the assembly of prizes is very tedious, low performance, we can use the prize after checking the prize is eligible, if not eligible to return a fixed prize.

6 Prize Distribution

Prizes can be distributed in factory mode. Different trophy types use different trophy distribution processors. The example code is as follows:

@param prizeList * @throws Exception */ @async ("myAsync") @transactional (rollbackFor = exception.class, propagation = Propagation.REQUIRED) public Future<Boolean> sendPrize(Long memberId, List<PrizeDto> prizeList){ try { for(PrizeDto prizeDto : PrizeList) {/ / filter out thank you to patronize the prize the if (prizeDto. GetType () = = PointsLuckDrawTypeEnum. XXHG. GetType ()) {continue; } / / to get from the factory depending on the type of award prizes issued class SendPrizeProcessor SendPrizeProcessor = sendPrizeProcessorFactory. GetSendPrizeProcessor ( PointsLuckDrawTypeEnum.getPointsLuckDrawTypeEnumByType(prizeDto.getType())); If (objectutil.isnotnull (sendPrizeProcessor)){// Send sendPrizeProcessor. Send (memberId, prizeDto); } } return new AsyncResult<>(Boolean.TRUE); }catch (Exception e){// saveSendPrizeErrorLog(memberId, prizeList); Logger. error(" Abnormal distribution of bonus points in lottery ", e); return new AsyncResult<>(Boolean.FALSE); }}Copy the code

The factory class:

@Component public class SendPrizeProcessorFactory implements ApplicationContextAware{ private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public SendPrizeProcessor getSendPrizeProcessor(PointsLuckDrawTypeEnum typeEnum){ String processorName = typeEnum.getSendPrizeProcessorName(); if(StrUtil.isBlank(processorName)){ return null; } SendPrizeProcessor processor = applicationContext.getBean(processorName, SendPrizeProcessor.class); If (objectutil. isNull(processor)){throw new RuntimeException(" no send award processor with name [" + processorName + "] "); } return processor; }}Copy the code

Examples of Award Distribution:

/** */ @component ("sendHbPrizeProcessor") public class sendHbPrizeProcessor implements SendPrizeProcessor{ private Logger LOGGER = LoggerFactory.getLogger(SendHbPrizeProcessor.class); @Resource private CouponService couponService; @Resource private MessageLogService messageLogService; @Override public void send(Long memberId, PrizeDto PrizeDto) throws the Exception {/ / issued a red envelope Coupon Coupon. = couponService receiveCoupon (memberId, Long.parseLong(prizeDto.getValue())); / / sending station letter messageLogService. InsertActivityMessageLog (memberId, "you to participate in the activities of integral lottery draw the" + coupon. GetAmount () + "yuan financial red envelope has to account, Thank you for your participation ", "Notice of winning bonus drawing "); MemberId + "selected in bonus draw" + prizedto.getPrizename () + "Issued already!" ); }}Copy the code

Recommend 3 original Springboot +Vue projects, with complete video explanation and documentation and source code:

Build a complete project from Springboot+ ElasticSearch + Canal

  • Video tutorial: www.bilibili.com/video/BV1Jq…
  • A complete development documents: www.zhuawaba.com/post/124
  • Online demos: www.zhuawaba.com/dailyhub

【VueAdmin】 hand to hand teach you to develop SpringBoot+Jwt+Vue back-end separation management system

  • Full 800 – minute video tutorial: www.bilibili.com/video/BV1af…
  • Complete development document front end: www.zhuawaba.com/post/18
  • Full development documentation backend: www.zhuawaba.com/post/19

【VueBlog】 Based on SpringBoot+Vue development of the front and back end separation blog project complete teaching

  • Full 200 – minute video tutorial: www.bilibili.com/video/BV1af…
  • Full development documentation: www.zhuawaba.com/post/17

If you have any questions, please come to my official account [Java Q&A Society] and ask me