多件商品根据概率抽奖

  最近在项目中分配了一个抽奖模块的任务,这里先说一下需求把:每个抽奖活动后台会配置多个中奖奖品,分为特殊奖品和普通奖品,所有奖品的中奖概率之和加起来为1。用户端用户抽奖需要根据概率来随机抽中一个商品。开始我脑子生出来的第一想法是生成一个随机数,然后让这个随机数跟概率去比较,取小于这个随机数的最大一个概率对应的商品为中奖商品,后来一想,发现自己想的太简单直观了,这样抽中的商品中奖概率不满足配置的中奖概率。在网上搜了一下相关的问题,然后就弄清楚了。说来惭愧,这么一个简单的算法题,自己竟然第一时间没有没有想到。所以在这里把这个问题记录下来。

public class DrawGoodsDO implements Comparable<DrawGoodsDO>{

    //主键id
    private long id;
    //抽奖id
    private long drawId;
    //商品名称
    private String goodsName;
    //商品图片地址
    private String goodsImageUrl;
    //上架库存
    private int drawStock;
    //当前库存
    private int drawStockCur;
    //商品类型,1特殊商品,2普通商品
    private int goodsType;
    // 中奖概率
    private double drawRate;
    // 添加时间
    private Timestamp addTime;

    //商品图片地址,绝对路径
    private String goodsImageUrlFormat;

    /**
     * 商品图片地址,绝对路径
     *
     * @return GoodsImageUrlFormat the GoodsImageUrlFormat
     */
    public String getGoodsImageUrlFormat() {
        return goodsImageUrlFormat;
    }

    /**
     * 商品图片地址,绝对路径
     *
     * @param goodsImageUrlFormat the goodsImageUrlFormat to set
     */
    public void setGoodsImageUrlFormat(String goodsImageUrlFormat) {
        this.goodsImageUrlFormat = goodsImageUrlFormat;
    }

    //主键id
    public long getId() {
        return this.id;
    }

    //主键id
    public void setId(long id) {
        this.id = id;
    }

    //抽奖id
    public long getDrawId() {
        return this.drawId;
    }

    //抽奖id
    public void setDrawId(long drawId) {
        this.drawId = drawId;
    }

    //商品名称
    public String getGoodsName() {
        return this.goodsName;
    }

    //商品名称
    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    //商品图片地址
    public String getGoodsImageUrl() {
        return this.goodsImageUrl;
    }

    //商品图片地址
    public void setGoodsImageUrl(String goodsImageUrl) {
        if (goodsImageUrl != null) {
            setGoodsImageUrlFormat(FileUrlConfig.file_visit_url + goodsImageUrl);
        }
        this.goodsImageUrl = goodsImageUrl;
    }

    //上架库存
    public int getDrawStock() {
        return this.drawStock;
    }

    //上架库存
    public void setDrawStock(int drawStock) {
        this.drawStock = drawStock;
    }

    //当前库存
    public int getDrawStockCur() {
        return this.drawStockCur;
    }

    //当前库存
    public void setDrawStockCur(int drawStockCur) {
        this.drawStockCur = drawStockCur;
    }

    //商品类型,1特殊商品,2普通商品
    public int getGoodsType() {
        return this.goodsType;
    }

    //商品类型,1特殊商品,2普通商品
    public void setGoodsType(int goodsType) {
        this.goodsType = goodsType;
    }

    // 获取 中奖概率
    public double getDrawRate() {
        return this.drawRate;
    }

    // 设置 中奖概率
    public void setDrawRate(double drawRate) {
        this.drawRate = drawRate;
    }

    // 获取 添加时间
    public Timestamp getAddTime() {
        return this.addTime;
    }

    // 设置 添加时间
    public void setAddTime(Timestamp addTime) {
        this.addTime = addTime;
    }

    @Override
    public int compareTo(DrawGoodsDO drawGoods) {
        if (this.drawRate >= drawGoods.getDrawRate()) {
            return 1;
        }
        return -1;
    }
}

这个是抽奖奖品实体类,他实现了Comparable接口,实现了compareTo()方法,这个方法很重要,后面再说。

/**
     * 从抽奖奖品列表中随机抽中一个
     *
     * @param drawGoodsList 奖品列表
     * @return
     */
    private DrawGoodsDO randomGetDrawGoods(List<DrawGoodsDO> drawGoodsList) {
        if (ValidateUtil.isNull(drawGoodsList)) {
            return null;
        }
        //将奖品按概率从小到大排序
        Collections.sort(drawGoodsList);
        //求出总概率
        double sumRate = 0D;
        for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
            sumRate += drawGoodsDO.getDrawRate();
        }
        if (sumRate != 100) {
            //如果总概率之和不为100,重新计算他们的概率,让他们的概率和为100
            for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
                drawGoodsDO.setDrawRate(drawGoodsDO.getDrawRate() * 100 / sumRate);
            }
        }

        //将每个奖品中奖区间段保存到list里面
        List<Double> list = new ArrayList<>();
        double rate = 0D;
        for (DrawGoodsDO drawGoodsDO : drawGoodsList) {
            rate += drawGoodsDO.getDrawRate() / sumRate;
            list.add(rate);
        }
        //找出符合概率得奖品所占的索引位置
        int index = 0;
        double randomNum = Math.random();
        for (int i=0;i<list.size();i++) {
            if (randomNum > list.get(i)) {
                index = i + 1;
            }
        }
        return drawGoodsList.get(index);
    }

