import lombok.extern.slf4j.
Slf4j;import org.redisson.api.RBucket
;import org.redisson.api.RLock
;import org.redisson.api.RMapCache
;import org.redisson.api.RedissonClient
;import org.springframework.beans.factory.annotation.
Autowired;import org.springframework.stereotype.
Service;import java.math.BigDecimal
;import java.util.*
;import java.util.concurrent.TimeUnit
;import java.util.concurrent.atomic.AtomicInteger
;import java.util.stream.Collectors
;/** * LotteryActivityRedisService 描述 * 抽奖活动 * @author tomas * @create 2018/10/24 **/@Slf4j@Service(
"lotteryActivityRedisServiceImpl")
public class LotteryActivityRedisServiceImpl
extends ActivityRedisService
implements LotteryActivityRedisService {
@Autowired private RedissonClient
redissonClient; @Autowired private ActivityInfoMapper
mapper; /** * 初始化 活动信息 * @param activityCode * @return */ @Override public ResultModel
init(String activityCode){
try { ActivityModel activityInfo =
mapper.selectByCode(activityCode)
; if(
null!=activityInfo ){ RBucket<ActivityModel> activityBucket =
redissonClient.getBucket(String.
format(
ACTIVITY_KEY,activityCode))
; activityBucket.set(activityInfo)
; if(
new Date().after(activityInfo.getBeginTime())){
return ResultModel.
getError(
"非可初始化活动时间")
; }
//1.初始化奖品 String awardPoolMapKey = String.
format(
ACTIVITY_PRIZE_POOL_MAP_KEY,activityCode)
; Prize p1=Prize.
builder().id(
6).prizeName(
"30天免单券").prizeType(
"一等奖").prizeTotalNum(
6).remainingPrize(
6).prizeRate(
0.002).build()
; Prize p2=Prize.
builder().id(
7).prizeName(
"7天免单券").prizeType(
"二等奖").prizeTotalNum(
30).remainingPrize(
30).prizeRate(
0.01).build()
; Prize p3=Prize.
builder().id(
8).prizeName(
"7折优惠券").prizeType(
"三等奖").prizeTotalNum(
0).remainingPrize(
0).prizeRate(
0.9988).def(
true).build()
; //Prize p4=Prize.builder().id(0L).prizeName("谢谢参与").prizeType("一等奖").prizeTotalNum(100000000L).remainingPrize(100000000L).prizeRate(0.001).build(); List<Prize> list=
new ArrayList<>()
; list.add(p1)
; list.add(p2)
; list.add(p3)
; RMapCache<Integer
, Prize> mapCache =
redissonClient.getMapCache(awardPoolMapKey)
; for (
int i =
0; i < list.size()
; i++) {
//将奖项数据初始化到redis中 Prize p=list.get(i)
; mapCache.put(p.getId()
,p
,10, TimeUnit.
DAYS)
; }
//todo 多线程操作/异步操作 System.
out.println(
"数据加载完成")
; }
return ResultModel.
getSuccess(
"初始化活动成功")
; }
catch (Exception e){
log.error(
"init activity Error activityCode ={} msg={} ",activityCode
,e.getMessage())
; }
return ResultModel.
getError(
"初始化活动失败")
; }
/** * 根据 code 和 userId 检查用户参与活动情况 * @param model * @return */ public ResultModel
check(ActivityParamModel model){
return ResultModel.
getSuccess()
; }
/** * 参与抽奖 * @param model * @return */ public ResultModel
lottery(ActivityParamModel model){
/* 获取活动奖品列表 */ List<Prize> selectPrizeList =
new ArrayList<>()
; //获取可抽取的奖品及其的概率集合 Map<String
, Object> optionalAwardMap =
this.getAllAwardProbability(model.getCode())
; //获取可选的奖品集合 selectPrizeList = (List<Prize>) optionalAwardMap.get(
"selectPrizeList")
; //获取可选奖品集合的总概率 double probabilityTotal = (
double) optionalAwardMap.get(
"probabilityTotal")
; if (probabilityTotal <
1) {
//当中奖概率不等于100%时,补充默认奖品 selectPrizeList =
this.supplementDefaultAward( selectPrizeList
, probabilityTotal
, model.getCode())
; }
//生成抽奖用的概率集合 List<Double> probabilityResult =
this.generatorAwardProbability(selectPrizeList)
; if(probabilityResult.size()<=
0){
return ResultModel.
getError(
"没有可抽奖奖品")
; }
/* 实例化抽奖算法,并抽奖 */ AliasMethod aliasMethod =
new AliasMethod(probabilityResult)
; /* 开始抽奖 */ int index = aliasMethod.next()
; // 返回抽中奖品 Prize selectPrize = selectPrizeList.get(index)
; if (selectPrize !=
null) {
//判断是否是默认的奖品,不是默认奖品 需要 redis 减Remaining 数量 if (!selectPrize.isDef()) { String awardPoolMapKey = String.
format(
ACTIVITY_PRIZE_POOL_MAP_KEY,model.getCode())
; //默认返回数量为0 if (selectPrize.getRemainingPrize()!=
null && selectPrize.getRemainingPrize() >=
1 ) { RLock lock =
redissonClient.getLock(awardPoolMapKey.concat(String.
valueOf(selectPrize.getId())))
; lock.lock(
200, TimeUnit.
MILLISECONDS)
; selectPrize.setRemainingPrize(
new AtomicInteger(selectPrize.getRemainingPrize()).decrementAndGet())
; redissonClient.getMapCache(awardPoolMapKey).put(selectPrize.getId()
,selectPrize)
; lock.unlock()
; }
else {
return lottery(model)
; } }
//判断是否 是安慰奖 if(!selectPrize.isComfort()){ } }
return ResultModel.
getSuccess(selectPrize)
; }
/** * 分享功能 * @param model * @return */ public ResultModel
share(ActivityParamModel model){
return ResultModel.
getSuccess()
; }
/** * 结束 活动开关 * @param activityCode * @return */ public ResultModel
stop(String activityCode){
return ResultModel.
getSuccess()
; }
/** * @param selectAwardList 奖品选项 * @return * @Describe 生成奖品概率 */ private List<Double>
generatorAwardProbability(List<Prize> selectAwardList) { List<Double> prob =
new ArrayList<>()
; try {
/* 遍历所有奖品,取得奖品概率生成随机算法计算规则 */ for (Prize prize : selectAwardList) {
double rate =prize.getPrizeRate().doubleValue()
; prob.add(rate)
; }
return prob
; }
catch (Exception e) {
log.error(e.getMessage())
; return new ArrayList<>()
; } }
/** * @param selectAwardList * @param probabilityTotal * @return * @Describe 补充默认的奖品 */ private List<Prize>
supplementDefaultAward(List<Prize> selectAwardList
, double probabilityTotal
,String activityCode) {
for (Prize prize : selectAwardList) {
if(prize.isDef()){ String awardPoolMapKey = String.
format(
ACTIVITY_PRIZE_POOL_MAP_KEY,activityCode)
; BigDecimal bigDecimal =
new BigDecimal(
1 - probabilityTotal)
; prize.setPrizeRate(prize.getPrizeRate()+bigDecimal.doubleValue())
; RLock lock =
redissonClient.getLock(awardPoolMapKey.concat(String.
valueOf(prize.getId())).concat(
"supply"))
; lock.lock(
200, TimeUnit.
MILLISECONDS)
; redissonClient.getMapCache(awardPoolMapKey).put(prize.getId()
,prize)
; lock.unlock()
; } }
return selectAwardList
; }
/** * @param activityCode 活动id * @return * @Describe 获取所有的奖品概率 */ private Map<String
, Object>
getAllAwardProbability(String activityCode) {
//返回的结果集 Map<String
, Object> result =
new HashMap<String
, Object>()
; /* 中奖率累计 */ double probabilityTotal =
0.0; /* 获取活动对应的奖品列表 */ List<Prize> prizeList =
this.getPrizeList(activityCode)
; List<Prize> selectPrizeList =
new ArrayList<>()
; /* 奖品结果集 */ for (Prize prize : prizeList) {
//查询奖品剩余的数量 //只有数量大于零 的奖品才能放到 selectPrizeList 中 if (
null!=prize && prize.getRemainingPrize() >
0) {
// 取出当前概率 double probability = prize.getPrizeRate()
; probabilityTotal += probability
; selectPrizeList.add(prize)
; }
else {
continue; } } result.put(
"probabilityTotal", probabilityTotal)
; result.put(
"selectPrizeList", selectPrizeList)
; return result
; }
/** * @Describe 获取活动对应的奖品列表 * @param activityCode * @return List<
Prize>
*/ private List<Prize>
getPrizeList(String activityCode) { String awardPoolMapKey = String.
format(
ACTIVITY_PRIZE_POOL_MAP_KEY,activityCode)
; RMapCache<Integer
, Prize> awardPoolMap =
redissonClient.getMapCache(awardPoolMapKey)
; return awardPoolMap.readAllValues().stream().collect(Collectors.
toList())
; }}
转载于:https://www.cnblogs.com/wangdaijun/p/9849584.html