思路:将每个都奖品的概率,加入一个数组,然后遍历数组,得到将随机数在的范围的奖品
因为前端值精确到 0.001%,所以存的值是加倍了的100000,换成整数来进行计算
public static final MAX_WINNING_PROBABILITY = 100000;
public static LuckyDrawAwardDoc draw(List<LuckyDrawAwardDoc> awardList){
int listSize = awardList.size();
if(awardList == null || listSize <1){ //没有设置奖品
return null;
}
//遍历奖品集合,计算区间最右值,存入int 数组中
int interval[] = new int[listSize+1];
for(int i=0;i <= listSize;i++){
if(i == 0){
Integer weight = awardList.get(i).getWinningProbability();
interval[0] = weight;
}else if(i < listSize){
Integer weight = awardList.get(i).getWinningProbability();
Integer lastAwardWeight = interval[i-1];
//区间最右的数是上一个 区间最右+自己的权重
interval[i] = weight + lastAwardWeight;
}else if(i == listSize){ //最后一个未中奖,因为数组下标从0开始
interval[i] = MAX_WINNING_PROBABILITY;
}
}
//random int 获取随机值
int maxInterval = interval[listSize-1];
Random random = new Random();
int ranVal = random.nextInt(MAX_WINNING_PROBABILITY);
//遍历int数组,找到随机值是位于哪个区间
for (int i = 0; i < interval.length; i++) {
if (i < interval.length-2 && ranVal >= interval[i] && ranVal < interval[i + 1] && ranVal < interval[interval.length-2]){
return awardList.get(i + 1);
}else if (i == 0 && ranVal < interval[0]){
// 第一个区间之内
return awardList.get(0);
}else if(ranVal >= interval[interval.length-2] && ranVal <= MAX_WINNING_PROBABILITY){ //未中奖情况
return null;
}
}
//抽奖异常
throw new LuckyDrawException(ErrorCode.DRAW_ERROR) ;
}