Java抽奖抢购算法

网友投稿 222 2023-07-10


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> 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=http://? " + 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={} checkDatehttp://={}", 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;

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:使用伪命名空间封装保护独自创建的对象方法
下一篇:Angular2内置指令NgFor和NgIf详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~