小组在做一个抽奖系统,现在给我分配到了抽奖逻辑这方面的实现。
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.将中奖人信息与奖项信息绑定,添加到中奖池信息表
简单的分析后,有了大致思路,细节什么的就在代码中完成:
一,先弄两个页面出来,一个是显示中奖信息的页面,另外一个是发送抽奖指令的页面(因为是领导来点击抽奖,所以有一个领导信息需要发送过来)。
抽奖页面奖品列表!!!!!!!!!!!!
var psel = document.getElementById("poe");
window.οnlοad=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 = '
inf += "
获奖人id获奖人姓名获奖人奖券号"/*
for(var i=0; i
/*]]>*/
var stu = rtn.list[i];
inf += "
"+stu.user_id+""+stu.user_name+""+stu.user_prize+""}
inf += "
"$("#showData").html(inf);
}
if(rtn.poe != null){
psel.value = rtn.poe;
}
}
});
}
}
//发送消息测试页面
发送消息测试页面Sorry,浏览器不支持WebSocket
发送
var websocket=null;
window.οnlοad=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);
}
这是之前写的用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 peo) throws IOException {
String prize_name = "第一轮抽奖";
//收到页面传来数据msg(抽奖人id),prize_name(抽取的奖项)获得抽奖信息
Map 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 dIdList = new ArrayList();
//定义一个获取抽奖结果的集合
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) m2.get("idList");
//将每一次抽奖的状态改变
testDao.update(priz_info.get("prize_id"), i+1);
}
System.out.println("获奖id:"+dIdList);
System.out.println("最后人数:"+peo);
//循环获得LIST 中奖人信息
ArrayList infoList = new ArrayList();
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 idList,int n) {
//取得中奖人id
ArrayList a = makeRandom(0,idList.size(), n);
System.out.println("中奖的数字为"+a);
//获奖id临时存储集合
ArrayList eidList = new ArrayList();
//排序
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 makeRandom(int x, int y, int num)
{
//创建一个integer的动态数组
ArrayList a = new ArrayList();
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
{
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人出来,并没有重复。
讲真,全程靠着表结构自己想逻辑,真的皮,有些字段都不确定是来干什么的,去问同组做这个的人,她说她不清楚,我服了,然后知道了个大概的流程,把这个简单的逻辑弄完给她看了看,她说差不多了,好吧,我不管了,后面都做完了我再修改细节。现在可以摸鱼了,摸个两三天再交差。