406 lines
18 KiB
PHP
406 lines
18 KiB
PHP
<?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);
|
||
}
|
||
|
||
}
|