Java 实现根据权重设置抽奖概率

抽奖活动

package com.wamei.activity;

import com.wamei.common.ResourceUtils;
import com.wamei.entity.AppUser;
import com.wamei.entity.activity.LotteryAddress;
import com.wamei.entity.activity.LotteryPrize;
import com.wamei.entity.activity.LotteryRecord;
import com.wamei.entity.activity.LotteryWinRecord;
import com.wamei.service.AppUserService;
import com.wamei.service.BaseService;
import com.wamei.util.AjaxPostResponse;
import com.wamei.util.DateToolUtils;
import com.wamei.util.JsonResponseHelper;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 总统竞选抽奖活动 Controller.
 * @author qixuan.chen
 * @version 1.0
 */
@Controller
@RequestMapping({"/activity/lotteryController"})
public class LotteryController extends AbstractController{

    private final static Logger logger = Logger.getLogger(LotteryController.class);

    private static String smsUrl = ResourceUtils.getValue("sms.httpUrl");

    public static String pathUrl = ResourceUtils.getValue("sign.path");

    public final static String ECID = "100148";
    public final static String ECKEY = "3O9oOAuGZ0k=dMMSmPTJUUI=";

    @Resource(name = "lotteryPrizeManager")
    private BaseService<LotteryPrize> lotteryPrizeSrv;

    @Resource(name = "lotteryRecordManager")
    private BaseService<LotteryRecord> lotteryRecordSrv;

    @Resource(name = "lotteryWinRecordManager")
    private BaseService<LotteryWinRecord> lotteryWinRecordSrv;

    @Resource(name = "lotteryAddressManager")
    private BaseService<LotteryAddress> lotteryAddressSrv;

    @Resource(name="appUserManager")
    private AppUserService appUserSrv;

    private static Cache validCodeCache;
    static{
        if (validCodeCache == null) {
            validCodeCache = CacheManager.getInstance().getCache("govDataCache");
        }
    }

