Java抽奖抢购算法

时间:2021-07-20 15:02:59

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

应用场景

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

代码实现

表结构:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--抽奖设置
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-正常
);
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);

代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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;
}

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