业务中不少地方用到根据权重来抽奖的逻辑,封装出公用的逻辑。
@Service
public class GeneratePrizeByWeightService {
private static final Logger LOG = LoggerFactory.getLogger(GeneratePrizeByWeightService.class);
public String getReward(String rewardStr) {
if(StringUtils.isEmpty(rewardStr)) {
return "";
}
List<ActiveTaskConfValueDto> rewardList = JSON.parseArray(rewardStr, ActiveTaskConfValueDto.class);
if(rewardList == null || rewardList.size() == 0) {
return "";
}
return getRewardByWeight(rewardList);
}
public String getRewardByWeight(List<ActiveTaskConfValueDto> prizes) {
int random = -1;
try {
//计算总权重
double sumWeight = 0;
for (ActiveTaskConfValueDto prize : prizes) {
sumWeight += prize.getWeight();
}
//产生随机数
double randomNumber;
randomNumber = Math.random();
//根据随机数在所有奖品分布的区域并确定所抽奖品
double beginRange = 0;
double endRange = 0;
for (int i = 0; i < prizes.size(); i++) {
endRange += Double.parseDouble(String.valueOf(prizes.get(i).getWeight())) / sumWeight;
if (i == 0) {
beginRange = 0;
} else {
beginRange += Double.parseDouble(String.valueOf(prizes.get(i - 1).getWeight())) / sumWeight;
}
if (randomNumber >= beginRange && randomNumber <= endRange) {
random = i;
break;
}
}
} catch (Exception e) {
LOG.info("[GeneratePrizeByWeightService.getRewardByWeight] 根据权重获取奖励异常,e:{}", e);
return "";
}
return prizes.get(random).getRpCode();
}
}
public class ActiveTaskConfValueDto {
private String rpCode;
private int weight;
public String getRpCode() {
return rpCode;
}
public void setRpCode(String rpCode) {
this.rpCode = rpCode;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
测试数据
{ "memberId" : "123", "prizesConfig" : "[{\"rpCode\":\"HYYXJ_tongyong_10\",\"weight\":40},{\"rpCode\":\"HYYXJ_dianyin_10\",\"weight\":20},{\"rpCode\":\"HYYXJ_huafei_10\",\"weight\":20},{\"rpCode\":\"HYYXJ_yingyin_10\",\"weight\":20}]" }