    /**
     * 主页视图
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/main", method ={RequestMethod.GET,RequestMethod.POST})
    public ModelAndView lotteryMain(HttpServletRequest request) throws Exception {
        ModelAndView mav = new ModelAndView("pages/activity/lottery/lottery");
        String token = ServletRequestUtils.getStringParameter(request, "token", "");//用户ID

        String loMark = "no";
        if(StringUtils.isNotEmpty(token)){
            AppUser user = appUserSrv.find(token);
            if(null!=user){
                //当天是否已参与过
                String lrHql = " from LotteryRecord t where user.id=? and t.createTime>= ? and t.createTime <= ? ";
                List<Object> param = new ArrayList<Object>();
                Date startTime = DateToolUtils.getTodayStart();
                Date endTime = DateToolUtils.getTodayEnd();
                param.add(user.getId());
                param.add(startTime);
                param.add(endTime);
                List<LotteryRecord> lrList = lotteryRecordSrv.list(lrHql,param.toArray());
                if(null!=lrList && lrList.size()>0){
                    loMark = "yes";
                }
                mav.addObject("token",user.getId());

            }
        }

        mav.addObject("loMark",loMark);
        //追加投票数
        String id = "1005";
        LotteryPrize mo = lotteryPrizeSrv.find(id);
        String time = String.valueOf(System.currentTimeMillis());
        String pr = time.substring(time.length()-1,time.length());
        //利用时间戳最后一位来设置投票互斥事件
        String[] p2={"1","3","5","7","9"};
        int  lpCount = mo.getNum();
        float mkCount = mo.getPrice();
        if(Arrays.asList(p2).contains(pr)){
            mo.setNum(lpCount+1);
        }else{
            mo.setPrice(mkCount+1);
        }
        lotteryPrizeSrv.update(mo);

        //奖品列表
        String hql = " from LotteryPrize t where t.status=1 ";
        List<LotteryPrize> list = lotteryPrizeSrv.list(hql,null);
        mav.addObject("prizeList",list);
        mav.addObject("lpCount",lpCount);
        mav.addObject("mkCount",(int)mkCount);

        return mav;
    }

    /**
     * 抽奖
     * @param request
     */
    @RequestMapping(value = "/getprize", method={RequestMethod.POST,RequestMethod.GET})
    public synchronized ResponseEntity<AjaxPostResponse> getprizesetting(HttpServletRequest request){
        String token = ServletRequestUtils.getStringParameter(request, "token", "");//用户ID
        try {
            int result = 5;
            int status = 0;
            if(StringUtils.isNotEmpty(token)){
                AppUser user = appUserSrv.find(token);
                if (null != user) {
                    synchronized(this) {
                        //每天只能抽一次奖
                        String lrHql = " from LotteryRecord t where user.id=? and t.createTime>= ? and t.createTime <= ? ";
                        List<Object> param = new ArrayList<Object>();
                        Date startTime = DateToolUtils.getTodayStart();
                        Date endTime = DateToolUtils.getTodayEnd();
                        param.add(user.getId());
                        param.add(startTime);
                        param.add(endTime);
                        List<LotteryRecord> lrList = lotteryRecordSrv.list(lrHql,param.toArray());
                        if(null!=lrList && lrList.size()>0){
                            return this.errorResponse("");
                        }else{
//                            //IP限制(每个IP一天一次)
//                            String ipHql = " from LotteryRecord t where userIp=? and t.createTime>= ? and t.createTime <= ? ";
//                            List<Object> ipParam = new ArrayList<Object>();
//                            ipParam.add(this.getIPAddress(request));
//                            ipParam.add(startTime);
//                            ipParam.add(endTime);
//                            List<LotteryRecord> ipList = lotteryRecordSrv.list(ipHql,ipParam.toArray());
//                            if(null!=ipList && ipList.size()>0){
//                                return this.errorResponse("手气不佳,明天再来!");
//                            }

                            //添加抽奖记录
                            LotteryRecord lotteryRecord = new LotteryRecord();
                            lotteryRecord.setUser(user);
                            lotteryRecord.setCreateTime(new Date());
                            lotteryRecord.setUserIp(this.getIPAddress(request));
                            lotteryRecord.setStatus(status);
                            lotteryRecordSrv.create(lotteryRecord);

                            //已经中过一次的用户,不能在中
                            String lwrHql = " from LotteryWinRecord t where user.id=? ";
                            List<Object> lwrParam = new ArrayList<Object>();
                            lwrParam.add(user.getId());
                            List<LotteryWinRecord> lwrList = lotteryWinRecordSrv.list(lwrHql,lwrParam.toArray());
                            if(null!=lwrList && lwrList.size()>0){
                                return this.errorResponse("手气不佳,明天再来!");
                            }

                            String time = String.valueOf(System.currentTimeMillis());
                            String pr = time.substring(time.length()-1,time.length());
                            Integer[] data = {2,4,6,8};//奖品参数
                            //利用时间戳最后一位来设置外层概率,互斥事件
                            //String[] p2={"0","1","2","3","4","5","6","7","8","9"};
                            String[] p2={"1","3","5","8"};
                            if(Arrays.asList(p2).contains(pr)){
                                //进行抽奖
                                List<LotteryPrize> prizeList = lotteryPrizeSrv.list();
                                result = getPrizeIndex(prizeList);
                                LotteryPrize prize = prizeList.get(result);
                                String prizeName = "";
                                if(null!=prize){
                                    //中奖了
                                    String msg = "手气不佳,明天再来!";
                                    if("1001".equals(prize.getId())){
                                        msg = "1台"+prize.getPrizename();
                                        prizeName = prize.getPrizename();
                                    }else if("1002".equals(prize.getId())){
                                        msg = "1台"+prize.getPrizename();
                                        prizeName = prize.getPrizename();
                                    }else if("1003".equals(prize.getId())){
                                        msg = "1张"+prize.getPrizename();
                                        prizeName = "价值"+prize.getPrice()+"元的"+prize.getPrizename();
                                    }else if("1004".equals(prize.getId())){
                                        msg = "1张"+prize.getPrizename();
                                        prizeName = "价值"+prize.getPrice()+"元的"+prize.getPrizename();
                                    }else{
                                        return this.errorResponse(msg);//手气不佳
                                    }

                                    if(prize.getNum()>=1){
                                        prize.setNum(prize.getNum()-1);
                                        lotteryPrizeSrv.update(prize);//更新剩余量
                                        status = 1;
                                        //添加中奖记录
                                        LotteryWinRecord winRecord = new LotteryWinRecord();
                                        winRecord.setUser(user);
                                        winRecord.setPrizeId(prize.getId());
                                        winRecord.setImgsrc(prize.getImgsrc());//奖品图片
                                        winRecord.setPrizename(prizeName);//奖品名称
                                        winRecord.setCreateTime(new Date());
                                        winRecord.setUserIp(this.getIPAddress(request));
                                        winRecord.setStatus(status);
                                        lotteryWinRecordSrv.create(winRecord);
                                        return this.okResponse(msg);
                                    }
                                }
                            }else{
                                return this.errorResponse("手气不佳,明天再来!");
                            }
                        }
                    }
                }else{
                    return this.errorResponse("不存在该用户!");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return this.errorResponse("手气不佳,明天再来!");
        }

        return this.errorResponse("手气不佳,明天再来!");
    }


    /**
     * 我的奖品记录
     * @param request
     * @param response
     */
    @RequestMapping(value = "/myprizes", method={RequestMethod.POST,RequestMethod.GET})
    public @ResponseBody void myprizesRecord(HttpServletRequest request, HttpServletResponse response){
        String token = ServletRequestUtils.getStringParameter(request, "token", "");//用户ID
        StringBuffer sb = new StringBuffer();
        String result = "";
        try {
            if(StringUtils.isNotEmpty(token)) {
                AppUser user = appUserSrv.find(token);
                if (null != user) {
                    String hql = " from LotteryWinRecord t where user.id=? ";
                    List<Object> paramValues = new ArrayList<Object>();
                    paramValues.add(token);
                    List<LotteryWinRecord> lotteryWinRecords = lotteryWinRecordSrv.list(hql, paramValues.toArray());
                    result = JsonResponseHelper.toJson(lotteryWinRecords).toString();
                }
            }
            sb.append("{\"statusCode\":\"1\", \"msg\":\"\", \"errorCode\":\"\", \"result\":{\"data\":" + result + "}}");
        } catch (Exception e) {
            e.printStackTrace();
            sb.append("{\"statusCode\":\"0\", \"msg\":\"获取失败!\", \"errorCode\":\"\", \"result\":{}}");
        }
        JsonResponseHelper.renderText(sb.toString(), response);
    }

    /**
     * 获取奖品快递地址信息
     * @param request
     */
    @RequestMapping(value = "/getAddress", method={RequestMethod.POST})
    public ResponseEntity<AjaxPostResponse> getAddress(HttpServletRequest request){
        String token = ServletRequestUtils.getStringParameter(request, "token", "");//用户ID

        try {
            if(StringUtils.isBlank(token)){
                return this.errorResponse("请先登录!");
            }

            if(StringUtils.isNotEmpty(token)){
                AppUser user = appUserSrv.find(token);
                if (null != user) {
                    String hql = " from LotteryAddress t where user.id=? ";
                    List<Object> paramValues = new ArrayList<Object>();
                    paramValues.add(token);
                    List<LotteryAddress> list = lotteryAddressSrv.list(hql,paramValues.toArray());
                    if(null!=list && list.size()>0){
                        return this.okResponse(list.get(0));
                    }else{
                        return this.okResponse("");
                    }
                }else{
                    return this.errorResponse("请先登录!");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.errorResponse("获取失败!");
    }

    /**
     * 保存奖品快递地址信息
     * @param request
     */
    @RequestMapping(value = "/address", method={RequestMethod.POST})
    public ResponseEntity<AjaxPostResponse> saveAddress(HttpServletRequest request){
        String token = ServletRequestUtils.getStringParameter(request, "token", "");//用户ID
        String truename = ServletRequestUtils.getStringParameter(request, "truename", "");//真实姓名
        String telPhone = ServletRequestUtils.getStringParameter(request, "mobile", "");//联系方式
        String city = ServletRequestUtils.getStringParameter(request, "city", "");//区域
        String street = ServletRequestUtils.getStringParameter(request, "street", "");//街道
        String address = ServletRequestUtils.getStringParameter(request, "address", "");//地址

        try {
            if(StringUtils.isBlank(token)){
                return this.errorResponse("请先登录!");
            }
            if(StringUtils.isBlank(truename)){
                return this.errorResponse("请输入真实姓名!");
            }
            if(StringUtils.isBlank(telPhone)){
                return this.errorResponse("请输入联系方式!");
            }
            Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
            Matcher m = p.matcher(telPhone);
            if (false == m.matches()) {
                return this.errorResponse("手机号格式不正确");
            }
            if(StringUtils.isBlank(city)){
                return this.errorResponse("请输入区域地址!");
            }
            if(StringUtils.isBlank(street)){
                return this.errorResponse("请输入街道地址!");
            }
            if(StringUtils.isNotEmpty(token)){
                AppUser user = appUserSrv.find(token);
                if (null != user) {
                    String hql = " from LotteryAddress t where user.id=? ";
                    List<Object> paramValues = new ArrayList<Object>();
                    paramValues.add(token);
                    List<LotteryAddress> list = lotteryAddressSrv.list(hql,paramValues.toArray());
                    LotteryAddress mo = new LotteryAddress();
                    mo.setUser(user);
                    mo.setTruename(truename);
                    mo.setTelPhone(telPhone);
                    mo.setCity(city);
                    mo.setStreet(street);
                    mo.setPrizeId("");
                    mo.setAddress(address);
                    if(null!=list && list.size()>0){
                        mo.setId(list.get(0).getId());
                        mo.setCreateTime(list.get(0).getCreateTime());
                        lotteryAddressSrv.update(mo);
                    }else{
                        mo.setCreateTime(new Date());
                        lotteryAddressSrv.create(mo);
                    }
                    logger.info("userId="+token+",地址保存成功");
                    return this.okResponse("保存成功!");
                }else{
                    return this.errorResponse("请先登录!");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.errorResponse("保存失败!");
    }


    /**
     * 根据Math.random()产生一个double型的随机数,判断每个奖品出现的概率
     * @param prizes
     * @return random:奖品列表prizes中的序列(prizes中的第random个就是抽中的奖品)
     */
    public int getPrizeIndex(List<LotteryPrize> prizes) {
        DecimalFormat df = new DecimalFormat("######0.00");
        int random = -1;
        try{
            //计算总权重
            double sumWeight = 0;
            for(LotteryPrize p : prizes){
                sumWeight += p.getPrizeWeight();
            }

            //产生随机数
            double randomNumber;
            randomNumber = Math.random();

            //根据随机数在所有奖品分布的区域并确定所抽奖品
            double d1 = 0;
            double d2 = 0;
            for(int i=0;i<prizes.size();i++){
                d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrizeWeight()))/sumWeight;
                if(i==0){
                    d1 = 0;
                }else{
                    d1 +=Double.parseDouble(String.valueOf(prizes.get(i-1).getPrizeWeight()))/sumWeight;
                }
                if(randomNumber >= d1 && randomNumber <= d2){
                    random = i;
                    break;
                }
            }
        }catch(Exception e){
            random =-1;
            logger.info("生成抽奖随机数出错,出错原因:" +e.getMessage());
        }
        return random;
    }


    /**
     * 测试
     * @param args
     */
    public static void main(String args[]){

        int i = 0;
        int[] result=new int[5];
        List<LotteryPrize> prizes = new ArrayList<LotteryPrize>();

        LotteryPrize p1 = new LotteryPrize();
        p1.setPrizename("iPhone7");
        p1.setPrizeWeight(0);//奖品的权重设置成1
        prizes.add(p1);

        LotteryPrize p2 = new LotteryPrize();
        p2.setPrizename("扫地机器人");
        p2.setPrizeWeight(0);//奖品的权重设置成2
        prizes.add(p2);
        LotteryPrize p3 = new LotteryPrize();
        p3.setPrizename("充电宝");
        p3.setPrizeWeight(3);//奖品的权重设置成3
        prizes.add(p3);

        LotteryPrize p4 = new LotteryPrize();
        p4.setPrizename("京东电子卡");
        p4.setPrizeWeight(4);//奖品的权重设置成4
        prizes.add(p4);

        LotteryPrize p5 = new LotteryPrize();
        p5.setPrizename("手气不佳");
        p5.setPrizeWeight(100000);//奖品的权重设置成4
        prizes.add(p5);


        LotteryController a1 = new LotteryController();
        //Thread t1 = new Thread(a1);
        System.out.println("抽奖开始");
        for (i = 0; i < 10000; i++)// 打印100个测试概率的准确性
        {
            int selected=a1.getPrizeIndex(prizes);
            System.out.println("第"+i+"次抽中的奖品为:"+prizes.get(selected).getPrizename() +"=========="+selected);
            result[selected]++;
            System.out.println("--------------------------------");
        }


        System.out.println("抽奖结束");
        System.out.println("每种奖品抽到的数量为:");
        System.out.println("一等奖:"+result[0]);
        System.out.println("二等奖:"+result[1]);
        System.out.println("三等奖:"+result[2]);
        System.out.println("四等奖:"+result[3]);
        System.out.println("无等奖:"+result[4]);

    }

}



  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值