rank.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <?php
  2. /**
  3. * 排行榜相关
  4. */
  5. class ModelRank
  6. {
  7. protected $moneyRankLimit = 200; //世界排行榜
  8. protected $friMoneyRankLimit = 200; //好友排行榜人数限制
  9. protected $friNumLimit = 500; //好友人数限制
  10. protected $worldRankSum =1000;//最大世界排行
  11. protected $countryRankSum = 50;//最大国家排行
  12. protected $countryMaster =['RO','US','DE','GB','ES','FR','IN'];//主要国家:罗马尼亚,美国,德国,英国,西班牙,法国,印度,其他
  13. protected $rankMinStar = 2000; //正式服排行榜最小上榜值
  14. /**
  15. * Notes:获取排行榜信息
  16. * User: wsc
  17. * Time: 2020/5/6 19:26
  18. * @param $uid
  19. * @param bool $falg
  20. * @return array
  21. */
  22. public function getStaRank($uid,$falg=false){
  23. $my_friend_num = $my_country_num = 0;
  24. //好友榜
  25. $friendRankList = $this->getFriendRank($uid);
  26. //世界排行
  27. $friends = oo::commonOprModel('friend')->getUserAllFriend($uid);
  28. $worldRankList = $this->getWorldStaRank();
  29. foreach ($worldRankList as $k=>$v){
  30. $worldRankList[$k]['isFri'] = in_array($v['uid'],$friends)?1:0;
  31. }
  32. //国家排行
  33. $countryList = $this->getCountryRank($uid);
  34. $myRank = $this->getMyRank($uid);
  35. foreach ($friendRankList as $k=>$v){
  36. if($v['uid']==$uid){
  37. $my_friend_num = $k+1;
  38. }
  39. }
  40. $myRank['my_friend_rank'] = $my_friend_num;
  41. if(!empty($countryList)){
  42. foreach ($countryList as $k=>$v){
  43. if($v['uid']==$uid){
  44. $my_country_num = $k+1;
  45. }
  46. }
  47. $myRank['my_country_rank'] = $my_country_num<=$this->countryRankSum&&$my_country_num>0?$my_country_num:">".$this->countryRankSum;
  48. $countryList = array_values($countryList);
  49. }else{
  50. $countryList = [];
  51. $myRank['my_country_rank'] =0;
  52. }
  53. $myRank['max_worldRank'] = $this->worldRankSum;
  54. $myRank['max_countryRank'] = $this->countryRankSum;
  55. $data = [
  56. "code"=>1,
  57. "list"=>[
  58. "fir"=>$friendRankList,
  59. "world"=>array_values($worldRankList),
  60. "self"=>$myRank,
  61. "country"=>$countryList,
  62. ]
  63. ];
  64. oo::commonOprRedis('User')->setex(okeys::UserRankData($uid),json_encode([
  65. 'friend' => $myRank['my_friend_rank'],
  66. 'country' => $myRank['my_country_rank'],
  67. 'world' => $myRank['pos'],
  68. ]),oo::redisRandomExpire(3*24*60*60));
  69. return $data;
  70. }
  71. /**
  72. * Notes:获取我的世界排名
  73. * User: wsc
  74. * Time: 2020/5/6 19:25
  75. * @param $uid
  76. * @return array
  77. */
  78. public function getMyRank($uid){
  79. $data = [];
  80. $info = oo::commonOprModel('member')->getUserBasic($uid);
  81. $stakey = okeys::worldStaRank();
  82. $res = oo::commonOprRedis('common')->zRevRank($stakey,$uid);
  83. $data['pos'] = $res?$res:">".$this->worldRankSum;
  84. $data['star'] = $info['star'];
  85. $data['nick'] = oo::commonOprModel('member')->getUserFirstName($info['nick']);
  86. $data['s_picture'] = $info['s_picture'];
  87. $data['u_flag'] = $info['u_flag'];
  88. return $data;
  89. }
  90. /**
  91. * Notes:获取我的好友排行榜
  92. * User: wsc
  93. * Time: 2020/5/6 19:25
  94. * @param $uid
  95. * @return array
  96. */
  97. public function getFriendRank($uid){
  98. $friends = oo::commonOprModel('friend')->getUserAllFriend($uid);
  99. $fbList = oo::commonOprModel('friend')->getUserAllFriend($uid,'fb');
  100. array_push($friends,$uid);
  101. $friends = array_unique($friends);
  102. foreach ($friends as $k=>$v){
  103. $friendRankList[$k] = oo::commonOprModel('member')->getUserBasic($v);
  104. $infoArr = oo::commonOprModel('member')->getAccount($friendRankList[$k]['siteuid']);
  105. $friendRankList[$k]['isFb'] =!empty($infoArr) && $infoArr['uid'] == $v?1:0;
  106. unset($friendRankList[$k]['spins']);
  107. unset($friendRankList[$k]['shield']);
  108. // unset($friendRankList[$k]['coins']);
  109. unset($friendRankList[$k]['siteuid']);
  110. $friendRankList[$k]['isFbFriend'] = in_array($v,$fbList)?1:0;
  111. $friendRankList[$k]['build'] = oo::commonOprModel('member')->getUserLevel($v)['element'];
  112. }
  113. array_multisort(array_column($friendRankList,'star'),SORT_DESC,array_column($friendRankList,'money'),SORT_DESC,$friendRankList);
  114. $friendRankList =count($friendRankList)>$this->friMoneyRankLimit? array_slice($friendRankList,0,$this->friMoneyRankLimit):$friendRankList;
  115. return $friendRankList;
  116. }
  117. /**
  118. * Notes:获取世界排行(定时传参true刷新)
  119. * User: wsc
  120. * Time: 2020/5/6 19:24
  121. * @param bool $db
  122. * @return array
  123. */
  124. public function getWorldStaRank($db=false){
  125. $cache= [];
  126. $wkey = okeys::worldRankInfo();
  127. if(!$db){
  128. $jsonStr =oo::commonOprRedis('common')->hGetAll($wkey);
  129. $cache = funs::getArrFromJsonArr($jsonStr);
  130. array_multisort(array_column($cache,'star'),SORT_DESC,array_column($cache,'money'),SORT_DESC,$cache);
  131. }
  132. if(empty($cache)){
  133. oo::commonOprRedis('common')->delete($wkey);
  134. $rankList = $this->newWorldStaRank($db);
  135. $i=0;
  136. foreach ($rankList as $k=>$v){
  137. $cache[$i] = $this->getUserSomeInfo($k);
  138. $data[$i] = json_encode($cache[$i]);
  139. $i++;
  140. }
  141. oo::commonOprRedis('common')->hMset($wkey,$data);
  142. }
  143. return $cache;
  144. }
  145. /**
  146. * Notes:更新世界排行
  147. * User: wsc
  148. * Time: 2020/5/20 19:49
  149. * @param bool $db
  150. * @return array
  151. */
  152. public function newWorldStaRank($db=false){
  153. $cache = [];
  154. $max = oo::commonOprModel('readconfig')->getCon('Rank','maxNum');
  155. $stakey = okeys::worldStaRank();
  156. if(!$db){
  157. $cache =oo::commonOprRedis('common')->zRevRange($stakey,0,49,true);
  158. }
  159. if(empty($cache)){
  160. $tb = otable::gh_gameserver(1);
  161. $sql = "SELECT mid as uid,star FROM {$tb} ORDER BY star DESC,money DESC LIMIT {$this->worldRankSum}";
  162. $arr = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  163. if(!empty($arr)){
  164. oo::commonOprRedis('common')->delete($stakey);
  165. foreach ($arr as $k=>$v){
  166. oo::commonOprRedis('common')->zAdd($stakey,$v['star'],$v['uid']);
  167. $cache[$v['uid']] = $v['star'];
  168. }
  169. $cache = array_slice($cache,0,50,true);
  170. // oo::logs()->debug3(["do"=>'update worldRank is success',"data"=>$cache],'worldRank.log');
  171. }
  172. }
  173. return $cache;
  174. }
  175. /**
  176. * Notes:获取个人国家排行榜
  177. * User: wsc
  178. * Time: 2020/5/20 19:59
  179. * @param $uid
  180. * @return array
  181. */
  182. public function getCountryRank($uid){
  183. $info = oo::commonOprModel('ipaddress')->getUserCountry($uid);
  184. $ckey = okeys::countryRank($info['showCode']);
  185. $jsonStr =oo::commonOprRedis('common')->hGetAll($ckey);
  186. $cache = funs::getArrFromJsonArr($jsonStr);
  187. if(empty($cache)){
  188. return [];
  189. }
  190. array_multisort(array_column($cache,'star'),SORT_DESC,array_column($cache,'money'),SORT_DESC,$cache);
  191. return $cache;
  192. }
  193. /**
  194. * Notes:更新国家排行(新版)
  195. * User: richard
  196. * Time: 2021/3/30 18:29
  197. * @return array
  198. */
  199. public function newCountryRank(){
  200. $tb = otable::useraddress();
  201. $tb2 = otable::gh_gameserver(1);
  202. $minStar = IS_DEBUF ? 500 : $this->rankMinStar; //最小星星上榜值
  203. $min = 0;
  204. //设置主要国家排行
  205. foreach ($this->countryMaster as $country_code){
  206. $ckey = okeys::countryRank($country_code);
  207. $tmp = oo::commonOprRedis('common')->hGet($ckey, 49); //找到最后一名的数据
  208. if(empty($tmp)){ //如果没有50名排行,找最小的一个
  209. $tmpArr = oo::commonOprRedis('common')->hGetAll($ckey);
  210. krsort($tmpArr);
  211. $tmp = $tmpArr ? current($tmpArr) : [];
  212. }
  213. $lastRank = $tmp ? (array)json_decode($tmp, true) : [];
  214. $star = !empty($lastRank['star']) ? $lastRank['star'] : $this->rankMinStar;
  215. if(empty($min) || $min > $star){
  216. $min = $star;
  217. }
  218. }
  219. $ckey2 = okeys::countryRank("OTHER");
  220. $tmp = oo::commonOprRedis('common')->hGet($ckey2, 49); //找到最后一名的数据
  221. $lastRank = $tmp ? (array)json_decode($tmp, true) : [];
  222. $star = !empty($lastRank['star']) ? $lastRank['star'] : $this->rankMinStar;
  223. $min = $min > $star ? $star : $min;
  224. $min = empty($min) ? $minStar : $min;
  225. $sql = "SELECT mid,star FROM {$tb2} WHERE star >= {$min} ORDER BY star DESC";
  226. $tmpList = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  227. $rankUids = $tmpList ? array_column($tmpList, 'mid') : [];
  228. if(empty($rankUids)){
  229. return [[], []];
  230. }
  231. $cache = $data = [];
  232. foreach ($this->countryMaster as $country_code){
  233. $uidList = [];
  234. for($i = 0; $i < count($rankUids); $i=$i+5000){
  235. $tmpUids = array_slice($rankUids, $i, 5000);
  236. $uidStr = implode(',', $tmpUids);
  237. $sql = "SELECT uid FROM {$tb} WHERE country_code = '{$country_code}' AND uid IN({$uidStr})";
  238. $tmpUids = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  239. $uidList = array_merge($uidList, $tmpUids);
  240. }
  241. if(empty($uidList)){
  242. return [];
  243. }
  244. $ckey = okeys::countryRank($country_code);
  245. $uids = array_column($uidList, 'uid');
  246. oo::commonOprRedis('common')->delete($ckey);
  247. $index = 0;
  248. $cache = $data = [];
  249. foreach($rankUids as $uid){
  250. if(!in_array($uid, $uids)){
  251. continue;
  252. }
  253. $cache[$index] = $this->getUserSomeInfo($uid);
  254. $data[$index] = json_encode($cache[$index]);
  255. $index++;
  256. if($index > 49){
  257. break;
  258. }
  259. }
  260. oo::commonOprRedis('common')->hMset($ckey,$data);
  261. }
  262. //设置其他国家排行
  263. $masterStr = '"'.implode('","',$this->countryMaster).'"';
  264. $sql = "SELECT uid FROM {$tb} WHERE country_code NOT IN($masterStr) AND uid IN({$uidStr})";
  265. $uidList = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  266. if(empty($uidList)){
  267. return [$data, []];
  268. }
  269. $uids = array_column($uidList, 'uid');
  270. oo::commonOprRedis('common')->delete($ckey2);
  271. $index = 0;
  272. $cache2 = $data2 = [];
  273. foreach($rankUids as $uid){
  274. if(!in_array($uid, $uids)){
  275. continue;
  276. }
  277. $cache2[$index] = $this->getUserSomeInfo($uid);
  278. $data2[$index] = json_encode($cache[$index]);
  279. $index++;
  280. if($index > 49){
  281. break;
  282. }
  283. }
  284. oo::commonOprRedis('common')->hMset($ckey2,$data2);
  285. return [$data,$data2];
  286. }
  287. /**
  288. * Notes:更新国家排行(旧版)
  289. * User: wsc
  290. * Time: 2020/5/20 19:59
  291. * @return array
  292. */
  293. public function newCountryRankOld(){
  294. $tb = otable::useraddress();
  295. $tb2 = otable::gh_gameserver(1);
  296. //设置主要国家排行
  297. foreach ($this->countryMaster as $country_code){
  298. $sql = "SELECT a.uid,a.country_code,b.star FROM {$tb} a LEFT JOIN {$tb2} b ON a.uid=b.mid WHERE a.country_code='{$country_code}' order by b.star DESC LIMIT 50";
  299. $list = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  300. $ckey = okeys::countryRank($country_code);
  301. if(!empty($list)){
  302. $i=0;
  303. oo::commonOprRedis('common')->delete($ckey);
  304. foreach ($list as $k=>$v){
  305. $cache[$i] = $this->getUserSomeInfo($v['uid']);
  306. $data[$i] = json_encode($cache[$i]);
  307. $i++;
  308. }
  309. oo::commonOprRedis('common')->hMset($ckey,$data);
  310. }
  311. }
  312. //设置其他国家排行
  313. $masterStr = '"'.implode('","',$this->countryMaster).'"';
  314. $sql = "SELECT a.uid,a.country_code,b.star FROM {$tb} a LEFT JOIN {$tb2} b ON a.uid=b.mid WHERE a.country_code NOT IN({$masterStr}) ORDER BY b.star DESC LIMIT 50";
  315. $list2 = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  316. $ckey2 = okeys::countryRank("OTHER");
  317. $i=0;
  318. foreach ($list2 as $k=>$v){
  319. oo::commonOprRedis('common')->delete($ckey2);
  320. $cache[$i] = $this->getUserSomeInfo($v['uid']);
  321. $data2[$i] = json_encode($cache[$i]);
  322. $i++;
  323. oo::commonOprRedis('common')->hMset($ckey2,$data2);
  324. }
  325. return [$data,$data2];
  326. }
  327. public function getUserSomeInfo($uid){
  328. $cache = oo::commonOprModel('member')->getUserBasic($uid);
  329. $infoArr = oo::commonOprModel('member')->getAccount($cache['siteuid']);
  330. $cache['isFb'] =!empty($infoArr) && $infoArr['uid'] == $uid?1:0;
  331. $cache['fbId'] = $cache['siteuid'];
  332. $cache['build'] = oo::commonOprModel('member')->getUserLevel($uid)['element'];
  333. unset($cache['spins']);
  334. unset($cache['shield']);
  335. // unset($cache['coins']);
  336. unset($cache['siteuid']);
  337. return $cache;
  338. }
  339. }