本文示例为大家分享了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;
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。