欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java抽奖抢购算法

程序员文章站 2024-03-13 10:57:15
本文示例为大家分享了java抽奖抢购算法,供大家参考,具体内容如下 应用场景 单件奖品抢购(可限时) 多件奖品按概率中奖(可限时、可不限量) 代码实现 表结构:...

本文示例为大家分享了java抽奖抢购算法,供大家参考,具体内容如下

应用场景

单件奖品抢购(可限时)
多件奖品按概率中奖(可限时、可不限量)

代码实现

表结构:

--抽奖设置
create table award_info
(
 id     number(11) not null,
 act_id   number(11),  --活动id
 num    number(11),  --奖品总量(0为不限量)
 rest    number(11),  --奖品余量
 odds    number(11) default 0,  --中奖概率
 start_date date,     --开始日期(可为空)
 end_date  date,     --结束日期(可为空)
 product_id number(11),  --奖品id
 state   number(5) default 0,  --状态 0-有效 1-失效
 info_type number(5) default 0   --0-正常 
);
alter table award_info
 add constraint pk_award_info primary key (id);

--中奖纪录
create table award_log
(
 id     number(11),  
 act_id   number(11),  --活动id
 get_time  date,  --中奖时间
 product_id number(11),  --奖品id
 num    number(11) default 1,  --中奖数量
 person   varchar2(50),  --中奖人
 info_id  number(11),  --抽奖设置id
 state   number(5)  --状态 0-有效 1-失效
);
alter table award_log
 add constraint pk_award_log primary key (id);

代码:

  public static class awardresult{
    public int ret;  //返回结果
    public int logid; //award_log id
  }

  /**
   * 抽奖算法
   * @param actid 抽奖活动id
   * @param person 抽奖人
   * @param productid 奖品id -1则为该活动id下所有奖品
   * @param excludeid 排除奖品id -1 则不排除,与productid不能同时>0
   * @param checkdate 是否检查时间
   * @return -1 没有抽奖数据;-2 奖品已抽完; -3 其他错误;>=0 中奖productid; -4 排除id
   * @throws exception
   */
  public static awardresult getawardfull(int actid, string person, int productid, int[] excludeids, boolean checkdate) throws sqlexception{
    awardresult result = new awardresult(); 

    connection conn = jdbc.getconnection();
    conn.setautocommit(false);
    try{
      list<map<string,object>> rows;
      string sql;
      string checkdatestr = "";
      string basesql = "select t.id, t.product_id, t.num, t.rest, t.odds, t.info_type from award_info t where t.act_id=? and t.state=0 ";
      if(checkdate){
        checkdatestr = " and t.start_date <= sysdate and t.end_date >= sysdate ";
      }
      if(productid > 0){//抢购
        sql = basesql + " and t.product_id=? " + checkdatestr + " for update";
        rows = jdbc.getrows(sql, new object[]{actid, productid}, conn);
      }else{//活动所有物品抽奖
        sql = basesql + checkdatestr + " for update";
        rows = jdbc.getrows(sql, new object[]{actid}, conn);
      }

      if(rows.isempty()){//没有抽奖数据
        log.info("没有抽奖数据 actid={} person={} productid={} excludeids={} checkdate={}", actid, person, productid, excludeids, checkdate);
        conn.commit();
        result.ret = -1;
        return result;
      }
      int infoid = -1;
      int getproductid = -1;
      int num = -1;
      int rest = -1;
      if(rows.size() == 1){//抢购
        num = ((number)rows.get(0).get("num")).intvalue();
        rest = ((number)rows.get(0).get("rest")).intvalue();
        infoid = ((number)rows.get(0).get("id")).intvalue();
        getproductid = ((number)rows.get(0).get("product_id")).intvalue();
      }else{//抽奖
        int[][] temp = new int[rows.size()][3];
        int sum = -1;
        int i = 0;
        for(int k = 0; k < rows.size(); k++){//设置奖品池
          int odds = ((bigdecimal)rows.get(k).get("odds")).intvalue();
          sum++;
          temp[i][0] = sum; //起始值
          sum = sum + odds;
          temp[i][1] = sum; //结束值
          temp[i][2] = k;  //rows index
          i++;
        }
        //抽奖
        random random = new random();

        int r = random.nextint(sum + 1);
        int j = 0;
        for(int k = 0; k < i; k++){
          if(r >= temp[k][0] && r <= temp[k][1]){
            j = k;
            break;
          }
        }
        infoid = ((bigdecimal)rows.get(temp[j][2]).get("id")).intvalue();
        getproductid = ((bigdecimal)rows.get(temp[j][2]).get("product_id")).intvalue();
        num = ((number)rows.get(temp[j][2]).get("num")).intvalue();
        rest = ((number)rows.get(temp[j][2]).get("rest")).intvalue();
      }

      //判断是否排除id
      if(arrayutils.contains(excludeids, getproductid)){
        log.info("是排除id actid={} person={} productid={} excludeids={} checkdate={}", actid, person, productid, excludeids, checkdate);
        conn.commit();
        result.ret = -4;
        return result;
      }

      //存量不足
      if(num > 0 && rest <= 0){
        log.info("奖品已清空 actid={} person={} productid={} excludeids={} checkdate={}", actid, person, productid, excludeids, checkdate);
        jdbc.commit(conn);
        result.ret = -2;
        return result;
      }

      //更新奖品记录
      if(num > 0){//非不限量
        sql = "update award_info set rest = rest - 1 where id = ?";
        jdbc.update(sql, new object[]{infoid}, conn);
      }

      //记录获奖名单
      awardlog log = new awardlog();
      log.setactid(actid);
      log.setnum(1);
      log.setperson(person);
      log.setproductid(getproductid);
      log.setinfoid(infoid);
      number logid = log.save(conn);
      if(logid == null){
        throw new sqlexception("save award_log error");
      }
      result.logid = logid.intvalue();

      conn.commit();
      result.ret = getproductid;
      return result;

    }catch(sqlexception e){
      log.error("getaward error", e);
      conn.rollback();
    }finally{
      jdbc.close(conn);
    }
    result.ret = -3;
    return result;
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。