games.action.php 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | FANWE 直播系统
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2011 http://www.fanwe.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: 云淡风轻(1956838968@qq.com)
  8. // +----------------------------------------------------------------------
  9. class gamesModule extends baseModule
  10. {
  11. /**
  12. * redis对象实例
  13. * @var [type]
  14. */
  15. protected static $redis, $video_redis;
  16. /**
  17. * 构造函数,实例化redis对象,导入模型库
  18. */
  19. public function __construct()
  20. {
  21. parent::__construct();
  22. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/GamesRedisService.php');
  23. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  24. self::$redis = new GamesRedisService();
  25. self::$video_redis = new VideoRedisService();
  26. fanwe_require(APP_ROOT_PATH . 'mapi/lib/core/Model.class.php');
  27. Model::$lib = dirname(__FILE__);
  28. }
  29. public function __destruct()
  30. {
  31. parent::__destruct();
  32. }
  33. /**
  34. * api返回信息
  35. * @param string $error 错误信息
  36. * @param integer $status 错误状态
  37. * @param array $data 返回数据
  38. * @return void
  39. */
  40. protected static function returnError($error = '出错了!', $status = 0, $data = [])
  41. {
  42. $data['status'] = $status;
  43. $data['error'] = $error;
  44. if ($error == '参数错误') {
  45. $data['data'] = $_REQUEST;
  46. }
  47. api_ajax_return($data);
  48. }
  49. /**
  50. * 日志写入
  51. * @param object $data 日志数据
  52. * @return void
  53. */
  54. protected static function pushLog($data)
  55. {
  56. if (IS_DEBUG) {
  57. fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/PushLog.class.php');
  58. PushLog::log($data);
  59. }
  60. }
  61. /**
  62. * 获取用户id
  63. * @return integer 登录用户id
  64. */
  65. protected static function getUserId()
  66. {
  67. $user_id = intval($GLOBALS['user_info']['id']);
  68. if ($_REQUEST['test'] == 'test' && IS_DEBUG) {
  69. return 687;
  70. }
  71. if (!$user_id) {
  72. self::returnError('未登录');
  73. }
  74. return $user_id;
  75. }
  76. /**
  77. * 获取游戏配置
  78. * @param integer $id 游戏(种类)id
  79. * @param string $field 数据字段
  80. * @return array 游戏(种类)数据
  81. */
  82. protected static function getGameById($id, $field = '')
  83. {
  84. $game = Model::build('games')->field($field)->selectOne(['id' => $id]);
  85. if (!$game) {
  86. self::returnError('游戏参数错误');
  87. }
  88. return $game;
  89. }
  90. /**
  91. * 根据主播id获取直播间id以及group_id
  92. * @param integer $user_id 主播用户id
  93. * @return array [$video_id,$group_id]
  94. */
  95. protected static function getLiveVideoByUserId($user_id)
  96. {
  97. $video = Model::build('video')->getLiveVideoByUserId($user_id, 'id,group_id');
  98. $video_id = intval($video['id']);
  99. if (!($video['id'] && $video['group_id'])) {
  100. self::returnError('不在直播状态');
  101. }
  102. return [$video_id, $video['group_id']];
  103. }
  104. /**
  105. * 获取游戏状态信息
  106. * @param integer $video_id 直播间id
  107. * @return array [$last_game, $last_log_id, $banker_status, $banker_id]
  108. */
  109. protected static function getLastGameByVideoId($video_id)
  110. {
  111. $model = Model::build('games');
  112. return $model::getLastGameByVideoId($video_id);
  113. }
  114. /**
  115. * 获取上庄信息
  116. * @param integer $video_id 直播间id
  117. * @param array $option 下注选项倍数数据
  118. * @return array [$banker_status, $banker_id, $banker_log_id, $banker_name, $banker_img, $coin, $max_bet]
  119. */
  120. protected static function getBankerStatus($video_id, $option)
  121. {
  122. $model = Model::build('games');
  123. return $model::getBankerStatus($video_id, $option);
  124. }
  125. /**
  126. * 游戏参数转换为字符串(参数类型转换)
  127. * @param array $option 下注选项倍数数据
  128. * @return array 下注选项倍数数据
  129. */
  130. protected static function parseOption($option)
  131. {
  132. $model = Model::build('games');
  133. return $model::parseOption($option);
  134. }
  135. /**
  136. * 下庄状态变化,金额返还
  137. * @param integer $video_id 直播间id
  138. * @param string $group_id IM群组id
  139. * @return [type] [description]
  140. */
  141. protected static function stopRedisBanker($video_id, $group_id)
  142. {
  143. $model = Model::build('games');
  144. self::pushLog($model::stopRedisBanker($video_id, $group_id));
  145. }
  146. /**
  147. * 发牌
  148. * @return [type] [description]
  149. */
  150. public function start()
  151. {
  152. $user_id = self::getUserId();
  153. $game_id = intval($_REQUEST['id']);
  154. list(
  155. $video_id,
  156. $group_id
  157. ) = self::getLiveVideoByUserId($user_id);
  158. $game_log_id = Model::build('games')->startGame($game_id, $video_id, $group_id, $user_id);
  159. if (is_string($game_log_id)) {
  160. self::returnError($game_log_id);
  161. }
  162. self::returnError('', 1, compact('game_log_id'));
  163. }
  164. /**
  165. * 下注
  166. * @return [type] [description]
  167. */
  168. public function bet()
  169. {
  170. $user_id = self::getUserId();
  171. $id = intval($_REQUEST['id']);
  172. $bet = intval($_REQUEST['bet']);
  173. $money = intval($_REQUEST['money']);
  174. $key = [1 => 'option1', 2 => 'option2', 3 => 'option3'];
  175. if (!isset($key[$bet])) {
  176. self::returnError('参数错误');
  177. }
  178. $field = 'status,group_id,podcast_id,create_time,long_time,game_id,video_id,option,rate';
  179. $game = self::$redis->get($id, $field);
  180. $option = json_decode($game['option'], 1);
  181. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
  182. $user_redis = new UserRedisService();
  183. $account_diamonds = $coin = $user_redis->getOne_db(intval($user_id), 'coin');
  184. if (defined('OPEN_DIAMOND_GAME_MODULE') && OPEN_DIAMOND_GAME_MODULE == 1) {
  185. $account_diamonds = $user_redis->getOne_db(intval($user_id), 'diamonds');
  186. }
  187. $return = [
  188. 'account_diamonds' => intval($account_diamonds),
  189. 'coin' => intval($coin),
  190. ];
  191. if (!$game['status']) {
  192. self::returnError('游戏不存在', 0, $return);
  193. }
  194. if (intval($game['create_time'] + $game['long_time'] - NOW_TIME) <= 0) {
  195. self::returnError('超出投注时间', 0, $return);
  196. }
  197. $video = self::$video_redis->getRow_db($game['video_id'], ['banker_id', 'banker_status', 'coin']);
  198. if ($video['banker_status'] == 2) {
  199. if ($video['banker_id'] == $user_id) {
  200. self::returnError('庄家不能投注', 0, $return);
  201. }
  202. $op_bet = self::$redis->getBet($id, [$bet]);
  203. if ($video['coin'] / ($option[$bet] - 1) < $money + $op_bet[0]) {
  204. self::returnError('超出庄家底金最大投注金额', 0, $return);
  205. }
  206. }
  207. $user_model = Model::build('user');
  208. $res = $user_model->coin($user_id, -$money);
  209. if (!$res) {
  210. self::returnError('余额不足', 0, $return);
  211. }
  212. $account_diamonds = $user_model->coin($user_id);
  213. Model::build('coin_log')->addLog($user_id, $id, -$money, $account_diamonds, '游戏投注');
  214. Model::build('user_game_log')->addLog($id, $game['podcast_id'], $money, $user_id, $bet, 1);
  215. self::$redis->bet($id, $bet, $money, $user_id);
  216. if ($game['rate'] >= rand(1, 50)) {
  217. $bet_option = $option;
  218. unset($bet_option[$bet]);
  219. $bet_option = array_keys($bet_option);
  220. self::$redis->inc($id, 'option' . $bet_option[array_rand($bet_option, 1)], intval($money * rand(100, 300) / 1000) * 10);
  221. }
  222. list($bet, $user_bet) = self::$redis->getBet($id, [1, 2, 3], $user_id);
  223. $time = intval($game['create_time'] + $game['long_time'] - NOW_TIME);
  224. $time = $time > 0 ? $time : 0;
  225. // 新推送
  226. $ext = [
  227. 'type' => 39,
  228. 'room_id' => intval($game['video_id']),
  229. 'desc' => '',
  230. 'time' => $time,
  231. 'game_id' => intval($game['game_id']),
  232. 'game_log_id' => $id,
  233. 'game_status' => intval($game['status']),
  234. 'game_action' => 2,
  235. 'game_data' => ['bet' => $bet],
  236. ];
  237. $res = timSystemNotify($game['group_id'], $ext);
  238. self::pushLog(compact('res', 'ext', 'data'));
  239. if (defined('OPEN_DIAMOND_GAME_MODULE') && OPEN_DIAMOND_GAME_MODULE == 1) {
  240. $account_diamonds = $user_redis->getOne_db(intval($user_id), 'diamonds');
  241. }
  242. $coin = $user_redis->getOne_db(intval($user_id), 'coin');
  243. self::returnError('', 1, ['data' => [
  244. 'game_status' => intval($game['status']),
  245. 'time' => $time,
  246. 'account_diamonds' => $account_diamonds,
  247. 'coin' => $coin,
  248. 'game_data' => compact('bet', 'user_bet'),
  249. ]]);
  250. }
  251. /**
  252. * 进入直播间获取游戏信息
  253. * @return [type] [description]
  254. */
  255. public function get_video()
  256. {
  257. $id = intval($_REQUEST['id']);
  258. $video_id = intval($_REQUEST['video_id']);
  259. $user_id = self::getUserId();
  260. if (!$id && !$video_id) {
  261. self::returnError('参数错误');
  262. }
  263. if (!$id && $video_id) {
  264. $id = intval(self::$video_redis->getOne_db($video_id, 'game_log_id'));
  265. }
  266. if (!$id) {
  267. self::returnError('');
  268. }
  269. $field = ['video_id', 'group_id', 'status', 'game_id', 'create_time', 'long_time', 'option', 'bet_option', 'dices', 'win'];
  270. for ($i = 1; $i <= 3; $i++) {
  271. $field[] = 'option' . $i;
  272. $field[] = 'option' . $i . ':' . $user_id;
  273. $field[] = 'option_win' . $i;
  274. $field[] = 'option_cards' . $i;
  275. $field[] = 'option_type' . $i;
  276. }
  277. $data = self::$redis->get($id, $field);
  278. $video_id = intval($data['video_id']);
  279. $option = self::parseOption(json_decode($data['option'], 1));
  280. if ($data['game_id'] === false) {
  281. self::returnError('游戏不存在');
  282. }
  283. list($banker_status, $banker_id, $banker_log_id, $banker_name, $banker_img, $coin, $max_bet) = self::getBankerStatus($video_id, $option);
  284. $video = self::$video_redis->getRow_db($video_id, ['principal', 'auto_start']);
  285. $principal = intval($video['principal']);
  286. $auto_start = intval($video['auto_start']);
  287. $public_cards = json_decode($data['public_cards'], 1);
  288. $public_cards = $public_cards ? $public_cards : [];
  289. $dices = json_decode($data['dices'], 1);
  290. $dices = $dices ? $dices : [];
  291. $win = intval($data['win']);
  292. $bet = [];
  293. $user_bet = [];
  294. $cards_data = [];
  295. for ($i = 1; $i <= 3; $i++) {
  296. $bet[] = intval($data['option' . $i]);
  297. $user_bet[] = intval($data['option' . $i . ':' . $user_id]);
  298. $cards = json_decode($data['option_cards' . $i], 1);
  299. $type = intval($data['option_type' . $i]);
  300. $cards_data[] = [
  301. 'cards' => $cards ? $cards : [],
  302. 'type' => $type ? $type : 0,
  303. ];
  304. }
  305. $time = intval($data['create_time'] + $data['long_time'] - NOW_TIME);
  306. $ext = [
  307. 'type' => 39,
  308. 'user_id' => $user_id,
  309. 'desc' => '',
  310. 'room_id' => $data['video_id'],
  311. 'time' => $time > 0 ? $time : 0,
  312. 'game_id' => $data['game_id'],
  313. 'game_log_id' => $id,
  314. 'game_status' => $data['status'],
  315. 'game_action' => 6,
  316. 'auto_start' => $auto_start,
  317. 'option' => array_values($option),
  318. 'bet_option' => json_decode($data['bet_option'], 1),
  319. 'game_data' => compact('public_cards', 'win', 'bet', 'user_bet', 'cards_data', 'dices'),
  320. 'banker_status' => $banker_status,
  321. 'banker' => compact('banker_status', 'banker_id', 'banker_log_id', 'banker_name', 'banker_img', 'coin', 'max_bet'),
  322. 'principal' => $principal,
  323. ];
  324. $res = timSystemNotify($data['group_id'], $ext, [$user_id]);
  325. self::pushLog(compact('res', 'ext'));
  326. self::returnError('', 1, ['data' => $ext, 'game_id' => $data['game_id']]);
  327. }
  328. /**
  329. * 获取游戏记录
  330. * @return [type] [description]
  331. */
  332. public function log()
  333. {
  334. $podcast_id = intval($_REQUEST['podcast_id']);
  335. $game_id = intval($_REQUEST['game_id']);
  336. if (!$podcast_id || !$game_id) {
  337. self::returnError('参数错误');
  338. }
  339. $number = intval($_REQUEST['number']);
  340. $where = [
  341. 'podcast_id' => $podcast_id,
  342. 'game_id' => $game_id,
  343. 'status' => 2,
  344. 'result' => ['>', 0],
  345. ];
  346. $data = Model::build('game_log')->getList('result', $where, 'id desc', $number ? $number : 20);
  347. $res = [];
  348. foreach ($data as $value) {
  349. if ($value['result']) {
  350. $res[] = intval($value['result']);
  351. }
  352. }
  353. self::returnError('', 1, ['data' => $res]);
  354. }
  355. /**
  356. * 停止游戏
  357. * @return [type] [description]
  358. */
  359. public function stop()
  360. {
  361. $user_id = self::getUserId();
  362. list(
  363. $video_id,
  364. $group_id
  365. ) = self::getLiveVideoByUserId($user_id);
  366. list(
  367. $last_game,
  368. $last_log_id,
  369. $banker_status,
  370. $banker_id
  371. ) = self::getLastGameByVideoId($video_id);
  372. if ($banker_status) {
  373. self::stopRedisBanker($video_id, $group_id);
  374. }
  375. if (!$last_log_id) {
  376. self::returnError('不在游戏状态');
  377. }
  378. if (self::$redis->isVideoLock($video_id)) {
  379. self::returnError('操作频率太高了,请等下再点!');
  380. }
  381. self::$redis->lockVideo($video_id);
  382. if ($last_game) {
  383. $res = Model::build('game_log')->stop($last_log_id);
  384. if (!$res) {
  385. self::$redis->unLockVideo($video_id);
  386. self::returnError('服务器繁忙');
  387. }
  388. }
  389. self::$redis->set($last_log_id, array('long_time' => 0));
  390. self::$video_redis->update_db($video_id, array('game_log_id' => 0, 'auto_start' => 0));
  391. if (!$last_game) {
  392. $ext = array(
  393. 'type' => 34,
  394. 'desc' => '',
  395. );
  396. $res = timSystemNotify($group_id, $ext);
  397. }
  398. self::$redis->unLockVideo($video_id);
  399. self::returnError('正在关闭游戏', 1);
  400. }
  401. /**
  402. * 更新用户金币并返回赚取金额
  403. * @return [type] [description]
  404. */
  405. public function userDiamonds()
  406. {
  407. $game_log_id = intval($_REQUEST['id']);
  408. $user_id = self::getUserId();
  409. $gain = 0;
  410. if ($game_log_id) {
  411. $where = [
  412. 'game_log_id' => $game_log_id,
  413. 'user_id' => $user_id,
  414. 'bet' => 0,
  415. 'type' => 2,
  416. ];
  417. $alert_key = 'game_gain_for_alert:'.md5("$user_id:$game_log_id");
  418. $game = self::$redis->get($game_log_id, ['video_id', 'group_id', 'podcast_id', $alert_key]);
  419. if ($game['podcast_id'] == $user_id && OPEN_DIAMOND_GAME_MODULE) {
  420. $gain = 0;
  421. } else {
  422. $log = Model::build('user_game_log')->field('money')->selectOne($where);
  423. $where = [
  424. 'game_log_id' => $game_log_id,
  425. 'user_id' => $user_id,
  426. 'type' => 1,
  427. ];
  428. $gain = $log ? intval($log['money']) : 0;
  429. if (defined('GAME_WINNER') && GAME_WINNER) {
  430. $gain -= Model::build('user_game_log')->sum('money', $where);
  431. }
  432. }
  433. $where = [
  434. 'l.game_log_id' => $game_log_id,
  435. 'l.user_id' => ['u.id'],
  436. 'l.podcast_id' => ['<>', 'l.user_id', 'and', 1],
  437. 'l.bet' => 0,
  438. 'l.type' => 2,
  439. ];
  440. if (defined('GAME_WINNER') && GAME_WINNER) {
  441. $winner = Model::build('user_game_log')->table('user_game_log l,user u')->field('u.nick_name,l.money')->order('l.money desc')->selectOne($where);
  442. if (!$winner) {
  443. unset($winner);
  444. }
  445. }
  446. if ($gain) {
  447. $m_config = load_auto_cache("m_config");
  448. $game_gain_for_alert = intval($m_config['game_gain_for_alert']);
  449. $gain_gift = intval(defined('GAME_REWARD') && GAME_REWARD == 1);
  450. if ($game_gain_for_alert || $gain_gift) {
  451. if ($game['podcast_id'] != $user_id) {
  452. if ($game_gain_for_alert && $gain >= $game_gain_for_alert && !$game[$alert_key]) {
  453. self::$redis->set($game_log_id, [$alert_key => 1]);
  454. $video_id = intval($game['video_id']);
  455. $group_id = $game['group_id'];
  456. $podcast_id = intval($game['podcast_id']);
  457. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
  458. $user_redis = new UserRedisService();
  459. $user_info = $user_redis->getRow_db($user_id, array('nick_name'));
  460. $nick_name = emoji_decode($user_info['nick_name']);
  461. self::popMessage($video_id, $group_id, $podcast_id, $podcast_id, "恭喜{$nick_name}赢得{$gain}");
  462. }
  463. if ($gain_gift) {
  464. $where = ['diamonds' => ['<=', $gain]];
  465. $gift_list = Model::build('prop')->getList($where);
  466. if (empty($gift_list)) {
  467. unset($gift_list);
  468. }
  469. }
  470. }
  471. }
  472. }
  473. }
  474. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
  475. $user_redis = new UserRedisService();
  476. $user_diamonds = $coin = intval($user_redis->getOne_db($user_id, 'coin'));
  477. if ((defined('OPEN_DIAMOND_GAME_MODULE') && OPEN_DIAMOND_GAME_MODULE == 1) || (defined('OPEN_SEND_DIAMONDS_MODULE') && OPEN_SEND_DIAMONDS_MODULE == 1)) {
  478. $user_diamonds = intval($user_redis->getOne_db($user_id, 'diamonds'));
  479. }
  480. self::returnError('', 1, compact('user_diamonds', 'coin', 'gain', 'gift_list', 'winner'));
  481. }
  482. /**
  483. * 获取兑换比例
  484. * @return [type] [description]
  485. */
  486. public function exchangeRate()
  487. {
  488. $m_config = load_auto_cache("m_config");
  489. $rate = $m_config['coin_exchange_rate'] ? floatval($m_config['coin_exchange_rate']) : 1;
  490. self::returnError('', 1, ['exchange_rate' => $rate]);
  491. }
  492. /**
  493. * 钻石兑换游戏币
  494. * @return [type] [description]
  495. */
  496. public function exchangeCoin()
  497. {
  498. $user_id = self::getUserId();
  499. $diamonds = intval($_REQUEST['diamonds']);
  500. if ($diamonds < 1) {
  501. self::returnError('请输入兑换钻石');
  502. }
  503. Connect::beginTransaction();
  504. //减少用户钻石
  505. $sql = "update " . DB_PREFIX . "user set diamonds = diamonds - " . $diamonds . " where id = '" . $user_id . "' and diamonds >= " . $diamonds;
  506. $GLOBALS['db']->query($sql);
  507. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
  508. $user_redis = new UserRedisService();
  509. if ($GLOBALS['db']->affected_rows()) {
  510. $user_redis->inc_field($user_id, 'diamonds', -$diamonds);
  511. $account_diamonds = $user_redis->getOne_db(intval($user_id), 'diamonds');
  512. //会员账户 钻石变更日志表
  513. $log_model = Model::build('user_log');
  514. $log_data = [
  515. 'log_time' => NOW_TIME,
  516. 'log_admin_id' => 0,
  517. 'money' => 0,
  518. 'type' => 7,
  519. 'prop_id' => 0,
  520. 'score' => 0,
  521. 'point' => 0,
  522. 'podcast_id' => 0,
  523. 'diamonds' => -$diamonds,
  524. 'video_id' => 0,
  525. 'log_info' => '兑换游戏币',
  526. 'user_id' => $user_id,
  527. 'ticket' => 0,
  528. ];
  529. $log_model->insert($log_data);
  530. $user_model = Model::build('user');
  531. $m_config = load_auto_cache("m_config");
  532. $rate = $m_config['coin_exchange_rate'] ? floatval($m_config['coin_exchange_rate']) : 1;
  533. $res = $user_model->coin($user_id, $diamonds * $rate);
  534. if (!$res) {
  535. Connect::rollback();
  536. self::returnError('兑换失败');
  537. }
  538. $coin = $user_model->coin($user_id);
  539. Model::build('coin_log')->addLog($user_id, -1, $diamonds * $rate, $coin, '钻石兑换游戏币');
  540. Connect::commit();
  541. self::returnError('兑换成功', 1, compact('account_diamonds', 'coin'));
  542. }
  543. Connect::rollback();
  544. self::returnError('余额不足');
  545. }
  546. /**
  547. * 赠送游戏币
  548. * @return [type] [description]
  549. */
  550. public function sendCoin()
  551. {
  552. $user_id = self::getUserId();
  553. $is_nospeaking = Model::build('user')->field('is_nospeaking')->selectOne(['id' => $user_id]);
  554. $is_nospeaking = intval($is_nospeaking['is_nospeaking']);
  555. if ($is_nospeaking) {
  556. self::returnError('被im全局禁言,不能赠送游戏币');
  557. }
  558. $coin = intval($_REQUEST['coin']);
  559. $to_user_id = intval($_REQUEST['to_user_id']);
  560. if (!($user_id && $to_user_id && $coin > 0)) {
  561. self::returnError('请输入游戏币');
  562. }
  563. $user_model = Model::build('user');
  564. Connect::beginTransaction();
  565. $res = $user_model->coin($user_id, -$coin, 'coin');
  566. if (!$res) {
  567. Connect::rollback();
  568. self::returnError('余额不足');
  569. }
  570. $res = $user_model->coin($to_user_id, $coin, 'coin');
  571. if (!$res) {
  572. Connect::rollback();
  573. self::returnError('赠送游戏币失败');
  574. }
  575. $coin_log_model = Model::build('coin_log');
  576. $coin1 = $user_model->coin($user_id, false, 'coin');
  577. $nick_name = $user_model->getOneById($to_user_id, 'nick_name');
  578. $nick_name = emoji_decode($nick_name['nick_name']);
  579. $coin_log_model->addLog($user_id, -1, -$coin, $coin1, "赠送($nick_name)游戏币");
  580. $coin2 = $user_model->coin($to_user_id, false, 'coin');
  581. $nick_name = $user_model->getOneById($user_id, 'nick_name');
  582. $nick_name = emoji_decode($nick_name['nick_name']);
  583. $coin_log_model->addLog($to_user_id, -1, $coin, $coin2, "收到($nick_name)游戏币");
  584. Connect::commit();
  585. api_ajax_return(
  586. [
  587. 'status' => 1,
  588. 'error' => '赠送成功',
  589. 'from_msg' => "送给你{$coin}游戏币",
  590. 'to_msg' => "收到{$coin}游戏币",
  591. 'from_score' => "",
  592. 'to_ticket' => 0,
  593. 'to_diamonds' => 0,
  594. 'to_user_id' => $to_user_id,
  595. 'prop_icon' => get_domain() . '/public/gift/jinbi.png',
  596. 'prop_id' => 0,
  597. 'total_ticket' => 0,
  598. ]
  599. );
  600. }
  601. /**
  602. * 赠送钻石
  603. * @return [type] [description]
  604. */
  605. public function sendDiamonds()
  606. {
  607. $user_id = self::getUserId();
  608. $is_nospeaking = Model::build('user')->field('is_nospeaking')->selectOne(['id' => $user_id]);
  609. $is_nospeaking = intval($is_nospeaking['is_nospeaking']);
  610. if ($is_nospeaking) {
  611. self::returnError('被im全局禁言,不能赠送钻石');
  612. }
  613. $diamonds = intval($_REQUEST['diamonds']);
  614. $to_user_id = intval($_REQUEST['to_user_id']);
  615. if (!($user_id && $to_user_id && $diamonds > 0)) {
  616. self::returnError('请输入钻石');
  617. }
  618. $user_model = Model::build('user');
  619. Connect::beginTransaction();
  620. $res = $user_model->coin($user_id, -$diamonds, 'diamonds');
  621. if (!$res) {
  622. Connect::rollback();
  623. self::returnError('余额不足');
  624. }
  625. $res = $user_model->coin($to_user_id, $diamonds, 'diamonds');
  626. if (!$res) {
  627. Connect::rollback();
  628. self::returnError('赠送钻石失败');
  629. }
  630. $coin_log_model = Model::build('coin_log');
  631. $diamonds1 = $user_model->coin($user_id, false, 'diamonds');
  632. $nick_name = $user_model->getOneById($to_user_id, 'nick_name');
  633. $nick_name = emoji_decode($nick_name['nick_name']);
  634. $coin_log_model->addLog($user_id, -1, -$diamonds, $diamonds1, "赠送($nick_name)钻石");
  635. $diamonds2 = $user_model->coin($to_user_id, false, 'diamonds');
  636. $nick_name = $user_model->getOneById($user_id, 'nick_name');
  637. $nick_name = emoji_decode($nick_name['nick_name']);
  638. $coin_log_model->addLog($to_user_id, -1, $diamonds, $diamonds2, "收到($nick_name)钻石");
  639. Connect::commit();
  640. api_ajax_return(
  641. [
  642. 'status' => 1,
  643. 'error' => '赠送成功',
  644. 'from_msg' => "送给你{$diamonds}钻石",
  645. 'to_msg' => "收到{$diamonds}钻石",
  646. 'from_score' => "",
  647. 'to_ticket' => 0,
  648. 'to_diamonds' => $diamonds,
  649. 'to_user_id' => $to_user_id,
  650. 'prop_icon' => get_domain() . '/public/images/y3.png',
  651. 'prop_id' => 0,
  652. 'total_ticket' => 0,
  653. ]
  654. );
  655. }
  656. /**
  657. * iOS日志记录
  658. * @return [type] [description]
  659. */
  660. public function pushTest()
  661. {
  662. $user_id = self::getUserId();
  663. $test_system_im = json_decode($_REQUEST['test_system_im']);
  664. fanwe_require(APP_ROOT_PATH . 'mapi/lib/tools/PushLog.class.php');
  665. PushLog::log(compact('user_id', 'test_system_im'));
  666. self::returnError('', 1);
  667. }
  668. /**
  669. * 开启上庄
  670. * @return [type] [description]
  671. */
  672. public function openBanker()
  673. {
  674. /**
  675. * 判断游戏状态
  676. */
  677. $user_id = self::getUserId();
  678. list(
  679. $video_id,
  680. $group_id
  681. ) = self::getLiveVideoByUserId($user_id);
  682. list(
  683. $last_game,
  684. $last_log_id,
  685. $banker_status,
  686. $banker_id
  687. ) = self::getLastGameByVideoId($video_id);
  688. if ($last_game) {
  689. self::returnError('上局游戏未结束');
  690. } else {
  691. $game['status'] = self::$redis->get('status');
  692. if ($game['status'] == 1) {
  693. self::returnError('上局游戏未结束');
  694. }
  695. }
  696. if (self::$redis->isVideoLock($video_id)) {
  697. self::returnError('操作频率太高了,请等下再点!');
  698. }
  699. self::$redis->lockVideo($video_id);
  700. /**
  701. * 转换游戏状态
  702. */
  703. $game = self::$redis->get($last_log_id, 'game_id');
  704. $game_id = $game['game_id'];
  705. $game = self::getGameById($game_id, 'principal');
  706. if (!$banker_status) {
  707. self::$video_redis->update_db($video_id, array('banker_status' => 1, 'principal' => $game['principal']));
  708. }
  709. /**
  710. * 群发开启上庄消息
  711. */
  712. $ext = [
  713. 'type' => 43,
  714. 'desc' => '',
  715. 'room_id' => $video_id,
  716. 'action' => 1,
  717. 'banker_status' => 1,
  718. 'data' => [
  719. 'principal' => intval($game['principal']),
  720. ],
  721. ];
  722. $res = timSystemNotify($group_id, $ext);
  723. self::pushLog(compact('res', 'ext'));
  724. self::$redis->unLockVideo($video_id);
  725. self::returnError('', 1, $ext);
  726. }
  727. /**
  728. * 主播下庄
  729. * @return [type] [description]
  730. */
  731. public function stopBanker()
  732. {
  733. /**
  734. * 判断游戏状态
  735. */
  736. $user_id = self::getUserId();
  737. list(
  738. $video_id,
  739. $group_id
  740. ) = self::getLiveVideoByUserId($user_id);
  741. list(
  742. $last_game,
  743. $last_log_id,
  744. $banker_status,
  745. $banker_id
  746. ) = self::getLastGameByVideoId($video_id);
  747. if ($last_game) {
  748. self::returnError('上局游戏未结束');
  749. }
  750. if (self::$redis->isVideoLock($video_id)) {
  751. self::returnError('操作频率太高了,请等下再点!');
  752. }
  753. self::$redis->lockVideo($video_id);
  754. /**
  755. * 返还正在上庄的玩家底金
  756. */
  757. Model::build('banker_log')->returnCoin(['video_id' => $video_id, 'status' => ['in', [1, 3]]], '主播下庄');
  758. /**
  759. * 改变上庄状态
  760. */
  761. $field = ['game_id', 'option'];
  762. $data = self::$redis->get($last_log_id, $field);
  763. $option = json_decode($data['option'], 1);
  764. list($banker_status, $banker_id, $banker_log_id, $banker_name, $banker_img, $coin, $max_bet) = self::getBankerStatus($video_id, $option);
  765. $data = [
  766. 'banker_id' => 0,
  767. 'banker_status' => 0,
  768. "banker_log_id" => 0,
  769. "banker_name" => '',
  770. "banker_img" => '',
  771. 'coin' => 0,
  772. ];
  773. self::$video_redis->update_db($video_id, $data);
  774. /**
  775. * 群发下庄消息
  776. */
  777. $ext = [
  778. 'type' => 43,
  779. 'desc' => '',
  780. 'room_id' => $video_id,
  781. 'action' => 4,
  782. 'banker_status' => 0,
  783. 'data' => [
  784. 'banker' => compact(
  785. "banker_id",
  786. "banker_log_id",
  787. "banker_name",
  788. "banker_img",
  789. 'coin'
  790. ),
  791. ],
  792. ];
  793. $res = timSystemNotify($group_id, $ext);
  794. self::pushLog(compact('res', 'ext'));
  795. self::$redis->unLockVideo($video_id);
  796. self::returnError('', 1, $ext);
  797. }
  798. /**
  799. * 申请上庄
  800. * @return [type] [description]
  801. */
  802. public function applyBanker()
  803. {
  804. $coin = intval($_REQUEST['coin']);
  805. $video_id = intval($_REQUEST['video_id']);
  806. /**
  807. * 判断游戏状态
  808. */
  809. $user_id = self::getUserId();
  810. list(
  811. $last_game,
  812. $last_log_id,
  813. $banker_status,
  814. $banker_id
  815. ) = self::getLastGameByVideoId($video_id);
  816. if ($last_game) {
  817. self::returnError('上局游戏未结束');
  818. }
  819. if (!$banker_status) {
  820. self::returnError('已关闭上庄');
  821. }
  822. if ($banker_id) {
  823. self::returnError('已上庄');
  824. }
  825. $banker_log_model = Model::build('banker_log');
  826. $log = $banker_log_model->field('id')->selectOne(
  827. [
  828. 'user_id' => $user_id,
  829. 'video_id' => $video_id,
  830. 'status' => 1,
  831. ]
  832. );
  833. if ($log) {
  834. self::returnError('已经申请上庄啦!');
  835. }
  836. $game = self::$redis->get($last_log_id, 'game_id,group_id,podcast_id');
  837. $group_id = $game['group_id'];
  838. $game_id = $game['game_id'];
  839. $podcast_id = $game['podcast_id'];
  840. $game = self::getGameById($game_id, 'principal');
  841. if ($coin < $game['principal']) {
  842. self::returnError('上庄金额不能低于底金');
  843. }
  844. if (self::$redis->isVideoLock($video_id)) {
  845. self::returnError('服务器繁忙,请等下再点!');
  846. }
  847. /**
  848. * 添加上庄申请记录
  849. */
  850. $model = Model::build('user');
  851. // $res = $model->coin($user_id, -$coin);
  852. // if (!$res) {
  853. // self::returnError('余额不足');
  854. // }
  855. $account_diamonds = $model->coin($user_id);
  856. if ($account_diamonds < $coin) {
  857. self::returnError('余额不足');
  858. }
  859. // Model::build('coin_log')->addLog($user_id, -1, -$coin, $account_diamonds, '上庄底金');
  860. $banker_log_model->addLog($video_id, $user_id, $coin);
  861. $list = $banker_log_model->getBankerList($video_id, 20);
  862. foreach ($list as $value) {
  863. if ($value['coin'] < $coin || $value['banker_id'] == $user_id) {
  864. /**
  865. * 群发申请上庄消息
  866. */
  867. $ext = [
  868. 'type' => 43,
  869. 'desc' => '',
  870. 'room_id' => $video_id,
  871. 'action' => 2,
  872. 'banker_status' => 1,
  873. 'data' => [
  874. 'banker_list' => $list,
  875. ],
  876. ];
  877. $res = timSystemNotify($group_id, $ext, [$podcast_id]);
  878. self::pushLog(compact('res', 'ext'));
  879. break;
  880. }
  881. }
  882. self::returnError('上庄成功', 1, ['coin' => $account_diamonds]);
  883. }
  884. /**
  885. * 选庄
  886. * @return [type] [description]
  887. */
  888. public function chooseBanker()
  889. {
  890. $banker_log_id = intval($_REQUEST['banker_log_id']);
  891. /**
  892. * 判断游戏状态
  893. */
  894. $user_id = self::getUserId();
  895. list(
  896. $video_id,
  897. $group_id
  898. ) = self::getLiveVideoByUserId($user_id);
  899. list(
  900. $last_game,
  901. $last_log_id,
  902. $banker_status,
  903. $banker_id
  904. ) = self::getLastGameByVideoId($video_id);
  905. if ($last_game) {
  906. self::returnError('上局游戏未结束');
  907. }
  908. if (!$banker_status) {
  909. self::returnError('已关闭上庄');
  910. }
  911. if ($banker_id) {
  912. self::returnError('已上庄');
  913. }
  914. $model = Model::build('banker_log');
  915. $banker = $model->field('user_id,coin')->selectOne(
  916. [
  917. 'id' => $banker_log_id,
  918. 'video_id' => $video_id,
  919. 'status' => 1,
  920. ]
  921. );
  922. if (!$banker) {
  923. self::returnError('数据错误');
  924. }
  925. if (self::$redis->isVideoLock($video_id)) {
  926. self::returnError('操作频率太高了,请等下再点!');
  927. }
  928. self::$redis->lockVideo($video_id);
  929. $user_model = Model::build('user');
  930. $res = $user_model->coin($banker['user_id'], -$banker['coin']);
  931. if (!$res) {
  932. // $model->update(['status' => 2], ['id' => $banker_log_id]);
  933. self::$redis->unLockVideo($video_id);
  934. self::returnError('该玩家余额不足,请重新刷新列表');
  935. }
  936. $account_diamonds = $user_model->coin($banker['user_id']);
  937. Model::build('coin_log')->addLog($banker['user_id'], -1, -$banker['coin'], $account_diamonds, '上庄底金');
  938. /**
  939. * 改变上庄状态,退还未选中上庄玩家底金
  940. */
  941. $model->chooseBanker($banker_log_id, $video_id);
  942. $user = Model::build('user')->field('nick_name,head_image')->selectOne(['id' => $banker['user_id']]);
  943. $data = [
  944. 'banker_status' => 2,
  945. "banker_id" => intval($banker['user_id']),
  946. "banker_log_id" => $banker_log_id,
  947. "banker_name" => emoji_decode($user['nick_name']),
  948. "banker_img" => get_spec_image($user['head_image']),
  949. 'coin' => intval($banker['coin']),
  950. ];
  951. self::$video_redis->update_db($video_id, $data);
  952. unset($data['banker_status']);
  953. /**
  954. * 群发选庄消息
  955. */
  956. $ext = [
  957. 'type' => 43,
  958. 'desc' => '',
  959. 'room_id' => $video_id,
  960. 'action' => 3,
  961. 'banker_status' => 2,
  962. 'data' => [
  963. 'banker' => $data,
  964. ],
  965. ];
  966. $res = timSystemNotify($group_id, $ext);
  967. self::pushLog(compact('res', 'ext'));
  968. self::$redis->unLockVideo($video_id);
  969. self::returnError('', 1, $ext);
  970. }
  971. /**
  972. * 申请上庄玩家列表
  973. * @return [type] [description]
  974. */
  975. public function getBankerList()
  976. {
  977. $user_id = self::getUserId();
  978. list(
  979. $video_id,
  980. $group_id
  981. ) = self::getLiveVideoByUserId($user_id);
  982. $model = Model::build('banker_log');
  983. $banker_list = $model->getBankerList($video_id, 20);
  984. foreach ($banker_list as $key => $value) {
  985. $banker_list[$key]['banker_name'] = emoji_decode($value['banker_name']);
  986. }
  987. self::returnError('', 1, compact('banker_list'));
  988. }
  989. /**
  990. * 获取庄家状态
  991. * @return [type] [description]
  992. */
  993. public function getBankerCoin()
  994. {
  995. $id = intval($_REQUEST['id']);
  996. $video_id = intval($_REQUEST['video_id']);
  997. if (!$id && !$video_id) {
  998. self::returnError('参数错误');
  999. }
  1000. if (!$id && $video_id) {
  1001. $id = intval(self::$video_redis->getOne_db($video_id, 'game_log_id'));
  1002. }
  1003. $field = ['game_id', 'option', 'video_id'];
  1004. $data = self::$redis->get($id, $field);
  1005. $option = json_decode($data['option'], 1);
  1006. $video_id = intval($data['video_id']);
  1007. if ($data['game_id'] === false) {
  1008. self::returnError('游戏不存在');
  1009. }
  1010. list($banker_status, $banker_id, $banker_log_id, $banker_name, $banker_img, $coin, $max_bet) = self::getBankerStatus($video_id, $option);
  1011. self::returnError('', 1, ['data' => compact('banker_status', 'banker_id', 'banker_log_id', 'banker_name', 'banker_img', 'coin', 'max_bet')]);
  1012. }
  1013. /**
  1014. * 弹幕消息推送
  1015. * @param [type] $room_id [description]
  1016. * @param [type] $group_id [description]
  1017. * @param [type] $podcast_id [description]
  1018. * @param [type] $user_id [description]
  1019. * @param [type] $msg [description]
  1020. * @return [type] [description]
  1021. */
  1022. protected static function popMessage($room_id, $group_id, $podcast_id, $user_id, $msg)
  1023. {
  1024. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
  1025. $user_redis = new UserRedisService();
  1026. $user_info = $user_redis->getRow_db($user_id, array('nick_name', 'head_image', 'user_level', 'v_icon'));
  1027. $user_info['user_id'] = $user_id;
  1028. $user_info['head_image'] = get_spec_image($user_info['head_image']);
  1029. $user_info['nick_name'] = emoji_decode($user_info['nick_name']);
  1030. $ext = [
  1031. 'type' => 2, //0:普通消息;1:礼物;2:弹幕消息;3:主播退出;4:禁言;5:观众进入房间;6:观众退出房间;7:直播结束
  1032. 'room_id' => $room_id, //直播ID 也是room_id;只有与当前房间相同时,收到消息才响应
  1033. 'num' => 1,
  1034. 'prop_id' => 0, //礼物id
  1035. 'icon' => '', //图片,是否要: 大中小格式?
  1036. 'user_prop_id' => 0, //红包时用到,抢红包的id
  1037. 'total_ticket' => intval($user_redis->getOne_db($podcast_id, 'ticket')), //用户总的:印票数
  1038. 'to_user_id' => 0, //礼物接收人(主播)
  1039. 'fonts_color' => '', //字体颜色
  1040. 'desc' => $msg, //弹幕消息
  1041. 'desc2' => $msg, //弹幕消息
  1042. 'sender' => $user_info,
  1043. ];
  1044. $msg_content = array(
  1045. 'MsgType' => 'TIMCustomElem',
  1046. 'MsgContent' => array(
  1047. 'Data' => json_encode($ext),
  1048. 'Desc' => '',
  1049. ),
  1050. );
  1051. fanwe_require(APP_ROOT_PATH . 'system/tim/TimApi.php');
  1052. $api = createTimAPI();
  1053. $ret = $api->group_send_group_msg2($user_id, $group_id, [$msg_content]);
  1054. }
  1055. /**
  1056. * 分销收益列表
  1057. * @return [type] [description]
  1058. */
  1059. public function getDistributionList()
  1060. {
  1061. $user_id = self::getUserId();
  1062. $data = Model::build('game_distribution')->getDistributionList($user_id);
  1063. self::returnError('', 1, compact('data'));
  1064. }
  1065. /**
  1066. * 输入邀请码(定制)
  1067. * @return [type] [description]
  1068. */
  1069. public function invitationCode()
  1070. {
  1071. $user_id = self::getUserId();
  1072. $code = trim($_REQUEST['code']);
  1073. $model = Model::build('user');
  1074. $invitation_id = $model->getInvitationBycode($code);
  1075. if ($invitation_id == $user_id || !$invitation_id) {
  1076. self::returnError('邀请码错误!');
  1077. }
  1078. if ($model->update(compact('invitation_id'), ['id' => $user_id]) === false) {
  1079. self::returnError('失败');
  1080. } else {
  1081. self::returnError('成功', 1);
  1082. }
  1083. }
  1084. /**
  1085. * 验证邀请码(定制)
  1086. * @return [type] [description]
  1087. */
  1088. public function checkCode()
  1089. {
  1090. $user_id = self::getUserId();
  1091. $m_config = load_auto_cache("m_config");
  1092. if ($m_config['enter_invitation_code']) {
  1093. $has_invitation_code = intval(Model::build('user')->getInvitationId($user_id) > 0);
  1094. } else {
  1095. $has_invitation_code = 1;
  1096. }
  1097. $invitation_tip = $m_config['enter_invitation_code_tip'];
  1098. self::returnError('', 1, compact('has_invitation_code', 'invitation_tip'));
  1099. }
  1100. public function autoStart()
  1101. {
  1102. $user_id = self::getUserId();
  1103. $auto_start = intval($_REQUEST['auto_start']);
  1104. list(
  1105. $video_id,
  1106. $group_id
  1107. ) = self::getLiveVideoByUserId($user_id);
  1108. $data = compact('auto_start');
  1109. self::$video_redis->update_db($video_id, $data);
  1110. self::returnError('', 1, $data);
  1111. }
  1112. }