上面就是主要的实现方法,这里最重要的就是先将奖品列表按照概率从小到大排序,因为Collections.sort()方法需要列表元素实现Comparable接口。所以上面的实体类中才那样写。然后根据中奖概率算出中奖区间段并且保存到list中,最后在生成一个随机数与这个中间区间段的list来比较,最后选中奖品。

原文地址:https://www.cnblogs.com/xslzjbra/p/10037304.html

时间: 2024-07-29 12:05:42

多件商品根据概率抽奖的相关文章

如何给一件商品定价?

本人大学狗,之前社团做一个公益项目,进了一批原材料后来做成产品后发现大家都不知道如何定价(或者说如何对产品定价才能吸引顾客的注意并诱发他们的消费欲望).之后我也对这个问题产生过疑问,求助了知乎.百度知道,发现都找不到一个比较系统的理论,挺郁闷的.直到买了微博上关注的黄成明老师@数据化管理 新出的一本书<数据化管理-洞悉零售及电子商务运营>,意外地看到他的关于商品定价的策略,感觉很系统化.很多干货,故摘抄其中一点写在这个回答上(强烈推荐大家去购买这本书,尤其是将来从事快消行业的童鞋,真是获益匪浅

前端+php实现概率抽奖

转前端之后,后台工程师大大跑路了只能兼任他的位置写点东西了 前端+后台抽奖代码网上一大堆,引用一位仁兄前面的代码(比较懒抱歉,后面数据处理,奖项判断是否抽完我将会标红,因为前面的代码网上太多了都能找到) 引用部分-start---------------------> 准备工作 首先要准备素材,抽奖的界面用到两张图片,圆盘图片和指针图片,实际应用中可以根据不同的需求制作不同的圆盘图片. 接着制作html页面,实例中我们在body中加入如下代码: <div class="demo&qu

ecshop二次开发 购物时为每件商品添加备注信息的修改方法

目标: 用户在选购商品加入购物车前可以为商品添加备注信息 加入购物车后可以在购物车查看备注信息 店主在查看订单时可以看到用户为商品添加的备注信息 用户在个人中心中可以看到商品的备注信息 目标一: 打开ecshop/goods.php,搜索"display"可以看到这句: $smarty->display('goods.dwt', $cache_id); 打开模板目录下的goods.dwt,搜索"<!-- {* 结束循环可选属性 *} -->",在这

php商城秒杀,可以购买多件商品,redis防高并发

<?php header('content-type:text/html;charset=utf-8');echo time();class SeckillRedis { static protected $validity_time = 30; // 有效期 5分钟 protected $goods_id; protected $user_queue_key; protected $goods_number_key; protected $user_id; public function __

关于买家买入一件商品以后需要进行的逻辑

public OrderDTO create(OrderDTO orderDTO) { String orderId = KeyUtil.genUniqueKey(); BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO); //1.查询商品(数量,价格) for (OrderDetail orderDetail : orderDTO.getOrderDetailList()) { ProductInfo productInfo = p

概率抽奖

[TestMethod] public void CheckTrue() { var reg = CommonTools.CheckTrue(1.001M); } /// <summary> /// 根据中奖率判断是否中奖 /// </summary> /// <param name="percent">中奖率(0~100)</param> /// <returns></returns> public static

不同概率的抽奖

今天为大家写个小程序. 工作中有遇到一些抽奖的活动,但是你懂得,抽奖物品的概率肯定不是一样,你会发现好的东西很难抽到,经常抽到一些垃圾的东西,嘿嘿,这就是本文要说的,我们要控制抽奖物品的概率.还有顺便说一句,网上这种小程序几乎没有,很多都是等概率的抽奖balabala- 需求很简单,为了更加形象,这里我们列一个表格来显示我们抽奖的物品和对应的概率(没有边框,大家凑合着看看吧,不想改造Octopress的样式了) 序号 物品名称 物品ID 抽奖概率 1 物品1 P1 0.2 2 物品2 P2 0.

javascript抽奖插件+概率计算

写了一个抽奖的jquery插件和计算概率的方法, 结合起来就是一个简单的概率抽奖, 不过实际项目中基本不会把抽奖概率的计算放在前端处理~. 概率计算 function Probability(conf) { this.probArr = conf || []; this.range = [], this.len = this.probArr.length; if (this.len > 0) { this.init(); } } Probability.prototype = { init: f

电商商品秒杀系统架构分析与实战

网址:http://my.oschina.net/xianggao/blog/524943 0 系列目录 1 秒杀业务分析 2 秒杀技术挑战 3 秒杀架构原则 4 秒杀架构设计 4.1 前端层设计 4.2 站点层设计 4.3 服务层设计 4.4 数据库设计 4.4.1 基本概念 4.4.2 设计思路 5 大并发带来的挑战 5.1 请求接口的合理设计 5.2 高并发的挑战:一定要“快” 5.3 重启与过载保护 6 作弊的手段:进攻与防守 6.1 同一个账号,一次性发出多个请求 6.2 多个账号,一