FaceID ?: ''; $NickName = $request->NickName ?: ''; $UserID = $request->UserID ?: ''; if (empty($UserID)) { return apiReturnFail(__('messages.api.game_api.user_info_lost')); } $data = compact('FaceID', 'NickName'); $data = array_filter($data); if (!empty($data)) { DB::table(TableName::QPAccountsDB() . 'AccountsInfo') ->where('UserID', $UserID) ->update($data); } return apiReturnSuc(); } // 用户来源 public function UserSource(Request $request) { $UserID = $request->input('UserID'); $Source = $request->input('Source'); $RequestDynamicPass = $request->input('DynamicPass'); // 验证用户信息 $DynamicPass = DB::table(TableName::QPAccountsDB() . 'AccountsInfo') ->where('UserID', $UserID) ->value('DynamicPass'); if ($DynamicPass != $RequestDynamicPass || empty($DynamicPass)) return apiReturnFail(__('messages.api.game_api.player_info_inconsistent')); (new AccountsSource())->notExistsInsert($UserID, $Source); return apiReturnSuc(); } public function billBoard(Request $request){ return $this->billBoard2($request); $UserID = $request->input('UserID'); $cachekey="Bill_board"; $myrank=10000; if(Redis::exists($cachekey)){ $boards=json_decode(Redis::get($cachekey),true); } $datekey=date("Ymd"); $datekey2=date("Ymd",time()-86400); if(!isset($boards)||Redis::ttl($cachekey)<305){ $boards=[]; $list = DB::connection('read')->table('QPAccountsDB.dbo.AccountsInfo as ai') ->leftJoin('QPRecordDB.dbo.RecordUserDataStatisticsNew as gi', 'ai.UserID', '=', 'gi.UserID') ->whereIn('gi.DateID',[$datekey,$datekey2]) ->orderBy('gi.WinScore','desc') ->limit(900) ->select(['ai.UserID','gi.WinScore as Score','ai.GameID','ai.NickName','ai.FaceID']) ->get()->toArray(); foreach ($list as $key=>$value){ $value=(array)$value; $value['FaceID']=intval($value['FaceID']); $value['Score']=floor($value['Score']/100)*100; $list[$key]=$value; } $all=Util::arraySort($list,'Score',SORT_DESC); foreach ($all as $key=>&$value){ $value['rank']=$key+1; } $boards=$all; Redis::set($cachekey,json_encode($boards)); //23:40以后冻结1小时 if(intval(date("H"))==23&&intval(date("i"))>=40){ Redis::expire($cachekey,3705); }else{ Redis::expire($cachekey,1205); } } foreach ($boards as $value){ if($value['UserID']==$UserID){ $myrank=$value['rank']; } } return apiReturnSuc(['ret' =>['myData'=>['rank'=>$myrank],'rank'=>array_slice($boards,0,100)]]); } public function billBoard2(Request $request){ $UserID = $request->input('UserID'); $cachekey="Bill_boardd"; $fakecachekey="Fake_Bill_boardd"; $myrank=10000; // 检查是否存在真实用户排行榜数据缓存 if(Redis::exists($cachekey)){ $boards=json_decode(Redis::get($cachekey),true); } $datekey=date("Ymd"); $datekey2=date("Ymd",time()-86400); // 获取真实用户排行榜数据 if(!isset($boards)||Redis::ttl($cachekey)<205){ $boards=[]; $list = DB::connection('read')->table('QPAccountsDB.dbo.AccountsInfo as ai') ->leftJoin('QPRecordDB.dbo.RecordUserDataStatisticsNew as gi', 'ai.UserID', '=', 'gi.UserID') ->whereIn('gi.DateID',[$datekey,$datekey2]) ->orderBy('gi.WinScore','desc') ->limit(900) ->select(['ai.UserID','gi.WinScore as Score','ai.GameID','ai.NickName','ai.FaceID']) ->get()->toArray(); foreach ($list as $key=>$value){ $value=(array)$value; $value['FaceID']=intval($value['FaceID']); $value['Score']=floor($value['Score']/100)*100; $list[$key]=$value; } $all=Util::arraySort($list,'Score',SORT_DESC); foreach ($all as $key=>&$value){ $value['rank']=$key+1; } $boards=$all; Redis::set($cachekey,json_encode($boards)); //23:40以后冻结1小时 if(intval(date("H"))==23&&intval(date("i"))>=40){ Redis::expire($cachekey,3705); }else{ Redis::expire($cachekey,805); } } // 生成和获取模拟用户数据 $fakeBoards = $this->generateFakeLeaderboard(); foreach ($fakeBoards as &$value){ $value=(array)$value; $value['FaceID']=intval($value['FaceID']); } // 合并真实和模拟用户数据 $combinedBoards = array_merge($boards, $fakeBoards); $combinedBoards = Util::arraySort($combinedBoards, 'Score', SORT_DESC); // 重新计算排名 foreach ($combinedBoards as $key=>&$value){ $value['rank'] = $key+1; if($value['UserID']==$UserID){ $myrank=$value['rank']; } } return apiReturnSuc(['ret' =>['myData'=>['rank'=>$myrank],'rank'=>array_slice($combinedBoards,0,100)]]); } /** * 生成模拟用户排行榜数据 * * @return array 模拟用户数据 */ private function generateFakeLeaderboard() { $fakeCacheKey = "Fake_Bill_boardd"; $fakeChangeCountKey = "Fake_Bill_Change_Count"; $fakeUserCount = 300; // 模拟用户最多300个 $now = time(); $todayDate = date('Ymd'); $todayKey = "fake_leaderboard_date"; // 检查是否是新的一天,如果是则重置 if (!Redis::exists($todayKey) || Redis::get($todayKey) != $todayDate) { Redis::del($fakeCacheKey); Redis::del($fakeChangeCountKey); Redis::set($todayKey, $todayDate); } // 如果缓存中存在模拟数据且未过期,直接返回 if (Redis::exists($fakeCacheKey) && Redis::ttl($fakeCacheKey) > 60) { $fakeBoards = json_decode(Redis::get($fakeCacheKey), true); // 判断是否需要更新模拟数据 $lastUpdateKey = "fake_leaderboard_last_update"; $lastUpdate = Redis::exists($lastUpdateKey) ? intval(Redis::get($lastUpdateKey)) : 0; $currentHour = intval(date('H')); $updateInterval = ($currentHour >= 0 && $currentHour < 10) ? 1800 : 600; // 0-10点每半小时,10点后每10分钟 if ($now - $lastUpdate >= $updateInterval) { $fakeBoards = $this->updateFakeUserScores($fakeBoards); Redis::set($lastUpdateKey, $now); } return $fakeBoards; } // 生成新的模拟用户数据 $fakeBoards = []; for ($i = 0; $i < $fakeUserCount; $i++) { $fakeBoards[] = $this->generateFakeUserData(); } // 按分数排序 $fakeBoards = Util::arraySort($fakeBoards, 'Score', SORT_DESC); // 保存到Redis Redis::set($fakeCacheKey, json_encode($fakeBoards)); Redis::expire($fakeCacheKey, 3600); // 缓存1小时 // 记录初次更新时间 Redis::set("fake_leaderboard_last_update", $now); return $fakeBoards; } private function generateFakeUserData() { $countryCode = env('COUNTRY_CODE', '92'); // 默认使用巴基斯坦区号 $userID = "99" . mt_rand(1000000, 9999999); $gameID = "1" . mt_rand(1000000, 9999999); $score = mt_rand(-15000, 35000); // -15000到35000 return [ "UserID" => $userID, "Score" => $score*100, "GameID" => $gameID, "NickName" => $this->generateFakeName($countryCode, $gameID), "FaceID" => mt_rand(1, 16), "rank" => 0, // 初始rank,会在合并后重新计算 "change_count" => 0 // 变化次数统计 ]; } /** * 更新模拟用户分数 * * @param array $fakeBoards 现有模拟用户数据 * @return array 更新后的模拟用户数据 */ private function updateFakeUserScores($fakeBoards) { $fakeChangeCountKey = "Fake_Bill_Change_Count"; $changeCountMap = []; // 获取现有的变化次数记录 if (Redis::exists($fakeChangeCountKey)) { $changeCountMap = json_decode(Redis::get($fakeChangeCountKey), true); } // 确保总体上有增长趋势 $increasedCount = 0; $minIncrease = count($fakeBoards) * 0.3; // 至少30%的用户要增加 foreach ($fakeBoards as $key => &$user) { $userID = $user['UserID']; // 初始化变化次数记录 if (!isset($changeCountMap[$userID])) { $changeCountMap[$userID] = 0; } // 50%的概率进行变化 if (mt_rand(0, 1) == 1) { // 如果变化次数超过70次,则不再变化 if ($changeCountMap[$userID] >= 70) { continue; } if(intval(date('H'))>=11){ $newScore=intval( $user['Score']*mt_rand(70,140)/100); if($newScore>$user['Score'])$increasedCount++; $user['Score'] = $newScore; }else { // 动态回报率,基础值10000 $changeAmount = mt_rand(-15000, 35000); // 基础值上下浮动 $user['Score'] += $changeAmount * 100; if($changeAmount>0){ $increasedCount++; } // 决定是增加还是减少 // if ($increasedCount < $minIncrease) { // // 强制增加以满足最低增长要求 // $user['Score'] += $changeAmount * 100; // $increasedCount++; // } else { // // 随机增减 // if (mt_rand(0, 1) == 1) { // $user['Score'] += $changeAmount * 100; // $increasedCount++; // } else { // $user['Score'] -= $changeAmount * 100; // // } // } } // 更新变化次数 $changeCountMap[$userID]++; } } // 控制模拟用户总数不超过300 $maxUsers = 300; if (count($fakeBoards) < $maxUsers) { // 每次增加少量新用户 $newUsersCount = min(5, $maxUsers - count($fakeBoards)); for ($i = 0; $i < $newUsersCount; $i++) { $fakeBoards[] = $this->generateFakeUserData(); } } // 重新按分数排序 $fakeBoards = Util::arraySort($fakeBoards, 'Score', SORT_DESC); // 更新Redis缓存 Redis::set("Fake_Bill_boardd", json_encode($fakeBoards)); Redis::expire("Fake_Bill_boardd", 3600); // 更新变化次数记录 Redis::set($fakeChangeCountKey, json_encode($changeCountMap)); Redis::expire($fakeChangeCountKey, 86400); // 缓存一天 return $fakeBoards; } /** * 根据国家代码生成模拟用户名 * * @param string $countryCode 国家代码 * @param string $gameID 游戏ID * @return string 生成的用户名 */ private function generateFakeName($countryCode, $gameID) { $lastFourDigits = substr($gameID, -4); // 根据国家代码生成不同国家风格的名字 switch ($countryCode) { case '92': // 巴基斯坦 $pakFirstNames = ['Ahmed', 'Muhammad', 'Ali', 'Hassan', 'Saeed', 'Omar', 'Yousaf', 'Imran', 'Tariq', 'Asif', 'Zain', 'Bilal', 'Faisal', 'Khalid', 'Malik']; $pakLastNames = ['Khan', 'Malik', 'Ali', 'Ahmed', 'Shah', 'Qureshi', 'Baloch', 'Siddiqui', 'Raza', 'Javed', 'Iqbal', 'Akbar', 'Aslam']; if (mt_rand(0, 1) == 0) { // 有50%概率使用首字母+数字格式 return 'U' . $lastFourDigits; } else { // 有50%概率使用巴基斯坦名字 return $pakFirstNames[array_rand($pakFirstNames)] . substr($pakLastNames[array_rand($pakLastNames)], 0, 1); } default: // 默认格式 return 'U' . $lastFourDigits; } } public static function webGameRooms() { if(!Redis::exists('webgamerooms')) { $webgames = DB::table('QPPlatformDB.dbo.GameRoomInfo')->select('ServerID', 'SortID', 'GameID', 'CellScore', 'MinEnterScore')->where('GameID', '>', 9000)->get()->toArray(); $sorts = []; foreach ($webgames as &$value) { $value = (array)$value; $value['SortID'] = intval($value['SortID']); $value['ServerID'] = intval($value['ServerID']); $value['MinEnterScore'] = intval($value['MinEnterScore']); $value['CellScore'] = intval($value['CellScore']); $sorts[$value['GameID']][$value['SortID']] = $value; } Redis::setex('webgamerooms', 600,json_encode($sorts)); }else{ $sorts=Redis::get('webgamerooms'); $sorts=json_decode($sorts,true); } return $sorts; } public function onlineList(Request $request){ try { if (Redis::exists('Online_Real')) { $online = Redis::get('Online_Real'); $online = json_decode($online, true); } $field = ['gi.GameID', 'gi.Nullity', 'gi.SortID', 'gi.ServerName', 'gi.ServerID']; $list = DB::connection('read')->table('QPPlatformDB.dbo.GameRoomInfo as gi') ->whereIn('GameID', config('games.openKGame')) ->leftJoin('QPTreasureDB.dbo.GameScoreLocker as gl', function ($query) { $query->on('gl.ServerID', 'gi.ServerID')->selectRaw('gl.ServerID')->groupBy('ServerID')->whereRaw('datediff(hh,gl.CollectDate,getdate())<=5'); }) ->select($field) // ->where('Nullity', 0) ->selectRaw('IsNull(count(DISTINCT gl.UserID),0) as game_count') ->groupBy($field) ->orderBy('gi.GameID', 'asc') ->orderBy('gi.ServerName', 'asc'); if (!isset($online) || Redis::ttl('Online_Real') < 5) { if($request->exists("hh")){ dd($list->toSql(),json_encode(config('games.openKGame'))); }else { $list=$list->get()->toArray(); } $online = []; foreach ($list as $item) { $item = (array)$item; if (!isset($item) || !isset($item['GameID'])) continue; if (!isset($item['game_count'])) $item['game_count'] = 0; if (isset($online[$item['GameID']])) { if (!isset($online[$item['GameID']][$item['SortID']])) $online[$item['GameID']][$item['SortID']] = 0; $online[$item['GameID']][$item['SortID']] += intval($item['game_count']) ?: mt_rand(100, 200) / 1000; } else { $online[$item['GameID']] = [1 => 0.3, 2 => 0.2, 3 => 0.1]; $online[$item['GameID']][$item['SortID']] = intval($item['game_count']) ?: mt_rand(100, 200) / 1000; } } foreach ($online as $gid => &$ol) { $base=$ol[1]+$ol[2]; $ol[1] = intval($base * 168); $ol[2] = intval($base *20); $ol[3] = intval($base *2); if(count($ol)>3){ $ol[2] = intval($base * 168); $ol[3] = intval($base *20); $ol[4] = intval($base *2); } } foreach ($online as $gid => &$ol) { $total=0; foreach ($ol as $count){ $total+=$count; } $online[$gid]=['a0'=>$total]; } Redis::set('Online_Real', json_encode($online)); Redis::expire('Online_Real', 65); } return apiReturnSuc(['ret' => $online]); }catch (\Exception $e){ Util::WriteLog('online_error',$e->getMessage().$e->getTraceAsString()); return apiReturnSuc(['ret' =>'']); } } }