一、实现原理:
- 获取所有的奖品信息;
- 遍历奖品,获取每个奖品的中奖率,注意:所有的奖品中奖率加起来不能超过100,最小值为0.01;
- 根据奖品中奖率计算奖品中奖区间(区间+=中奖率 x 10000),注意:10000越大中奖率越精确;
- 设置随机数,控制在 (100 x 10000)内去生成,注意: 100乘的数和上面的中奖率乘的数一致;
- 循环区间集合,如果随机数在某个区间内,返回具体的奖品,因为计算的区间集合和奖品集合是一致的,
所以可以根据当前循环的次数找到对应的奖品集合中的奖品。 - 配合分布式锁更好用哦!
二、实现代码
/**
* @Title getLotteryPrize
* @Description 计算抽奖概率,并随机进行抽奖 概率算法:每个奖品的中奖率*10000 区间算法
* @author 刺风
* @param prizes 奖品列表集合对象
* @return LotteryPrizeEntity 中奖则返回奖品对象,未中奖或者奖品已被抽完则返回null
*/
private LotteryPrizeEntity getLotteryPrize(List<LotteryPrizeEntity> prizes) {
LotteryPrizeEntity lotteryPrizeEntity=null; //声明要返回的奖品对象
Long times = System.currentTimeMillis(); //获取当前时间
int totalPro = 0; //总的概率区间
//用于存储每个奖品新的概率区间
List<Integer> proSection = new ArrayList<Integer>();
proSection.add(0); //设置初始值
//遍历每个奖品,设置概率区间,总的概率区间为每个概率区间的总和
for (LotteryPrizeEntity p : prizes) {
//每个概率区间为奖品概率乘以10000(把概率放大一万倍)
totalPro += (p.getProbability() * 10000);
log.info("【用户抽奖】各个奖品区间值PrizeName:"+p.getPrizeName() + " totalPro:" + totalPro);
proSection.add(totalPro);
}
log.info(("【用户抽奖】奖品的总区间为 totalPro:" + totalPro));
if (totalPro == 0) {
return null;
}
//获取总的概率区间中的随机数
Random random = new Random();
int randomPro = random.nextInt(100*10000);//获取100万内随机产生的数
//判断取到的随机数在哪个奖品的概率区间中
log.info("【用户抽奖】 本次获取区间随机数为:" + randomPro);
int count= (proSection.size()- 1);
for (int i = 0; i <count; i++) {
if (i ==count) {
if (randomPro >= proSection.get(i)) {
log.info("【用户抽奖】 获得的奖品为LotteryPrizeEntity:" + Jackson2Helper.toJsonString(prizes.get(i)));
lotteryPrizeEntity=prizes.get(i);
break;
}
} else {
if (randomPro >= proSection.get(i) && randomPro < proSection.get(i + 1)) {
log.info("【用户抽奖】 获得的奖品为LotteryPrizeEntity:" + Jackson2Helper.toJsonString(prizes.get(i)));
lotteryPrizeEntity=prizes.get(i);
break;
}
}
}
//验证奖品中奖数量是否大于奖品数量
if(Utils.isNotNull(lotteryPrizeEntity)){
//如果奖品总数-中奖数量-当前奖品 的结果大于0表示中奖数量未超出,可以返回奖品,否则
int num=lotteryPrizeEntity.getPrizeNum()-lotteryPrizeEntity.getLotteryNum()-1;
if(num>=0){
return lotteryPrizeEntity;
}else{
//奖品已被抽光
log.info("【用户抽奖】奖品已被抽光,返回空的奖品信息,按未中奖处理");
}
}else{
//如果超出实际奖品区间范围则表示未中奖
log.info("【用户抽奖】中奖概率计算,随机数为: "+randomPro+" 未在奖品区间内,未中奖");
}
return null;
}
贴一下LotteryPrizeEntity实体类(奖品实体类)的代码:
package com.wtoip.platform.porsche.entity.lottery;
import com.wtoip.platform.porsche.entity.BaseEntity;
import java.util.Date;
import java.util.List;
public class LotteryPrizeEntity extends BaseEntity {
//主键
private Integer id;
//奖品名称
private String prizeName;
//奖品类型
private String prizeType;
//奖品数量
private Integer prizeNum;
//中奖率
private Double probability;
//奖品图片地址
private String prizeUrl;
//创建时间
private Date createTime;
//修改时间
private Date updateTime;
//抽奖活动主键
private Integer lotteryInfoId;
//是否允许重复抽奖
private String prizeManyYn;
//中奖数量
private Integer lotteryNum;
//描述信息
private String description;
//奖品级别
private String prizeLevel;
//优惠券ID
private String couponId;
//位置排序
private String sortNum;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPrizeName() {
return prizeName;
}
public void setPrizeName(String prizeName) {
this.prizeName = prizeName == null ? null : prizeName.trim();
}
public String getPrizeType() {
return prizeType;
}
public void setPrizeType(String prizeType) {
this.prizeType = prizeType == null ? null : prizeType.trim();
}
public Integer getPrizeNum() {
return prizeNum;
}
public void setPrizeNum(Integer prizeNum) {
this.prizeNum = prizeNum;
}
public Double getProbability() {
return probability;
}
public void setProbability(Double probability) {
this.probability = probability;
}
public String getPrizeUrl() {
return prizeUrl;
}
public void setPrizeUrl(String prizeUrl) {
this.prizeUrl = prizeUrl == null ? null : prizeUrl.trim();
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getLotteryInfoId() {
return lotteryInfoId;
}
public void setLotteryInfoId(Integer lotteryInfoId) {
this.lotteryInfoId = lotteryInfoId;
}
public String getPrizeManyYn() {
return prizeManyYn;
}
public void setPrizeManyYn(String prizeManyYn) {
this.prizeManyYn = prizeManyYn == null ? null : prizeManyYn.trim();
}
public Integer getLotteryNum() {
return lotteryNum;
}
public void setLotteryNum(Integer lotteryNum) {
this.lotteryNum = lotteryNum;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
public String getPrizeLevel() {
return prizeLevel;
}
public void setPrizeLevel(String prizeLevel) {
this.prizeLevel = prizeLevel;
}
public String getCouponId() {
return couponId;
}
public void setCouponId(String couponId) {
this.couponId = couponId;
}
public String getSortNum() {
return sortNum;
}
public void setSortNum(String sortNum) {
this.sortNum = sortNum;
}
}
网友评论