0, 'heart' => 1, 'club' => 2, 'diamond' => 3, ]; public static $figures = [ 'A' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, '10' => 10, 'J' => 11, 'Q' => 12, 'K' => 13, ]; public static function parseCards($cards) { $new_cards = array(); foreach ($cards as $v) { $new_cards[] = array(self::$colors[$v[0]], self::$figures[$v[1]]); } return $new_cards; } public function crontab() { /** * 封装各方法 * @return [type] [description] */ $microtime = microtime(1); fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/BaseRedisService.php'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/GamesRedisService.php'); $redis = new GamesRedisService(); if ($redis->isLock()) { return array('is_lock'); } $redis->lock(); fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php'); $video_redis = new VideoRedisService(); $game_log_model = Model::build('game_log'); $time = NOW_TIME; $games = $game_log_model->field('id,game_id,create_time,long_time')->select(['status' => 1]); $game_types = array(); $return_data = array('time' => 0); /** * 游戏处理 */ if ($games) { $m_config = load_auto_cache("m_config"); $game_commission = +$m_config['game_commission']; $podcast_commission = intval(defined('PODCAST_COMMISSION') && PODCAST_COMMISSION); $user_model = Model::build('user'); $games_model = Model::build('games'); $coin_log_model = Model::build('coin_log'); $banker_log_model = Model::build('banker_log'); $user_game_log_model = Model::build('user_game_log'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/Poker.class.php'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/NiuNiu.class.php'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/DeZhou.class.php'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/Dice.class.php'); fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php'); $user_redis = new UserRedisService(); foreach ($games as $game) { $game_log_id = $game['id']; $game_id = $game['game_id']; $game_log = $redis->get($game_log_id, 'video_id,podcast_id,group_id,public_cards,banker_id'); $video_id = $game_log['video_id']; $podcast_id = $game_log['podcast_id']; $banker_id = $game_log['banker_id']; if (!isset($game_types[$game_id])) { $game_types[$game_id] = $games_model->field('commission_rate,rate,option,class,principal,ticket_rate')->selectOne(['id' => $game_id]); } $game_type = $game_types[$game_id]; $option = json_decode($game_type['option'], 1); if (!in_array($game_type['class'], ['Poker', 'NiuNiu', 'DeZhou', 'Dice'])) { break; } $game_object = new $game_type['class'](); if ($game['create_time'] + $game['long_time'] <= $time) { $live_in = $video_redis->getOne_db($video_id, 'live_in'); if ($redis->isVideoLock($video_id)) { break; } $redis->lockVideo($video_id); if ($live_in && $game['long_time']) { $sql_time = microtime(1); // 计算投注结果 $sum = []; $sum_v = []; $table = DB_PREFIX . 'user_game_log'; foreach ($option as $key => $value) { $res = intval($user_game_log_model->sum('money', ['game_log_id' => $game_log_id, 'bet' => $key])); $sum[] = $res; $sum_v[] = $res * $value; } $rate = $user_redis->getOne_db($podcast_id, 'rate'); $rate = $rate ? $rate : (+$game_type['rate']); $cheat = rand(1, 100) < $rate && !$banker_id; $dices = []; $cards_data = []; switch ($game_id) { case 1: case 2: $cards_data = $this->formatCardsData($game_object->play()); if ($cheat) { $cards_data = $this->sortGame($sum_v, $cards_data); } else { shuffle($cards_data); } break; case 3: $game_object->flop(json_decode($game_log['public_cards'], 1)); $data = $this->formatCardsData($game_object->play()); $cards = self::parseCards($game_object->gp); $gp = array( 'win' => false, 'cards' => $cards, 'type' => 0, ); if ($game_object->compare($res[0], $res[1]) == $game_object->compare($res[1], $res[0])) { $data[0]['win'] = false; $gp['win'] = true; shuffle($data); } else { if ($cheat && $sum_v[2] > $sum_v[0]) { $value = $data[0]; $data[0] = $data[1]; $data[1] = $value; } else { shuffle($data); } } $cards_data = array( $data[0], $gp, $data[1], ); break; case 4: if ($cheat) { $key = array_search(min($sum_v), $sum_v); $total = $key == 1 ? 7 : ($key ? rand(8, 12) : rand(2, 6)); } else { $total = false; } $dices = $game_object->play(2, $total); break; default: break; } // 计算得胜结果 $result = 0; $data = array('status' => 2); if ($cards_data) { foreach ($cards_data as $key => $value) { if ($value['win']) { $result = $key + 1; } unset($cards_data[$key]['win']); $data['option_win' . ($key + 1)] = intval($value['win']); $data['option_cards' . ($key + 1)] = json_encode($value['cards']); $data['option_type' . ($key + 1)] = $value['type']; } } else if ($dices) { $res = sum($dices); switch ($res) { case 7: $result = 2; break; default: $result = $res > 7 ? 3 : 1; break; } } $times = $option[$result]; $redis->set($game_log_id, $data); // MySQL结束游戏 // 计算主播收入 $commission_rate = $game_type['commission_rate']; $income = array_sum($sum) - $times * $sum[$result - 1]; $suit_patterns = json_encode($cards_data); $bet = json_encode($sum); $podcast_income = $income > 0 ? intval($income * $commission_rate / 100) : 0; $final_income = $banker_id ? ($income > 0 ? intval($income * $game_commission / 100) : 0) : $income - $podcast_income; $commission = 0; Connect::beginTransaction(); // 游戏记录结算 if ($game_log_model->multiAddLog($game_log_id, $result, $bet, $suit_patterns, $podcast_income, $banker_id ? 0 : $final_income) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $game_log_model->getLastSql(); break; } // 玩家收入 if ($sum[$result - 1]) { // 获得下注总金额三倍返还 if ($user_model->multiAddCoin($game_log_id, $result, $times) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_model->getLastSql(); break; } // 批量插入金币记录 if ($coin_log_model->multiAddLog($game_log_id, $result, $times) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $coin_log_model->getLastSql(); break; } if ($game_commission) { if ($user_model->multiAddCoin($game_log_id, $result, -$game_commission / 100 * $times) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_model->getLastSql(); break; } // 批量插入金币记录 if ($coin_log_model->multiAddLog($game_log_id, $result, -$game_commission / 100 * $times, '玩家收入平台抽成') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $coin_log_model->getLastSql(); break; } } if ($podcast_commission) { if ($user_model->multiAddCoin($game_log_id, $result, -$commission_rate / 100 * $times) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_model->getLastSql(); break; } // 批量插入金币记录 if ($coin_log_model->multiAddLog($game_log_id, $result, -$commission_rate / 100 * $times, '玩家收入主播抽成') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $coin_log_model->getLastSql(); break; } $commission = $commission_rate / 100 * $times * $sum[$result - 1]; if (defined('OPEN_DIAMOND_GAME_MODULE') && OPEN_DIAMOND_GAME_MODULE == 1) { $ticket = intval($commission * $game_type['ticket_rate'] / 100); $res = $user_model->update(['ticket' => ['ticket + ' . $ticket]], ['id' => $podcast_id]); $video_redis->inc_field($video_id, 'vote_number', $ticket); if ($res) { $log_data = [ 'log_info' => '主播游戏赢家抽成', 'log_time' => NOW_TIME, 'log_admin_id' => 0, 'money' => 0, 'user_id' => 1, 'type' => 7, 'prop_id' => 0, 'score' => 0, 'point' => 0, 'podcast_id' => $podcast_id, 'diamonds' => 0, 'ticket' => $ticket, 'video_id' => $video_id, ]; Model::build('user_log')->insert($log_data); } if (defined('GAME_DISTRIBUTION') && GAME_DISTRIBUTION) { if (Model::build('game_distribution')->addLog($podcast_id, $video_id, $game_log_id, $ticket, '游戏直播分销') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_game_log_model->getLastSql(); break; } } } else { $res = $user_model->coin($podcast_id, $commission); $account_diamonds = $user_model->coin($podcast_id); if ($res) { //会员账户 金币变更日志表 if ($coin_log_model->addLog($podcast_id, $game_log_id, $commission, $account_diamonds, '主播游戏赢家抽成') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } } if (defined('GAME_DISTRIBUTION') && GAME_DISTRIBUTION) { if (Model::build('game_distribution')->addLog($podcast_id, $video_id, $game_log_id, $commission, '游戏直播分销') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_game_log_model->getLastSql(); break; } } } } $win_times = $times * (1 - ($game_commission + $commission_rate * $podcast_commission) / 100); // 批量插入获胜记录 if ($user_game_log_model->multiAddLog($game_log_id, $result, $win_times, $podcast_id) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_game_log_model->getLastSql(); break; } } // 主播收入增加 if ($podcast_income) { if (defined('OPEN_DIAMOND_GAME_MODULE') && OPEN_DIAMOND_GAME_MODULE == 1) { $ticket = intval($podcast_income * $game_type['ticket_rate'] / 100); $res = $user_model->update(['ticket' => ['ticket + ' . $ticket]], ['id' => $podcast_id]); $video_redis->inc_field($video_id, 'vote_number', $ticket); if ($res) { $log_data = [ 'log_info' => '游戏直播收入', 'log_time' => NOW_TIME, 'log_admin_id' => 0, 'money' => 0, 'user_id' => $podcast_id, 'type' => 7, 'prop_id' => 0, 'score' => 0, 'point' => 0, 'podcast_id' => $podcast_id, 'diamonds' => 0, 'ticket' => $ticket, 'video_id' => $video_id, ]; Model::build('user_log')->insert($log_data); } if (defined('GAME_DISTRIBUTION') && GAME_DISTRIBUTION) { if (Model::build('game_distribution')->addLog($podcast_id, $video_id, $game_log_id, $ticket, '游戏直播分销') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_game_log_model->getLastSql(); break; } } } else { $res = $user_model->coin($podcast_id, $podcast_income); $account_diamonds = $user_model->coin($podcast_id); if ($res) { //会员账户 金币变更日志表 if ($coin_log_model->addLog($podcast_id, $game_log_id, $podcast_income, $account_diamonds, '游戏直播收入') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } } if (defined('GAME_DISTRIBUTION') && GAME_DISTRIBUTION) { if (Model::build('game_distribution')->addLog($podcast_id, $video_id, $game_log_id, $podcast_income, '游戏直播分销') === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__ . ' sql:' . $user_game_log_model->getLastSql(); break; } } } } // 主播收入增加 if ($podcast_income + $commission) { if ($user_game_log_model->addLog($game_log_id, $podcast_id, $podcast_income + $commission) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } } $stop_banker = false; // 庄家收入 if ($banker_id) { $banker_income = $income; if ($income > 0) { $banker_income = intval((100 - $game_commission - $commission_rate) / 100 * $income); } $res = $banker_log_model->update(['coin' => ["`coin`+$banker_income"]], ['user_id' => $banker_id, 'video_id' => $video_id, 'status' => 3]); $video_redis->inc_field($video_id, 'coin', $banker_income); $coin = $video_redis->getOne_db($video_id, 'coin'); if ($res) { if ($user_game_log_model->addLog($game_log_id, $banker_id, $banker_income) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } } // 强制下庄 if ($coin < $game_type['principal']) { $stop_banker = true; } } Connect::commit(); $sql_time = microtime(1) - $sql_time; $ids = array(); if ($sum[$result - 1]) { $res = $user_game_log_model->field('user_id')->group('user_id')->select(array('game_log_id' => $game_log_id)); foreach ($res as $value) { $ids[] = $value['user_id']; } } if ($podcast_income) { $ids[] = $podcast_id; } if (!empty($ids)) { user_deal_to_reids($ids); } $banker = $video_redis->getRow_db($video_id, [ 'banker_status', 'banker_id', 'banker_log_id', 'banker_name', 'banker_img', 'coin', ]); $tim_time = microtime(1); // 新推送 $ext = array( 'type' => 39, 'desc' => '', 'room_id' => $video_id, 'time' => 0, 'game_id' => $game_id, 'game_log_id' => $game_log_id, 'game_status' => 2, 'game_action' => 4, 'podcast_income' => $podcast_income, 'game_data' => array( 'win' => $result, 'bet' => $sum, 'dices' => $dices, 'cards_data' => $cards_data, ), 'banker_status' => intval($banker['banker_status']), 'banker' => [ 'banker_id' => intval($banker['banker_id']), 'banker_log_id' => intval($banker['banker_log_id']), 'banker_name' => $banker['banker_name'] ? $banker['banker_name'] : '', 'banker_img' => $banker['banker_img'] ? $banker['banker_img'] : '', 'coin' => intval($banker['coin']), 'max_bet' => $banker['coin'] / (max($option) - 1), ], ); $res = timSystemNotify($game_log['group_id'], $ext); if ($stop_banker) { if ($banker_log_model->returnCoin(['video_id' => $video_id, 'status' => 3], '底金不足,玩家下庄') == false) { $return_data[$game_log_id] = 'error:' . __LINE__ . $banker_log_model->getLastSql(); break; } $banker_ext = [ 'type' => 43, 'desc' => '', 'room_id' => $video_id, 'action' => 4, 'banker_status' => 0, 'data' => [ 'banker' => [ 'banker_id' => intval($banker['banker_id']), 'banker_log_id' => intval($banker['banker_log_id']), 'banker_name' => $banker['banker_name'] ? $banker['banker_name'] : '', 'banker_img' => $banker['banker_img'] ? $banker['banker_img'] : '', 'coin' => intval($banker['coin']), ], ], ]; $data = [ 'banker_id' => 0, 'banker_status' => 0, "banker_log_id" => 0, "banker_name" => '', "banker_img" => '', 'coin' => 0, ]; $video_redis->update_db($video_id, $data); $banker_res = timSystemNotify($game_log['group_id'], $banker_ext); } $tim_time = microtime(1) - $tim_time; $return_data[$game_log_id] = array( 'type' => 'result', 'id' => $game_log_id, 'data' => $ext, 'res' => $res, 'sql_time' => $sql_time, 'tim_time' => $tim_time, 'banker_ext' => $banker_ext, 'banker_res' => $banker_res, ); } else { // 返还投注 Connect::beginTransaction(); if ($game_log_model->update(array('status' => 2), array('id' => $game_log_id)) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } $redis->set($game_log_id, array('status' => 2)); if ($user_model->returnCoin($game_log_id) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } if ($coin_log_model->returnCoin($game_log_id) === false) { Connect::rollback(); $return_data[$game_log_id] = 'error:' . __LINE__; break; } if ($GLOBALS['db']->affected_rows()) { $res = $user_game_log_model->field('user_id')->group('user_id')->select(array('game_log_id' => $game_log_id)); $ids = array(); foreach ($res as $value) { $ids[] = $value['user_id']; } user_deal_to_reids($ids); } Connect::commit(); $data = [ 'game_log_id' => 0, 'banker_id' => 0, 'banker_status' => 0, "banker_log_id" => 0, "banker_name" => '', "banker_img" => '', 'coin' => 0, ]; $video_redis->update_db($video_id, $data); $ext = array( 'type' => 34, 'desc' => '', ); $res = timSystemNotify($game_log['group_id'], $ext); $return_data[$game_log_id] = array( 'type' => 'end_return', 'id' => $game_log_id, 'res' => $res, ); } $redis->unLockVideo($video_id); } else if ($game['create_time'] + $game['long_time'] > $time && !$banker_id) { // 机器人下注 $robot_num = $video_redis->getOne_db($video_id, 'robot_num'); if ($robot_num) { $rest = $game['create_time'] + $game['long_time'] - $time; if (rand(1, 300) < $game_type['rate'] && ($time - $game['create_time'] > 5)) { $option = json_decode($game_type['option'], 1); $data = array(); $op = array_rand($option); for ($i = 0; $i < $robot_num; $i++) { if (isset($data[$op])) { $data[$op] += rand(0, 10) * 10; } else { $data[$op] = rand(0, 10) * 10; } } foreach ($data as $key => $value) { $redis->inc($game_log_id, 'option' . $key, $value); } $data = $redis->get($game_log_id, array('option1', 'option2', 'option3')); $bet = array(); for ($i = 1; $i <= 3; $i++) { $bet[] = intval($data['option' . $i]); } $ext = array( 'type' => 39, 'room_id' => $video_id, 'desc' => '', 'time' => $rest, 'game_id' => $game_id, 'game_log_id' => $game_log_id, 'game_status' => 1, 'game_action' => 2, 'game_data' => array( 'bet' => $bet, ), ); $res = timSystemNotify($game_log['group_id'], $ext); $return_data[$game_log_id] = array( 'type' => 'robot', 'id' => $game_log_id, 'ext' => $ext, 'res' => $res, ); } } } } } $this->clearGameLog(); if (defined('OPEN_BANKER_MODULE') && OPEN_BANKER_MODULE == 1) { $this->clearBankerLog(); } $return_data['time'] = microtime(1) - $microtime; $redis->unLock(); return $return_data; } /** * 将关闭的直播游戏上庄记录移入历史记录 * @param string $value [description] * @return [type] [description] */ public function clearBankerLog($value = '') { $video_table = DB_PREFIX . 'video'; $table = DB_PREFIX . 'banker_log'; $history = DB_PREFIX . 'banker_log_history'; $res = $GLOBALS['db']->getOne("SELECT COUNT(1) FROM `$table` WHERE `video_id` NOT IN(SELECT id FROM `$video_table` WHERE live_in = 1)"); if ($res) { $res = $GLOBALS['db']->getAll("SELECT `video_id` FROM `$table` WHERE `video_id` NOT IN(SELECT id FROM `$video_table` WHERE live_in = 1) AND `status` IN (1,3) GROUP BY `video_id`"); $model = Model::build('banker_log'); foreach ($res as $key => $value) { $data = [ 'banker_id' => 0, 'banker_status' => 0, "banker_log_id" => 0, "banker_name" => '', "banker_img" => '', 'coin' => 0, ]; $video_redis->update_db($value['video_id'], $data); $res = $model->returnCoin(['video_id' => $value['video_id'], 'status' => ['in', [1, 3]]], '主播退出,退还上庄金额'); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__ . ':' . $model->getLastSql()); } } Connect::beginTransaction(); $res = Connect::exec("INSERT INTO `$history`(SELECT * FROM `$table` WHERE `video_id` NOT IN(SELECT id FROM `$video_table` WHERE live_in = 1) AND `status` IN (2,4))"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } $res = Connect::exec("DELETE FROM `$table` WHERE `video_id` NOT IN(SELECT id FROM `$video_table` WHERE live_in = 1) AND `status` IN (2,4)"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } Connect::commit(); } } /** * 将关闭的直播游戏记录移入历史记录 * @return [type] [description] */ public function clearGameLog() { $table = DB_PREFIX . 'game_log'; $video_table = DB_PREFIX . 'video'; $res = $GLOBALS['db']->getOne("SELECT COUNT(1) FROM `$table` WHERE podcast_id NOT IN(SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2"); if ($res) { $history = DB_PREFIX . 'game_log_history'; $log_table = DB_PREFIX . 'user_game_log'; $log_history = DB_PREFIX . 'user_game_log_history'; Connect::beginTransaction(); /** * 游戏记录迁移 * @var [type] */ $res = Connect::exec("INSERT INTO `$history`(SELECT * FROM `$table` WHERE podcast_id NOT IN(SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2)"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } $res = Connect::exec("DELETE FROM `$table` WHERE podcast_id NOT IN (SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } /** * 下注记录迁移 * @var [type] */ $res = Connect::exec("INSERT INTO `$log_history`(SELECT * FROM `$log_table` WHERE `game_log_id` NOT IN(SELECT `id` FROM `$table`))"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } $res = Connect::exec("DELETE FROM `$log_table` WHERE `game_log_id` NOT IN (SELECT `id` FROM `$table`)"); if ($res === false) { Connect::rollback(); $return_data['clear_log'] = array('error:' . __LINE__); } Connect::commit(); } } public function sortGame($sum, $res) { $min = min($sum); asort($sum); $data = array(); foreach ($sum as $k => $v) { if ($v == $min) { $data[] = array_shift($res); shuffle($data); shuffle($res); } else { $data[] = array_pop($res); } } $result = array(); $i = 0; foreach ($sum as $k => $v) { $result[$k] = $data[$i]; $i++; } ksort($result); return $result; } public function formatCardsData($cards_data) { $data = []; foreach ($cards_data as $key => $value) { $cards = self::parseCards($value['cards']); $data[] = array( 'win' => !$key, 'cards' => $cards, 'type' => $value['check']['type'], ); } return $data; } }