zoukankan      html  css  js  c++  java
  • 抽奖活动 mark


    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());
    }
    }
  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/xmanblue/p/9849584.html
Copyright © 2011-2022 走看看