| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- <?php
- namespace App\Http\Controllers\Api;
- use App\Util;
- use Illuminate\Support\Facades\Redis;
- use App\Facade\TableName;
- use App\Http\Controllers\Controller;
- use App\Models\AccountsSource;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\DB;
- class GameApiController extends Controller
- {
- // 修改用户信息--【昵称,和头像】
- public function updateUserInfo(Request $request)
- {
- $FaceID = $request->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' =>'']);
- }
- }
- }
|