game2006api/webapp/controller/SeasonController.class.php
hujiabin 8d162f3917 1
2022-10-28 11:44:42 +08:00

406 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once('mt/Parameter.php');
require_once('mt/Rank.php');
require_once('mt/Season.php');
require_once('mt/Drop.php');
require_once('mt/RankSeason.php');
require_once('models/User.php');
require_once('models/Season.php');
require_once('models/Mission.php');
require_once('services/AwardService.php');
require_once('services/PropertyChgService.php');
require_once('services/SeasonService.php');
require_once('services/MissionService.php');
use phpcommon\SqlHelper;
use models\User;
use models\Season;
use models\Mission;
class SeasonController extends BaseAuthedController {
private $propertyChgService = null;
private $awardService = null;
private $userInfo = null;
private $currRankSeasonMeta = null;
private $seasonDb = null;
private $missionService = null;
private $rankingUnid = 'game_2006_rank';
private $TopXunid = 'echelon_TopX_';
private $starshine = 2800;
public function _handlePre()
{
parent::_handlePre();
$this->currRankSeasonMeta = mt\RankSeason::getCurrentSeason();
if (!$this->currRankSeasonMeta) {
$this->_rspErr(10, 'server internal error');
die();
}
$this->propertyChgService = new services\PropertyChgService();
$this->awardService = new services\AwardService();
$this->userInfo = $this->_safeGetOrmUserInfo();
$this->seasonDb = Season::find($this->currRankSeasonMeta['id']);
if (!$this->seasonDb) {
Season::add($this->currRankSeasonMeta['id']);
$this->seasonDb = Season::find($this->currRankSeasonMeta['id']);
}
if (!$this->seasonDb) {
$this->_rspErr(10, 'server internal error');
die();
}
$this->missionService = new services\MissionService();
$this->missionService->init($this->userInfo, $this->seasonDb);
}
public function info()
{
$rankMeta = mt\Rank::get($this->userInfo['rank']);
$this->_rspData(array(
'info' => array(
'season_id' => $this->currSeasonMeta['id'],
'rank' => $this->userInfo['rank'],
'score' => $this->userInfo['score'],
'max_score' => $rankMeta ? $rankMeta['max_score'] : 0,
'noshow_score_bar' => $rankMeta ? $rankMeta['noshow_score_bar'] : 1,
'mission' => $this->getMissionInfo()
)
));
}
public function infoNew()
{
// $r = $this->_getRedis($this->TopXunid.'4');
// $TopX_List = $this->readRankingList($r,$this->TopXunid.'5');
// $XX = $TopX_List ? $TopX_List[0]["rank_sort"]:10001;
// print_r($XX);
// die;
$rankMeta = mt\Rank::getRankById($this->userInfo['rank']);
$nextRankMeta = mt\Rank::getNextRankById($this->userInfo['rank']);
if (!$nextRankMeta){
$nextRankMeta = mt\Rank::getMaxRank();
}
$info = array(
'season_name' => $this->currRankSeasonMeta['name'],
'rank' => $this->userInfo['rank'],
'rank_name' => $rankMeta['rank_name'],
'score' => $this->userInfo['score'],
'next_score' => $nextRankMeta['rank_score'],
'season_end_time' => strtotime($this->currRankSeasonMeta['end_time']),
'season_reward' => Season::seasonReward($rankMeta)
);
$r = $this->_getRedis($this->rankingUnid);
$rankList = $this->readRankingList($r,$this->rankingUnid);
$list = array();
if (!$rankList){
$rankList = $this->checkRankingList();
$this->saveRankingList($r,$this->rankingUnid,$rankList);
}
foreach ($rankList as $v){
if ($this->userInfo['rank'] == $v['rank'] && count($list) < 20){
array_push($list,$v);
}
}
$info['season_rank'] = $rankList;
$this->_rspData(['info'=>$info]);
}
public function getRankingInfo(){
$rank_param = getReqVal('rank',0);
if (!$rank_param){
$this->_rspErr(1, 'params rank error');
die();
}
$r = $this->_getRedis($this->rankingUnid);
$rankList = $this->readRankingList($r,$this->rankingUnid);
$list = array();
if (!$rankList){
$rankList = $this->checkRankingList();
$this->saveRankingList($r,$this->rankingUnid,$rankList);
}
foreach ($rankList as $v){
if ($rank_param == $v['rank'] && count($list) < 20){
array_push($list,$v);
}
}
$this->_rspData(['info'=>$list]);
}
public function getDataInfo(){
$seasonDb = Season::find($this->currRankSeasonMeta['id']);
$currRankSeasonHistory = array();
if ($seasonDb){
$battleData = json_decode($seasonDb['battle_data'], true);
$seasonBattleData = isset($battleData) ? getXVal($battleData, 'season_data', array()) : array();
$gameTimes = getXVal($seasonBattleData, 'total_battle_times', 0);
$winTimes = getXVal($seasonBattleData, 'total_win_times', 0);
$topTenTimes = getXVal($seasonBattleData, 'total_top_ten_times', 0);
$totalKills = getXVal($seasonBattleData, 'total_kills_times', 0);
$currRankSeasonHistory= array(
'season_id' => $seasonDb['season_id'],
// 'total_kills' => $totalKills,
'game_times' => $gameTimes,
'win_times' => $winTimes,
'top_ten_times' => $topTenTimes,
'kill_killed' => round($totalKills/($gameTimes-$winTimes),2),
);
}
if (!$currRankSeasonHistory){
$currRankSeasonHistory = array(
'season_id' => $this->currRankSeasonMeta['id'],
// 'total_kills' => $totalKills,
'game_times' => 0,
'win_times' => 0,
'top_ten_times' => 0,
'kill_killed' => 0,
);
}
$this->_rspData(['info'=>$currRankSeasonHistory]);
}
public function getHeroInfo(){
$seasonDb = Season::find($this->currRankSeasonMeta['id']);
$currHeroSeasonHistory = array();
if ($seasonDb) {
$battleData = json_decode($seasonDb['battle_data'], true);
$seasonBattleData = isset($battleData) ? getXVal($battleData, 'season_data', array()) : array();
$seasonHeroInfo = isset($seasonBattleData) ? getXVal($seasonBattleData, 'hero_info', array()) : array();
$heroSort = array();
foreach ($seasonHeroInfo as $key=>$heroInfo){
$heroSort[$key]['use_times'] = isset($heroInfo['use_times']) ? $heroInfo['use_times'] : 0;
$heroSort[$key]['weapon'] = isset($heroInfo['weapon']) ? $heroInfo['weapon'] : array();
$heroSort[$key]['win_times'] = isset($heroInfo['win_times']) ? $heroInfo['win_times'] : 0;
$heroSort[$key]['top_ten_times'] = isset($heroInfo['top_ten_times']) ? $heroInfo['top_ten_times'] : 0;
$heroSort[$key]['hero'] = $key;
arsort($heroSort[$key]['weapon']);
$heroSort[$key]['weapon'] = array_keys($heroSort[$key]['weapon']);
$heroSort[$key]['weapon'] = implode('|',array_slice($heroSort[$key]['weapon'],0,2));
}
arsort($heroSort);
$heroSort = array_slice($heroSort,0,3);
foreach ($heroSort as &$value){
$value['season_id'] = $seasonDb['season_id'];
$value['win_rate'] = round($value['win_times']/$value['use_times'],2);
$value['top_ten_rate'] = round($value['top_ten_times']/$value['use_times'],2);
}
$currHeroSeasonHistory = $heroSort;
}
// if (!$currHeroSeasonHistory){
// array_push($currHeroSeasonHistory,
// array(
// 'season_id' => $this->currRankSeasonMeta['id'],
// 'use_times' => 0,
// 'weapon' => 0,
// 'win_times' => 0,
// 'top_ten_times' => 0,
// 'hero_id' => 0,
// 'win_rate' => 0,
// 'top_ten_rate' => 0,
// ));
// }
$this->_rspData(['info'=>$currHeroSeasonHistory]);
}
public function getMissionReward()
{
$mission = $this->getMissionInfo();
if (!$mission || $mission['state'] != Mission::RECEIVEABLE_STATE) {
$this->_rspErr(1, 'Can not receive');
return;
}
$missionMeta = mt\Task::get($this->currSeasonMeta['task_id']);
$missionId = $this->currSeasonMeta['task_id'];
if (!$missionMeta) {
$this->_rspErr(10, 'server internal error');
return;
}
$dropMeta = mt\Drop::get($missionMeta['reward']);
if (!$dropMeta) {
$this->_rspErr(10, 'server internal error');
return;
}
$this->_scatterDrop('mission:' . $missionId, $dropMeta, $this->awardService, $this->propertyChgService);
Mission::add($missionId);
$missionDb = Mission::find($missionId);
$missionDto = $this->missionService->getMissionDto(
$this->userInfo,
$this->seasonDb,
$missionDb,
$missionMeta);
$this->_rspData(array(
'award' => $this->awardService->toDto(),
'property_chg' => $this->propertyChgService->toDto(),
));
}
private function getMissionInfo()
{
$info = array(
'state' => Mission::NOT_FINISHED_STATE,
'current' => 0,
'target' => 0,
'target_rank' => 0
);
$missionMeta = mt\Task::get($this->currSeasonMeta['task_id']);
if ($missionMeta) {
$info['target_rank'] = $missionMeta['param1'];
$info['target'] = $missionMeta['target'];
$missionDb = Mission::find($missionMeta['id']);
$missionDto = $this->missionService->getMissionDto(
$this->userInfo, $this->seasonDb, $missionDb, $missionMeta);
if ($missionDto) {
$info['state'] = $missionDto['state'];
$info['current'] = $missionDto['current'];
$info['target'] = $missionDto['target'];
}
}
return $info;
}
private function checkRankingList(){
$rankList = array();
$users = User::orderBy(User::allUser());
$rewardParamMeta = \mt\Parameter::getByName('rank_ring_reward');
$rewardParamMetaValue = $rewardParamMeta ? $rewardParamMeta['param_value'] : '';
$rewardList = explode('|',$rewardParamMetaValue);
if (count($users)>0){
$KingCount = 0;
foreach ($users as $k=>$user){
$userDto = User::getUserByRankMess($user);
$userDto['rank_sort'] = $k+1;
if ($userDto['score'] >= $this->starshine){
$KingCount += 1;
$userDto['echelonTopX'] = $this->echelonTopX($userDto['rank_sort']);
$r = $this->_getRedis($this->TopXunid.$userDto['echelonTopX']);
$TopX_List = $this->readRankingList($r,$this->TopXunid.$userDto['echelonTopX']);
array_push($TopX_List,$userDto);
$this->saveRankingList($r,$this->TopXunid.$userDto['echelonTopX'],$TopX_List);
}
switch ($userDto['rank_sort']){
case 1:$userDto['ring_item_id'] = $rewardList[0];break;
case 2:$userDto['ring_item_id'] = $rewardList[1];break;
case 3:$userDto['ring_item_id'] = $rewardList[2];break;
default : $userDto['ring_item_id'] = 0;
}
array_push($rankList,$userDto);
}
//当月排位赛最大分配金额
$maxSum = $this->calcCECMaxSum();
//排位赛参与分配人数
// $PeopleCapita = $this->calcPeopleCapita($KingCount);
//排位赛人数%
// $PeopleCapitaPer = $this->calcPeopleCapitaPer($KingCount);
//排位赛预计分配额
$expected_CEC_Sum = 0;
foreach ($rankList as $k=>$value){
$r = $this->_getRedis($this->TopXunid.($value['echelonTopX']+1));
$TopX_List = $this->readRankingList($r,$this->TopXunid.($value['echelonTopX']+1));
$XX = $TopX_List ? $TopX_List[0]["rank_sort"]:10001;
$rankList[$k]['standardTopX'] = $this->standardTopX($value['rank_sort'],$XX);
$expected_CEC_Sum += $this->calcCECTopXSum($value['rank_sort'],$KingCount,$XX);
}
//排位赛金额%
$rankAmountPre = min($maxSum/($expected_CEC_Sum+1),1); //MIN(当月排位赛最大分配额/(排位赛预计分配额+1),1)
foreach ($rankList as $k=>$value){
// $rankList[$k]['rewardCEC'] = $value['standardTopX']*$rankAmountPre;
if ($value['score'] >= $this->starshine){
$rankList[$k]['rewardCEC'] = $value['standardTopX']*$rankAmountPre;
}else{
$rankList[$k]['rewardCEC'] = 0;
}
}
}
return $rankList;
}
//排位赛最大分配金额
private function calcCECMaxSum(){
//当月排位赛最大分配金额=ROUND(40000000/(12*(1+0.7^1+0.7^2+0.7^3+0.7^4+0.7^5+0.7^6+0.7^7))*0.7^(CEILING(月份数/12-0.01,1)-1),0)*70%
$month = date('m',$this->_getNowTime());
return round(40000000/(12*(1+pow(0.7,1)+pow(0.7,2)+pow(0.7,3)+pow(0.7,4)
+pow(0.7,5)+pow(0.7,6)+pow(0.7,7)))*pow(0.7,ceil($month/12-0.01)-1),0)*0.7;
}
//排位赛参与分配人数
private function calcPeopleCapita($kingCount){
//MIN(当月王者及以上用户数ROUND(LOG10(当月王者及以上用户数+2)^3*1.5,1)*100)
return min($kingCount,round(pow(log10($kingCount+2),3)*1.5,1)*100);
}
//排位赛人数%
private function calcPeopleCapitaPer($kingCount){
//MIN(ROUND(0.31*MIN(当月王者及以上用户数,ROUND(LOG10(当月王者及以上用户数+1)^3*1.5,2)*100)^0.226,2),2)
return min(round(0.31*pow(min($kingCount,round(pow(log10($kingCount+1),3)*1.5,2)*100),0.226),2),2);
}
//TopX梯队
private function echelonTopX($top){
//TopX梯队=SIGN(TopX<=3)*1+SIGN(TopX>3)*SIGN(TopX<=10)*2+SIGN(TopX>10)*SIGN(TopX<=50)*3
//+SIGN(TopX>50)*SIGN(TopX<=100)*4+SIGN(TopX>100)*SIGN(TopX<=500)*5+SIGN(TopX>500)*SIGN(TopX<=1000)*6
//+SIGN(TopX>1000)*SIGN(TopX<=2000)*7+SIGN(TopX>2000)*SIGN(TopX<=5000)*8
//+SIGN(TopX>5000)*SIGN(TopX<=10000)*9+SIGN(TopX>10000)*10
return ($top<=3?1:0)*1+($top>3?1:0)*($top<=10?1:0)*2+($top>10?1:0)*($top<=50?1:0)*3
+($top>50?1:0)*($top<=100?1:0)*4+($top>100?1:0)*($top<=500?1:0)*5+($top>500?1:0)*($top<=1000?1:0)*6
+($top>1000?1:0)*($top<=2000?1:0)*7+($top>2000?1:0)*($top<=5000?1:0)*8
+($top>5000?1:0)*($top<=10000?1:0)*9+($top>10000?1:0)*10;
}
//TopX开始值
private function startTopX($top){
//TopX开始值=SIGN(TopX梯队=1)*1+SIGN(TopX梯队=2)*4+SIGN(TopX梯队=3)*11+SIGN(TopX梯队=4)*51
//+SIGN(TopX梯队=5)*101+SIGN(TopX梯队=6)*501+SIGN(TopX梯队=7)*1001
//+SIGN(TopX梯队=8)*2001+SIGN(TopX梯队=9)*5001+SIGN(TopX梯队=10)*10001
return ($this->echelonTopX($top)==1?1:0)*1+($this->echelonTopX($top)==2?1:0)*4+($this->echelonTopX($top)==3?1:0)*11+($this->echelonTopX($top)==4?1:0)*51
+($this->echelonTopX($top)==5?1:0)*101+($this->echelonTopX($top)==6?1:0)*501+($this->echelonTopX($top)==7?1:0)*1001
+($this->echelonTopX($top)==8?1:0)*2001+($this->echelonTopX($top)==9?1:0)*5001+($this->echelonTopX($top)==10?1:0)*10001;
}
//TopX梯队最高值
private function maxTopX($top){
//TopX梯队最高值=ROUND(2000*0.6^(TopX梯队-1)*0.9^(TopX梯队-1),0)
return round(2000*pow(0.6,$this->echelonTopX($top)-1)*pow(0.9,$this->echelonTopX($top)-1),0);
}
//TopX梯队最低值
private function minTopX($top){
//TopX梯队最低值=ROUND(2000*0.6^(TopX梯队)*0.9^(TopX梯队-1),0)
return round(2000*pow(0.6,$this->echelonTopX($top))*pow(0.9,$this->echelonTopX($top)-1),0);
}
//TopX排位赛标准分配额
private function standardTopX($top,$XX){
//TopX排位赛标准分配额=MAX(ROUND(TopX梯队最高值-(TopX梯队最高值-TopX梯队最低值)/(TopX梯队开始值(TopX梯队+1)-TopX梯队开始值-1)*(TopX-TopX梯队开始值),2),TopX梯队最低值)
return max(round($this->maxTopX($top)-($this->maxTopX($top)-$this->minTopX($top))/($XX-$this->startTopX($top)-1)*($top-$this->startTopX($top)),2),$this->minTopX($top));
}
//TopX排位赛预计分配额
private function calcCECTopXSum($top,$kingCount,$XX){
//TopX排位赛标准分配额*排位赛人数%
return $this->standardTopX($top,$XX)*$this->calcPeopleCapitaPer($kingCount);
}
//排位赛金额%
private function rankAmountPre(){
//MIN(当月排位赛最大分配额/(排位赛预计分配额+1),1)
}
private function readRankingList($r,$rankUnid)
{
$list = $r->get(RANKING_KEY.$rankUnid);
if (empty($list)) {
return array();
}
$list = json_decode($list, true);
return $list;
}
private function saveRankingList($r,$rankUnid ,$list)
{
$r->set(RANKING_KEY.$rankUnid , json_encode($list));
$r->pexpire(RANKING_KEY.$rankUnid , 6*60*60*1000);
}
}