Java抽選実現
19237 ワード
1概要
プロジェクト開発では抽選というマーケティング活動のニーズがよくあります.例えば、積分大回転盤、刮刮楽、トラ機など多くの形式がありますが、実際にはバックグラウンドの実現方法は同じで、本稿ではよく使われる抽選の実現方法を紹介します.
全体の抽選過程には以下のいくつかの面が含まれています.賞品 賞品プール 抽選アルゴリズム 賞品制限 賞品発行 2賞品
賞品には、賞品、賞品確率、制限、賞品記録が含まれます.賞品表:
賞品確率制限表:
賞品記録表:
3賞品プール
賞品プールは賞品の確率と制限によって組み立てられた抽選用のプールです.主に賞品の合計プール値と各賞品が占めるプール値(開始値と終了値に分けられる)の2つの次元が含まれます.賞品の合計プール値:すべての賞品プール値の合計. 各賞品のプール値:アルゴリズムは融通可能で、よく使われるのは以下の2つの方法があります. 賞品の確率*10000(保証は整数) 賞品の確率10000賞品の残り数
賞品プールbean:
池の賞品bean:
賞品プールの組立コード:
4抽選アルゴリズム
抽選アルゴリズム全体は次のとおりです.
抽選コード:
5賞品制限
実際の抽選では、ある賞品には数の制限があることが多い.例えば、ある賞品は1日に最大5回、ある賞品はユーザー1人に1回しか抽選できない.このような制限については、2つの状況に分けて区別します.
6賞品支給
賞品発行は工場モードで発行することができる:異なる賞品タイプは異なる賞品発行プロセッサを歩き、サンプルコードは以下の通りである:賞品発行:
工場クラス:
賞品配布類の例:
プロジェクト開発では抽選というマーケティング活動のニーズがよくあります.例えば、積分大回転盤、刮刮楽、トラ機など多くの形式がありますが、実際にはバックグラウンドの実現方法は同じで、本稿ではよく使われる抽選の実現方法を紹介します.
全体の抽選過程には以下のいくつかの面が含まれています.
賞品には、賞品、賞品確率、制限、賞品記録が含まれます.賞品表:
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 ' 1: 2: 3: 4: 5: ',
`status` tinyint(4) DEFAULT NULL COMMENT ' ',
`is_del` bit(1) DEFAULT NULL COMMENT ' ',
`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=' ';
賞品確率制限表:
CREATE TABLE `points_luck_draw_probability` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`points_prize_id` bigint(20) DEFAULT NULL COMMENT ' ID',
`points_prize_phase` int(10) DEFAULT NULL COMMENT ' ',
`probability` float(4,2) DEFAULT NULL COMMENT ' ',
`frozen` int(11) DEFAULT NULL COMMENT ' ',
`prize_day_max_times` int(11) DEFAULT NULL COMMENT ' ',
`user_prize_month_max_times` int(11) DEFAULT NULL COMMENT ' ',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=114 DEFAULT CHARSET=utf8mb4 COMMENT=' ';
賞品記録表:
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 ' ',
`points` int(11) DEFAULT NULL COMMENT ' ',
`prize_id` bigint(20) DEFAULT NULL COMMENT ' ID',
`result` smallint(4) DEFAULT NULL COMMENT '1: 2: ',
`month` varchar(10) DEFAULT NULL COMMENT ' ',
`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=' ';
3賞品プール
賞品プールは賞品の確率と制限によって組み立てられた抽選用のプールです.主に賞品の合計プール値と各賞品が占めるプール値(開始値と終了値に分けられる)の2つの次元が含まれます.
賞品プールbean:
public class PrizePool implements Serializable{
/**
*
*/
private int total;
/**
*
*/
private List poolBeanList;
}
池の賞品bean:
public class PrizePoolBean implements Serializable{
/**
* ID
*/
private Long id;
/**
*
*/
private int begin;
/**
*
*/
private int end;
}
賞品プールの組立コード:
/**
*
* @param zillionaireProductMap map
* @param flag true: false:
* @return
*/
private PrizePool getZillionairePrizePool(Map zillionaireProductMap, boolean flag) {
//
int total = 0;
List poolBeanList = new ArrayList<>();
for(Entry entry : zillionaireProductMap.entrySet()){
ActivityProduct product = entry.getValue();
// ,
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;
}
4抽選アルゴリズム
抽選アルゴリズム全体は次のとおりです.
1.
2. , 。
抽選コード:
public static PrizePoolBean getPrize(PrizePool prizePool){
//
int total = prizePool.getTotal();
//
Random rand=new Random();
int random=rand.nextInt(total);
//
for(PrizePoolBean prizePoolBean : prizePool.getPoolBeanList()){
if(random >= prizePoolBean.getBengin() && random < prizePoolBean.getEnd()){
return prizePoolBean;
}
}
return null;
}
5賞品制限
実際の抽選では、ある賞品には数の制限があることが多い.例えば、ある賞品は1日に最大5回、ある賞品はユーザー1人に1回しか抽選できない.このような制限については、2つの状況に分けて区別します.
1. , 3 : , 。 , , 5 , 。
2. , , , , , 。
6賞品支給
賞品発行は工場モードで発行することができる:異なる賞品タイプは異なる賞品発行プロセッサを歩き、サンプルコードは以下の通りである:賞品発行:
/**
*
* @param prizeList
* @throws Exception
*/
@Async("myAsync")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public Future sendPrize(Long memberId, List prizeList){
try {
for(PrizeDto prizeDto : prizeList){
//
if(prizeDto.getType() == PointsLuckDrawTypeEnum.XXHG.getType()){
continue;
}
//
SendPrizeProcessor sendPrizeProcessor = sendPrizeProcessorFactory.getSendPrizeProcessor(
PointsLuckDrawTypeEnum.getPointsLuckDrawTypeEnumByType(prizeDto.getType()));
if(ObjectUtil.isNotNull(sendPrizeProcessor)){
//
sendPrizeProcessor.send(memberId, prizeDto);
}
}
return new AsyncResult<>(Boolean.TRUE);
}catch (Exception e){
//
saveSendPrizeErrorLog(memberId, prizeList);
LOGGER.error(" ", e);
return new AsyncResult<>(Boolean.FALSE);
}
}
工場クラス:
@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(" 【" + processorName + "】 ");
}
return processor;
}
}
賞品配布類の例:
/**
*
*/
@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 Exception {
//
Coupon coupon = couponService.receiveCoupon(memberId, Long.parseLong(prizeDto.getValue()));
//
messageLogService.insertActivityMessageLog(memberId,
" " + coupon.getAmount() + " , ",
" ");
// log
LOGGER.info(memberId + " " + prizeDto.getPrizeName() + " !");
}
}