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;
  }

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

(0)

相关推荐

  • java数据结构与算法之双向循环队列的数组实现方法

    本文实例讲述了java数据结构与算法之双向循环队列的数组实现方法.分享给大家供大家参考,具体如下: 需要说明的是此算法我并没有测试过,这里给出的相当于伪代码的算法思想,所以只能用来作为参考! package source; public class Deque { private int maxSize; private int left; private int right; private int nItems; private long[] myDeque; //constructor p

  • Java抽奖算法第二例

    本文实例为大家分享了java抽奖算法,供大家参考,具体内容如下 1. 算法分析  根据概率将奖品划分区间,每个区间代表一个奖品,然后抽取随机数,反查落在那个区间上,即为所抽取的奖品. 2. 代码 核心算法 public class Arithmetic { // 放大倍数 private static final int mulriple = 1000000; public int pay(List<Prize> prizes) { int lastScope = 0; // 洗牌,打乱奖品次

  • java数据结构与算法之中缀表达式转为后缀表达式的方法

    本文实例讲述了java数据结构与算法之中缀表达式转为后缀表达式的方法.分享给大家供大家参考,具体如下: //stack public class StackX { private int top; private char[] stackArray; private int maxSize; //constructor public StackX(int maxSize){ this.maxSize = maxSize; this.top = -1; stackArray = new char[

  • java数据结构与算法之奇偶排序算法完整示例

    本文实例讲述了java数据结构与算法之奇偶排序算法.分享给大家供大家参考,具体如下: 算法思想: 基本思路是奇数列排一趟序,偶数列排一趟序,再奇数排,再偶数排,直到全部有序 举例吧, 待排数组[6 2 4 1 5 9] 第一次比较奇数列,奇数列与它的邻居偶数列比较,如6和2比,4和1比,5和9比 [6 2 4 1 5 9] 交换后变成 [2 6 1 4 5 9] 第二次比较偶数列,即6和1比,5和5比 [2 6 1 4 5 9] 交换后变成 [2 1 6 4 5 9] 第三趟又是奇数列,选择的是

  • 微信随机生成红包金额算法java版

    最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启发. public class WxAlgorithm{ /** * @param moneySum 输入总金额 * @param redNum 输入红包数量 */ private static void wxAlgorithm(double moneySum, int redNum) { // 设置最小的金额 double moneyMin = 0.01;

  • Java版本的回文字算法(java版本)

    废话不多说了,直接给大家贴代码了,具体代码如下所述: package com.gdh.backtext; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; public class BackText { String text; public BackText() { super(); this.text = null; } public BackText(String text) { supe

  • java实现的AES加密算法完整实例

    本文实例讲述了java实现的AES加密算法.分享给大家供大家参考,具体如下: import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import android.util.Base64; /** * @author vipin.cb , vipin.cb@experionglobal.com <br> * Sep 27, 2013

  • 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, --中奖概

  • Java实现双色球抽奖随机算法示例

    第一次写技术博客,写一下以前写的一个双色球抽奖随机算法. 原理如下: 1首先初始化一个待抽奖的数组nums,数组的长度k 2. 随机一个1-k之间的随机数,得到nums[k],这样得到第一个抽奖号,nums中剔除该号码,k--. 3. 重复步骤2,直到得到全部中奖号码 class myLuck { private int mTarget; List<Integer> mNums = new ArrayList<Integer>(); //摇奖池 ///从多少个数中产生多少个数 //

  • java数据结构与算法之快速排序详解

    本文实例讲述了java数据结构与算法之快速排序.分享给大家供大家参考,具体如下: 交换类排序的另一个方法,即快速排序. 快速排序:改变了冒泡排序中一次交换仅能消除一个逆序的局限性,是冒泡排序的一种改进:实现了一次交换可消除多个逆序.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 步骤: 1.从数列中挑出一个元素,称为 "基准"(piv

  • java数据结构排序算法之树形选择排序详解

    本文实例讲述了java数据结构排序算法之树形选择排序.分享给大家供大家参考,具体如下: 这里我们就来说说选择类排序之一的排序:树形选择排序 在简单选择排序中,每次的比较都没有用到上次比较的结果,所以比较操作的时间复杂度是O(N^2),想要降低比较的次数,则需要把比较过程中的大小关系保存下来.树形选择排序是对简单选择排序的改进. 树形选择排序:又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进

  • java实现Fibonacci算法实例

    本文实例讲述了java实现Fibonacci算法的方法.分享给大家供大家参考.具体如下: package com.yenange.test2; import java.util.Scanner; public class Fibonacci { private static Scanner input = new Scanner(System.in); public static void main(String[] args) { System.out.println("-----------

  • Java TreeMap排序算法实例

    本文实例讲述了Java TreeMap排序算法.分享给大家供大家参考,具体如下: TreeMap 和 HashMap 用法大致相同,但实际需求中,我们需要把一些数据进行排序: 以前在项目中,从数据库查询出来的数据放在List中,顺序都还是对的,但放在HashMap中,顺序就完全乱了. 为了处理排序的问题: 1. 对于一些简单的排序,如:数字,英文字母等 TreeMap hm = new TreeMap<String, String>(new Comparator() { public int

  • Java数据结构与算法之栈(Stack)实现详解

    本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型顺序栈的设计与实现链式栈的设计与实现栈的应用 栈的抽象数据类型   栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表),栈与线性表的最大区别是数据的存取的操作,我们可以这样认为栈(Stack)是一种特殊的线性表,其插入和删除操作只允许在线性表的一端进行,一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作

  • java数据结构与算法之插入排序详解

    本文实例讲述了java数据结构与算法之插入排序.分享给大家供大家参考,具体如下: 复习之余,就将数据结构中关于排序的这块知识点整理了一下,写下来是想与更多的人分享,最关键的是做一备份,为方便以后查阅. 排序 1.概念: 有n个记录的序列{R1,R2,.......,Rn}(此处注意:1,2,n 是下表序列,以下是相同的作用),其相应关键字的序列是{K1,K2,.........,Kn}.通过排序,要求找出当前下标序列1,2,......,n的一种排列p1,p2,........pn,使得相应关键

随机推荐