基于Java的抽奖逻辑

小组在做一个抽奖系统,现在给我分配到了抽奖逻辑这方面的实现。
EMMM,拿到分配的时候是懵B的。

老大给的需求图

给的关键表结构

DROP TABLE IF EXISTS `dd_annual_meeting_check`;
CREATE TABLE `dd_annual_meeting_check` (
  `check_id` int(255) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `check_prize_id` varchar(255) NOT NULL COMMENT '抽奖Id',
  `emp_id` int(10) NOT NULL COMMENT '中奖员工id',
  `emp_prize_time` varchar(255) NOT NULL COMMENT '中奖时间',
  `check_receive` varchar(100) NOT NULL COMMENT '核销 0-已经核销 1-未核销',
  `check_user_id` int(10) DEFAULT NULL COMMENT '核销工作人员(对于员工id)',
  `check_time` varchar(255) DEFAULT NULL COMMENT '核销时间',
  PRIMARY KEY (`check_id`)
) ENGINE=InnoDB AUTO_INCREMENT=158 DEFAULT CHARSET=utf8 COMMENT='中奖池信息表';

DROP TABLE IF EXISTS `dd_annual_meeting_prize`;
CREATE TABLE `dd_annual_meeting_prize` (
  `prize_id` varchar(255) NOT NULL COMMENT '主键',
  `prize_name` varchar(100) NOT NULL COMMENT '抽奖名称',
  `prize_num` varchar(100) NOT NULL COMMENT '抽奖总人数',
  `prize_count` varchar(100) NOT NULL COMMENT '每次中奖人数',
  `prize_range` varchar(100) DEFAULT NULL COMMENT '抽奖范围: 0-all 1-未中奖',
  `prize_state` varchar(100) DEFAULT NULL COMMENT '状态: 0-待抽 1-抽中 2-已抽',
  `prize_date` varchar(255) DEFAULT NULL COMMENT '状态时间',
  `leader_id` int(10) NOT NULL COMMENT '抽奖领导Id',
  `giver_id` int(10) DEFAULT NULL COMMENT '加奖人Id',
  `prize_detial` varchar(100) NOT NULL COMMENT '抽奖详情',
  `giver_state` varchar(255) DEFAULT '0' COMMENT '是否加奖 0-否 1-是',
  PRIMARY KEY (`prize_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='抽奖池信息表';

DROP TABLE IF EXISTS `dd_annual_meeting_user`;
CREATE TABLE `dd_annual_meeting_user` (
  `u_id` int(10) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(100) NOT NULL COMMENT '员工工号',
  `user_name` varchar(100) NOT NULL COMMENT '员工姓名',
  `user_time` varchar(255) DEFAULT NULL COMMENT '扫码时间',
  `user_type` varchar(100) DEFAULT NULL COMMENT '身份: 0-普通员工 1-领导 2-工作人员',
  `user_state` varchar(100) DEFAULT NULL COMMENT '状态: 1-已领取0-未领取',
  `state_date` varchar(255) DEFAULT NULL COMMENT '状态时间',
  `user_prize` varchar(255) NOT NULL COMMENT '奖票号',
  PRIMARY KEY (`u_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3423 DEFAULT CHARSET=utf8 COMMENT='人员信息表';

追加:

-- ----------------------------
-- Table structure for dd_annual_meeting_record
-- ----------------------------
DROP TABLE IF EXISTS `dd_annual_meeting_record`;
CREATE TABLE `dd_annual_meeting_record` (
  `record_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `record_prize_id` int(10) NOT NULL COMMENT '抽奖id',
  `record_times` int(10) NOT NULL COMMENT '第几轮',
  `record_over` int(10) NOT NULL COMMENT '剩余次数',
  `record_count` int(10) NOT NULL COMMENT '每次中奖数',
  `record_state` varchar(100) NOT NULL COMMENT '进行状态 0-未开始 1-已结束',
  PRIMARY KEY (`record_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of dd_annual_meeting_record
-- ----------------------------

没有多余讲解,就一句话,“需求是这样,怎样实现我不管。”这是老大的座右铭。
可我特么的是新手啊,难受啊,马飞!
好吧,其实是说业务流程和其他表结构并没有最终确定,先做个大概的抽奖逻辑出来,咱就按照表结构和自己的意思做一把思想上的巨人。

先从第一个开始(一二三等奖不能重复获得)

分析下表结构:

一共三张表,中奖池信息表dd_annual_meeting_check,这个比较容易理解,就是将得到的中奖人的id和奖 项id插入这张表。
抽奖池信息表dd_annual_meeting_prize,这张表看来是获取抽奖信息的来源。
人员信息表dd_annual_meeting_user,这个就是用来得到抽奖人集合的表了。

分析下抽奖的过程:
抽奖池信息表里面信息已经定好了不用我管 ,假设人员信息表有100个人参与活动。

  • 第一次抽奖(一等奖) 从100人中抽5个人来中奖,但是要分5次抽完,每次抽1人。

  • 第二次抽奖(二等奖)从95人(中了一次奖的人,不参与抽奖)中抽10个人来中奖,每次抽5人出来,要抽2次。

  • 第三次抽奖(二等奖)从85人(中了一次奖的人,不参与抽奖)中抽5个人来中奖,每次抽1人,抽5次。
    来个图:


    思路图

实现逻辑大致思路:

1.从人员信息表获得所有参与人员的数量

2.根据页面数据判断抽的什么奖励

3.从抽奖池信息表中获得抽奖主键id(prize_id),抽奖总人数(prize_num),每次中奖人数(prize_count),抽奖人领导id(leader_id)

4.进行抽奖,从人数中抽出对应的数字,根据数字去人员表中得到对应的人员信息

5.将中奖人信息与奖项信息绑定,添加到中奖池信息表

简单的分析后,有了大致思路,细节什么的就在代码中完成:

一,先弄两个页面出来,一个是显示中奖信息的页面,另外一个是发送抽奖指令的页面(因为是领导来点击抽奖,所以有一个领导信息需要发送过来)。
<html lang="en" xmlns:th="http://www.thymeleaf.org"> 
<head> 
<meta charset="UTF-8"/> 
<title>抽奖页面</title> 
<script src="http://how2j.cn/study/jquery.min.js">
</script> </head> <body> 
<div> 
    <div id="showData" name="showData"> 
        <p>奖品列表!!!!!!!!!!!!</p>
    </div> 
    <input type="hidden" name="poe" id="poe" />
</div> 
<script type="text/javascript">
var psel = document.getElementById("poe");  
 window.onload=function (){
     websocket = new WebSocket("ws://127.0.0.1:8080/websocket");
     websocket.onmessage = function(msg) {  
        console.log(msg.data);
        $.ajax({
            url:"test2",
            type:"POST",
            data:{
                msg:msg.data,
                peo:psel.value  
            },
           dataType : "json",
            success : function (rtn) {
               console.log("Successfully");
               console.log(rtn);
               if(rtn.list != null){
                  var inf = '<table class=table>';
                   inf += "<tr><th>获奖人id</th><th>获奖人姓名</th><th>获奖人奖券号</th></tr>"
                    /*<![CDATA[*/
                    for(var i=0; i<rtn.list.length;i++){
                    /*]]>*/
                    var stu = rtn.list[i];
                    inf += "<tr><td>"+stu.user_id+"</td><td>"+stu.user_name+"</td><td>"+stu.user_prize+"</td></tr>"
                    }   
                    inf += "</table>"   
                    $("#showData").html(inf); 
               }
               if(rtn.poe != null){
                  psel.value = rtn.poe; 
               }
             
            }
        });
     }
 }
</script> 
</body> 
</html>

//发送消息测试页面
<html lang="en" xmlns:th="http://www.thymeleaf.org"> 
<head> 
<meta charset="UTF-8"/> 
<title>发送消息测试页面</title> 
<script th:src="@{js/sockjs.min.js}">
</script> <script th:src="@{js/stomp.min.js}">
</script> <script src="http://how2j.cn/study/jquery.min.js"th:src="@{js/jquery/2.0.0/jquery.min.js}">
</script> </head> <body> 
<noscript><h2 style="color: #e80b0a;">Sorry,浏览器不支持WebSocket</h2></noscript> 
<div> 
    <div> 
        <button id="disconnect"  onclick="send()"  onclike="send()">发送</button>
        <input id="text" type="text"/> 
    </div> 
</div> 
<script type="text/javascript">
    var websocket=null;
    window.onload=function (){
        if ('WebSocket' in window) {
            console.log("1");
            websocket = new WebSocket("ws://127.0.0.1:8080/websocket");
        } else if ('MozWebSocket' in window) {
            console.log("2");
            websocket = new MozWebSocket("ws://127.0.0.1:8080/websocket");
        } else {
            websocket = new SockJS("ws://127.0.0.1:8080/websocket");
        }
        //websocket = new WebSocket("ws://127.0.0.1:8080/websocket");
        websocket.onmessage = function(msg) {  
            console.log(msg.data);  
            }  
   }
    
    function send() {
        var message = document.getElementById('text').value;
        console.log(message); 
        websocket.send(message);
        
    }
</script> </body> </html>

这是之前写的用websocket来实时传值的两个页面,稍微改了改。

二,写Controller层代码

先把两个页面的请求写出来

@Controller
@RequestMapping("/hello")
public class WsController { 
//测试页面
    @RequestMapping("/test1")
    public String test() throws IOException{ 
        return "showlist";
    } 
    
    //消息发送页面
    @RequestMapping("/test3")
    public String test2() throws IOException{
        return "ws2";
    } 

剩下的就是抽奖逻辑代码 和数据库脚本代码了,细节如何构思的就不说了,脑壳疼,一边想着怎么做,然后老大那边又说这个流程这么走,不不不,那么走,嗯嗯嗯,还是这么走。

//抽奖测试
    @Autowired
    private TestDao testDao;
    @ResponseBody
    @RequestMapping("/test2")
    public Map test(@RequestParam("msg") String msg,@RequestParam("peo") List<Integer> peo) throws IOException {
        String prize_name = "第一轮抽奖";
        //收到页面传来数据msg(抽奖人id),prize_name(抽取的奖项)获得抽奖信息
        Map<String,String> priz_info = testDao.findPrizinfo(msg,prize_name);
        //定义一个最终传回值的集合
        Map m1 = new HashMap();
        if(priz_info != null) {
        //判断peo数据如果没人数数据 添加数据
            if(peo.isEmpty()) {
                //n为人员总数
                int n = testDao.findAll();
                for(int i = 0; i < n;i++) {
                    peo.add(i);
                }
            }
            System.out.println("当前抽奖总人数为:"+peo);
            //定义一个最终获奖人id的集合
            ArrayList<Integer> dIdList = new ArrayList<Integer>();
            //定义一个获取抽奖结果的集合
            Map m2 = new HashMap();
            //得到抽奖次数
            int count = Integer.parseInt(priz_info.get("prize_num"))  / Integer.parseInt(priz_info.get("prize_count")) ;
            for(int i = 0; i < count;i++) {
                //进行抽奖并获得结果集
                m2 = luck(peo,Integer.parseInt( priz_info.get("prize_count")));
                //得到中奖人id集合
                dIdList.addAll((List)m2.get("eidList"));
                //得到剩余人数 
                peo = (List<Integer>) m2.get("idList");
                //将每一次抽奖的状态改变
                testDao.update(priz_info.get("prize_id"), i+1);
            }
            System.out.println("获奖id:"+dIdList);
            System.out.println("最后人数:"+peo);
            //循环获得LIST<USER> 中奖人信息
            ArrayList<User> infoList = new ArrayList<User>(); 
            for(int i = 0;i < dIdList.size();i++) {
                infoList.add(testDao.findById(dIdList.get(i)));
            }
            //为返回值传入参数
                //获奖信息
            m1.put("list", infoList);
                //未中奖人
            m1.put("poe", peo);
        }       
    return m1;
}   
    
        //抽奖 传参 1.总人数  3,几人中奖
     Map luck(List<Integer> idList,int n) {
          //取得中奖人id
          ArrayList<Integer> a = makeRandom(0,idList.size(), n);
          System.out.println("中奖的数字为"+a);
          //获奖id临时存储集合
          ArrayList<Integer> eidList = new ArrayList<Integer>();
          //排序
          Object[] b = a.toArray();
          Arrays.sort(b);
          //定义一个中奖人数据集合
          List t = new ArrayList();
          for(int i = 0; i < b.length;i++)
           {    
              eidList.add(idList.get((int) b[i]));
              System.out.println("中奖的id为"+idList.get((int) b[i]));
              t.add(idList.get((int) b[i]));
           }
          //总人数中移除中奖人数据
          idList.removeAll(t);
          //写到Map集合回传
          Map m = new HashMap();
          //剩余id
          m.put("idList", idList);
          //获奖id
          m.put("eidList", eidList);
          return m;
    }
    
    
    //从x-y 取num个随机数
    ArrayList<Integer> makeRandom(int x, int y, int num)
    { 
        //创建一个integer的动态数组
        ArrayList<Integer> a = new ArrayList<Integer>();
        int index = 0;
        //往数组里面逐一加取到不重复的元素
        while(index < num)
        {
        //产生x-y的随机数
            Random r = new Random();
            int temp = r.nextInt(y-x)+x ;
        //设置是否重复的标记变量为false
            boolean flag = false;
            for(int i =0; i<index;i++)
            {
                if(temp == a.get(i))
                {
                    flag = true;
                    break;
                }
            }
            if(flag==false)
            {
                a.add(temp);
                index++;
            }
        }
        return a;
    }
}

Dao

@Mapper
public interface TestDao {
    //查询抽奖人数
    @Select("select count(*) from dd_annual_meeting_user where user_state = 1")
    int findAll();
    
    //查询中奖人信息
    @Select("select * from dd_annual_meeting_user where user_state = 1 limit ${id},1")
    User findById(@Param("id") int id);
    
    //修改中奖人与奖池练联系(暂时不写)
    @Insert("INSERT INTO dd_annual_meeting_check VALUES ( #{check_prize_id}, #{emp_id},curdate(),'1')")
    void inset(@Param("check_prize_id") String check_prize_id,@Param("emp_id") int emp_id);

    //获取抽奖信息
    @Select("select prize_id,prize_num,prize_count from dd_annual_meeting_prize where leader_id=#{msg} and prize_name=#{prize_name} and prize_state=0")
    Map findPrizinfo(@Param("msg") String msg, @Param("prize_name") String prize_name);
    
    //更改抽奖状态
    @Update("update dd_annual_meeting_record set record_state=1  where record_prize_id = #{prize_id} and record_times = #{record_times}")
    void update(@Param("prize_id") Object prize_id, @Param("record_times") int record_times);
}

现在来测试效果:

点击前

这边自己在数据库中添加了数据,传1后会进行抽奖


第一次点击

第二次点击

点了两次 共抽了10人出来,并没有重复。

讲真,全程靠着表结构自己想逻辑,真的皮,有些字段都不确定是来干什么的,去问同组做这个的人,她说她不清楚,我服了,然后知道了个大概的流程,把这个简单的逻辑弄完给她看了看,她说差不多了,好吧,我不管了,后面都做完了我再修改细节。现在可以摸鱼了,摸个两三天再交差。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容

  • 抽奖活动API 获取参与抽奖名单 分页获取参与抽奖名单 导出参与名单的报表模板 导入参与名单 内定中奖名单列表 获...
    kingsonCai阅读 2,501评论 1 1
  • php实现刮刮卡大转盘抽奖概率 本文实例为大家分享了php中奖概率算法,可用于刮刮卡,大转盘等抽奖算法,用法很简单...
    RwatitFahsa阅读 870评论 1 2
  • 每天进步一点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点~~从开始只能写几句话、模仿别人的观点,到现...
    一个帅气的名字呀阅读 18,023评论 4 31
  • 在烟台市莱山区陈家村里的一所学校叫陈家小学。有一个通缉犯学生叫陈星羽。他身高大约150以上。看见了,立即拨打...
    四叶草的仙女阅读 234评论 0 0
  • 平静的夜,被一个又一个的消息打破了,激起了层层涟漪。而翻来覆去睡不着也只有我自己一个人。经常性的失眠,长期以来的纠...
    一棵奇思幻想的树阅读 234评论 0 0