$total) { return []; } if($max*$num < $total){ return []; } while ($num >= 1) { $num--; $kmix = max($min, $total - $num * $max); $kmax = min($max, $total - $num * $min); $kAvg = $total / ($num + 1); //获取最大值和最小值的距离之间的最小值 $kDis = min($kAvg - $kmix, $kmax - $kAvg); //获取0到1之间的随机数与距离最小值相乘得出浮动区间,这使得浮动区间不会超出范围 $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2; $k = sprintf("%.2f", $kAvg + $r); $k = round($k, 0); $total -= $k; $data[] = $k; $sum += $k; } if($totals != (int)$sum){ $return = $this->red_envelope_create_money($min, $max, $nums, $totals); return $return; }else{ return $data; } } //红包展示 public function get_red_envelope_list($uid, $type){ $config = get_uncache_system_config(); $user_info = db::name('user')->find($uid); if(!$user_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } //红包类型 $envelope_type_info = db::name('envelope_type')->find($type); if(!$envelope_type_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } //是否有进行中的 $map = []; $map[] = ['tid', '=', $type]; $map[] = ['is_finish', '=', 2]; $map[] = ['is_delete', '=', 1]; $map[] = ['is_stop', '=', 2]; $red_envelope_info = db::name('red_envelope')->where($map)->find(); $data = []; $data['type'] = $type; $data['type_name'] = $envelope_type_info['type_name']; $data['price'] = $envelope_type_info['price']; if($red_envelope_info){ $data['unopen_num'] = $red_envelope_info['num'] - $red_envelope_info['open_num']; $data['is_finish'] = $red_envelope_info['is_finish']; $data['num'] = $red_envelope_info['num']; }else{ $data['unopen_num'] = 0; $data['is_finish'] = 1; if($type == 1){ $data['num'] = $config['silver_envelope_num']; }else if($type == 2){ $data['num'] = $config['gold_envelope_num']; }else if($type == 3){ $data['num'] = $config['drill_envelope_num']; } } $data['integral'] = $user_info['integral']; return ['code' => 200, 'msg' => '获取成功', 'data' => $data]; } //抢红包 public function snatch_red_envelope($uid, $rid, $type){ $user_info = db::name('user')->find($uid); if(!$user_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } if($user_info['is_tester'] == 2){ return ['code' => 201, 'msg' => '虚拟号无法参与', 'data' => null]; } //房间是否存在 $map = []; $map[] = ['rid', '=', $rid]; $room_info = db::name('room')->where($map)->find(); if(!$room_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } //红包类型 $envelope_type_info = db::name('envelope_type')->find($type); if(!$envelope_type_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } //金币是否充足 if($user_info['integral'] < $envelope_type_info['price']){ return ['code' => 201, 'msg' => '金币不足', 'data' => null]; } $where = []; $where[] = ['a.uid', '=', $uid]; $where[] = ['b.is_stop', '=', 2]; $red_envelope_log = db::name('user_red_envelope_log')->alias('a')->join('yy_red_envelope b', 'a.eid = b.id')->field('sum(b.money) as money')->where($where)->find(); $surplus_money = $user_info['integral'] - $red_envelope_log['money']; if($envelope_type_info['price'] > $surplus_money){ return ['code' => 201, 'msg' => '金币不足', 'data' => null]; } //是否有进行中的 $map = []; $map[] = ['tid', '=', $type]; $map[] = ['is_finish', '=', 2]; $map[] = ['is_delete', '=', 1]; $map[] = ['is_stop', '=', 2]; $red_envelope_info = db::name('red_envelope')->where($map)->find(); if(!$red_envelope_info){ return ['code' => 201, 'msg' => '暂未开放', 'data' => null]; } //开始十秒内无法抢红包 $time = time() - $red_envelope_info['add_time']; if($time < 10){ return ['code' => 201, 'msg' => '请在开始十秒后再抢', 'data' => null]; } //是否抢过该红包 $map = []; $map[] = ['uid', '=', $uid]; $map[] = ['eid', '=', $red_envelope_info['id']]; $user_snatch_red_envelope = db::name('user_red_envelope_log')->where($map)->find(); if($user_snatch_red_envelope){ return ['code' => 201, 'msg' => '你已抢过该红包', 'data' => null]; } //该红包数量是否剩余 $map = []; $map[] = ['eid', '=', $red_envelope_info['id']]; $user_snatch_red_envelope_sum = db::name('user_red_envelope_log')->where($map)->count(); if($user_snatch_red_envelope_sum == $red_envelope_info['num']){ return ['code' => 201, 'msg' => '红包已被抢完', 'data' => null]; } $config = get_uncache_system_config(); $redis = connectionRedis(); $user_red_envelope_id_list = []; $is_open = 1; if($type == 1){ $keyname = "silver:envelope:key:name:".$red_envelope_info['id']; $envelope_num = $config['silver_envelope_num']; if($config['open_silver_envelope'] != 1){ $is_open = 2; } }else if($type == 2){ $keyname = "gold:envelope:key:name:".$red_envelope_info['id']; $envelope_num = $config['gold_envelope_num']; if($config['open_gold_envelope'] != 1){ $is_open = 2; } }else if($type == 3){ $keyname = "drill:envelope:key:name:".$red_envelope_info['id']; $envelope_num = $config['drill_envelope_num']; if($config['open_drill_envelope'] != 1){ $is_open = 2; } } Db::startTrans(); try { //抢红包记录 $list_len = $redis->llen($keyname); if($list_len = 0){ return ['code' => 201, 'msg' => '该轮红包已被抢完,请稍后', 'data' => null]; } $snatch_price_data = $redis->blpop($keyname, 2); if(empty($snatch_price_data)){ return ['code' => 201, 'msg' => '红包已被抢完', 'data' => null]; } $snatch_price = $snatch_price_data[1]; $data = []; $data['price'] = $snatch_price; $user_red_envelope_id_list[] = $data; //记录 $insert_data_log = []; $insert_data_log['uid'] = $uid; $insert_data_log['rid'] = $rid; $insert_data_log['tid'] = $type; $insert_data_log['eid'] = $red_envelope_info['id']; $insert_data_log['money'] = $red_envelope_info['money']; $insert_data_log['price'] = $red_envelope_info['price']; $insert_data_log['snatch_price'] = $snatch_price; $insert_data_log['envelope_price'] = $config['envelope_rate'] * $red_envelope_info['money']; $insert_data_log['room_price'] = $room_info['envelope_rate'] * $snatch_price; $insert_data_log['add_time'] = time(); $sid = db::name('user_red_envelope_log')->insertGetId($insert_data_log); if(!$sid){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //修改红包已开次数 $map = []; $map[] = ['id', '=', $red_envelope_info['id']]; $map[] = ['open_num', '<', $red_envelope_info['num']]; $reslut = db::name('red_envelope')->where($map)->inc('open_num', 1)->update(); if(!$reslut){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //抢红包收入 $resluts = model('admin/User')->change_user_money_by_user_info($user_info, $snatch_price, 2, 19, "抢红包收入", $uid, $sid, $rid); if(!$resluts){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //厅主收益 if($insert_data_log['room_price'] > 0){ $room_user_info = db::name('user')->find($room_info['room_owner_uid']); $reslut = model('admin/User')->change_user_money_by_user_info($room_user_info, $insert_data_log['room_price'], 1, 20, "抢红包厅主流水", $uid, $sid, $rid); if(!$reslut){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } } //是否最后一个红包 $where = []; $where[] = ['eid', '=', $red_envelope_info['id']]; $red_envelope_list = db::name('user_red_envelope_log')->where($where)->order('snatch_price desc,id asc')->select(); if(count($red_envelope_list) == $red_envelope_info['num']){ //修改红包状态 $update_data = []; $update_data['is_finish'] = 1; $update_data['is_stop'] = 1; $update_data['stop_time'] = time(); $reslut = db::name('red_envelope')->where('id', $red_envelope_info['id'])->update($update_data); if(!$reslut){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //找到手气最佳新生成一轮红包 foreach ($red_envelope_list as $k => $v){ if($k == 0){ //修改手气最佳 $update_data = []; $update_data['is_lucky'] = 1; $reslut = db::name('user_red_envelope_log')->where('id', $v['id'])->update($update_data); if(!$reslut){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //后台是否已关闭发红包功能 if($is_open == 1){ //发红包 $insert_data = []; $insert_data['tid'] = $type; $insert_data['uid'] = $v['uid']; $insert_data['type'] = 2; $insert_data['money'] = $envelope_type_info['price']; $insert_data['price'] = $insert_data['money'] * (1 - $config['envelope_rate']); $insert_data['num'] = $envelope_num; $insert_data['add_time'] = time(); $sid = db::name('red_envelope')->insertGetId($insert_data); if(!$sid){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } $insert_user_info = db::name('user')->find($v['uid']); //扣除发红包金币数 $resluts = model('admin/User')->change_user_money_by_user_info($insert_user_info, -$envelope_type_info['price'], 2, 18, "发红包支出", $v['uid'], $sid, $rid); if(!$resluts){ Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '请重试', 'data' => null]; } //生成红包队列 $redis->del($keyname); if($type == 1){ $key_name = "silver:envelope:key:name:". $sid; }else if($type == 2){ $key_name = "gold:envelope:key:name:" . $sid; }else if($type == 3){ $key_name = "drill:envelope:key:name:" . $sid; } $envelope_price_array = model('Envelope')->red_envelope_create_money(1, 500, $envelope_num, $insert_data['price']); $envelope_insert_data = $envelope_price_array; array_unshift($envelope_insert_data, $key_name); call_user_func_array([$redis, 'rPush'], $envelope_insert_data); } } } } Db::commit(); //抢红包socket $snatch_red_envelope = []; $snatch_red_envelope['uid'] = $uid; $snatch_red_envelope['rid'] = $rid; $snatch_red_envelope['head_pic'] = localpath_to_netpath($user_info['head_pic']); $snatch_red_envelope['nick_name'] = mb_convert_encoding(base64_decode($user_info['base64_nick_name']), 'UTF-8', 'UTF-8'); $snatch_red_envelope['type'] = $type; $snatch_red_envelope['type_name'] = $envelope_type_info['type_name']; $snatch_red_envelope['num'] = $red_envelope_info['num'] - $red_envelope_info['open_num'] - 1; $snatch_red_envelope['room_name'] = mb_convert_encoding(base64_decode($room_info['base64_room_name']), 'UTF-8', 'UTF-8'); $snatch_red_envelope['is_show_price'] = 2; if(count($red_envelope_list) == $red_envelope_info['num']){ $red_envelope_over = []; $where = []; $where[] = ['a.eid', '=', $red_envelope_info['id']]; $user_red_envelope_log_list = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->field('a.id,a.uid,a.rid,a.eid,a.snatch_price,b.head_pic,b.base64_nick_name,c.base64_room_name,a.is_lucky')->where($where)->order('a.id asc')->select(); foreach ($user_red_envelope_log_list as $k => $v){ $user_log_array = []; $user_log_array['uid'] = $v['uid']; $user_log_array['rid'] = $v['rid']; $user_log_array['head_pic'] = localpath_to_netpath($v['head_pic']); $user_log_array['nick_name'] = mb_convert_encoding(base64_decode($v['base64_nick_name']), 'UTF-8', 'UTF-8'); $user_log_array['room_name'] = mb_convert_encoding(base64_decode($v['base64_room_name']), 'UTF-8', 'UTF-8'); $user_log_array['snatch_price'] = $v['snatch_price']; $user_log_array['is_show_price'] = 1; $user_log_array['is_lucky'] = $v['is_lucky']; $red_envelope_over[] = $user_log_array; } //结束socket $push_all_snatch_envelope_data = []; $push_all_snatch_envelope_data['snatch_red_envelope'] = $snatch_red_envelope; $push_all_snatch_envelope_data['red_envelope_over'] = $red_envelope_over; $push_all_snatch_envelope_data['type'] = $type; $push_all_snatch_envelope_data['type_name'] = $envelope_type_info['type_name']; if($is_open == 1){ $push_all_snatch_envelope_data['is_open'] = 1; $push_all_snatch_envelope_data['num'] = $envelope_num; $push_all_snatch_envelope_data['second'] = 10; }else{ $push_all_snatch_envelope_data['is_open'] = 2; $push_all_snatch_envelope_data['num'] = 0; $push_all_snatch_envelope_data['second'] = 0; } $push_data = []; $push_data['code'] = 412; $push_data['msg'] = '抢红包结束数据播报'; $push_data['data'] = $push_all_snatch_envelope_data; model('api/WebSocketPush')->send_to_all($push_data); }else{ $push_data = []; $push_data['code'] = 411; $push_data['msg'] = '抢红包数据播报'; $push_data['data'] = $snatch_red_envelope; model('api/WebSocketPush')->send_to_all($push_data); } $snatch_red_envelope['integral'] = db::name('user')->where('uid', $uid)->value('integral'); return ['code' => 200, 'msg' => '成功', 'data' => $snatch_red_envelope]; } catch (\Exception $e) { // 回滚事务 dump($e); Db::rollback(); $this->redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list); return ['code' => 201, 'msg' => '失败', 'data' => null]; } } //返还用户抽中红包金额到队列 private function redis_envelope_data_rollback($redis, $keyname, $user_red_envelope_id_list) { $insert_data = []; foreach ($user_red_envelope_id_list as $k => $v) { $insert_data[] = $v['price']; } if (!empty($insert_data)) { array_unshift($insert_data, $keyname); //右侧取 右侧插入 call_user_func_array([$redis, 'lPush'], $insert_data); } return ['code' => 200, 'msg' => '返还成功', 'data' => null]; } //红包记录信息 public function red_envelope_info($uid, $type){ $user_info = db::name('user')->find($uid); if(!$user_info){ return ['code' => 201, 'msg' => '参数错误', 'data' => null]; } $data = []; //最新红包记录 $map = []; $map[] = ['is_delete', '=', 1]; $map[] = ['is_finish', '=', 2]; $map[] = ['is_stop', '=', 2]; $map[] = ['tid', '=', $type]; $red_envelope_info = db::name('red_envelope')->where($map)->order('id desc')->limit(1)->find(); if($red_envelope_info){ $user_red_envelope_log_list = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->where('a.eid', $red_envelope_info['id'])->field('a.id, a.uid, a.rid, a.eid, b.head_pic,b.base64_nick_name,c.base64_room_name')->order('a.id asc')->select(); foreach ($user_red_envelope_log_list as $k => &$v){ $v['head_pic'] = localpath_to_netpath($v['head_pic']); $v['nick_name'] = mb_convert_encoding(base64_decode($v['base64_nick_name']), 'UTF-8', 'UTF-8'); $v['room_name'] = mb_convert_encoding(base64_decode($v['base64_room_name']), 'UTF-8', 'UTF-8'); $v['is_show_price'] = 2; } $data['red_envelope_list'] = $user_red_envelope_log_list; }else{ $data['red_envelope_list'] = []; } //前一次红包记录 $map = []; $map[] = ['is_delete', '=', 1]; $map[] = ['is_stop', '=', 1]; $map[] = ['tid', '=', $type]; $last_red_envelope_info = db::name('red_envelope')->where($map)->order('id desc')->limit(1)->find(); // dump($last_red_envelope_info); if($last_red_envelope_info){ $user_red_envelope_log_lists = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->where('a.eid', $last_red_envelope_info['id'])->field('a.id, a.uid, a.rid, a.eid,a.snatch_price,a.is_lucky, b.head_pic,b.base64_nick_name,c.base64_room_name')->order('a.id asc')->select(); foreach ($user_red_envelope_log_lists as $a => &$b){ $b['head_pic'] = localpath_to_netpath($b['head_pic']); $b['nick_name'] = mb_convert_encoding(base64_decode($b['base64_nick_name']), 'UTF-8', 'UTF-8'); $b['room_name'] = mb_convert_encoding(base64_decode($b['base64_room_name']), 'UTF-8', 'UTF-8'); $b['is_show_price'] = 2; } // dump($user_red_envelope_log_lists); $user_red_envelope_list = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->where('a.eid', $last_red_envelope_info['id'])->field('a.id, a.uid, a.rid, a.eid,a.snatch_price,a.is_lucky, b.head_pic,b.base64_nick_name,c.base64_room_name')->order('a.id asc')->select(); foreach ($user_red_envelope_list as $x => &$y){ $y['head_pic'] = localpath_to_netpath($y['head_pic']); $y['nick_name'] = mb_convert_encoding(base64_decode($y['base64_nick_name']), 'UTF-8', 'UTF-8'); $y['room_name'] = mb_convert_encoding(base64_decode($y['base64_room_name']), 'UTF-8', 'UTF-8'); $y['is_show_price'] = 1; } $data['last_red_envelope_list'] = array_merge($user_red_envelope_log_lists, $user_red_envelope_list); }else{ $data['last_red_envelope_list'] = []; } return ['code' => 200, 'msg' => '获取成功', 'data' => $data]; } //红包规则 public function envelope_note(){ $envelope_note = get_system_config('envelope_note'); return ['code' => 200, 'msg' => '获取成功', 'data' => $envelope_note]; } //用户抢红包记录 public function user_red_envelope_log_list($uid, $type, $page, $page_limit){ $page = intval($page); $page_limit = $page_limit < 30 ? $page_limit : 30; $map = []; $map[] = ['a.uid', '=', $uid]; $map[] = ['a.tid', '=', $type]; $list = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->field('a.id,a.uid,a.rid,a.tid,a.snatch_price,b.head_pic,b.base64_nick_name,c.base64_room_name')->where($map)->order('id desc')->page($page, $page_limit)->select(); foreach ($list as $k => &$v){ $v['head_pic'] = localpath_to_netpath($v['head_pic']); $v['nick_name'] = mb_convert_encoding(base64_decode($v['base64_nick_name']), 'UTF-8', 'UTF-8'); $v['room_name'] = mb_convert_encoding(base64_decode($v['base64_room_name']), 'UTF-8', 'UTF-8'); } return ['code' => 200, 'msg' => '获取成功', 'data' => $list]; } //限时结束 public function red_envelope_time_limit(){ $config = get_uncache_system_config(); Db::startTrans(); try { if($config['envelope_sustain_duration'] != 0){ //是否有已开宝藏 $map = []; $map[] = ['is_stop', '=', 2]; $map[] = ['is_delete', '=', 1]; $red_envelope_list = db::name('red_envelope')->where($map)->select(); if($red_envelope_list){ foreach ($red_envelope_list as $k => $v){ //是否超时 $time = time() - $v['add_time']; if($time > $config['envelope_sustain_duration']){ $red_envelope_log_list = db::name('user_red_envelope_log')->alias('a')->join('yy_user b', 'a.uid = b.uid')->join('yy_room c', 'a.rid = c.rid')->field('a.id,a.uid,a.rid,a.eid,a.snatch_price,b.head_pic,b.base64_nick_name,c.base64_room_name,a.is_lucky')->where('eid', $v['id'])->order('id asc')->select(); if(count($red_envelope_log_list) != $v['num']){ //修改宝藏状态 $update_data = []; $update_data['is_stop'] = 1; $update_data['stop_time'] = time(); $reslut = db::name('red_envelope')->where('id', $v['id'])->update($update_data); if($reslut){ //发布socekt $snatch_red_envelope = []; $snatch_red_envelope['uid'] = 0; $red_envelope_over = []; if(!empty($red_envelope_log_list)){ foreach ($red_envelope_log_list as $a => $b){ $user_log_array = []; $user_log_array['uid'] = $b['uid']; $user_log_array['rid'] = $b['rid']; $user_log_array['head_pic'] = localpath_to_netpath($b['head_pic']); $user_log_array['nick_name'] = mb_convert_encoding(base64_decode($b['base64_nick_name']), 'UTF-8', 'UTF-8'); $user_log_array['room_name'] = mb_convert_encoding(base64_decode($b['base64_room_name']), 'UTF-8', 'UTF-8'); $user_log_array['snatch_price'] = $b['snatch_price']; $user_log_array['is_show_price'] = 1; $user_log_array['is_lucky'] = $b['is_lucky']; $red_envelope_over[] = $user_log_array; } } $push_all_snatch_envelope_data = []; $push_all_snatch_envelope_data['snatch_red_envelope'] = $snatch_red_envelope; $push_all_snatch_envelope_data['red_envelope_over'] = $red_envelope_over; $push_all_snatch_envelope_data['type'] = $v['tid']; $push_all_snatch_envelope_data['type_name'] = db::name('envelope_type')->where('id', $v['tid'])->value('type_name'); $push_all_snatch_envelope_data['is_open'] = 2; $push_all_snatch_envelope_data['num'] = 0; $push_all_snatch_envelope_data['second'] = 0; $push_data = []; $push_data['code'] = 412; $push_data['msg'] = '抢红包结束数据播报'; $push_data['data'] = $push_all_snatch_envelope_data; model('api/WebSocketPush')->send_to_all($push_data); } } } } } } Db::commit(); return ['code' => 200, 'msg' => '成功', 'data' => null]; } catch (\Exception $e) { // 回滚事务 dump($e); Db::rollback(); return ['code' => 201, 'msg' => '失败', 'data' => null]; } } }