本文示例為大家分享了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 --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; } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。