<?php
namespace Game\Logic\Pvp;

use Exception;
use Framework\Define\ErrorDefine;
use Framework\Lib\Utils;
use Framework\Log\LogMark;
use Framework\MVC\ModelManager;
use Framework\DB\Handler\MatchingDBHandler;
use Game\Constant\ConstTemplate\TemplateCar;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\ConstTemplate\TemplateRankMatch;
use Game\Constant\ConstTemplate\TemplateSeasonRewardCondition;
use Game\Constant\DBTableDefine;
use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Data\Car\CarStatisticsData;
use Game\Data\RaceResultData;
use Game\Data\RecordData;
use Game\Data\RoomData;
use Game\Data\SeasonStatisticsData;
use Game\Logic\Car\CarStatisticsLogic;
use Game\Logic\EventConditionLogic;
use Game\Logic\EventLogic;
use Game\Logic\Friend\FriendLogic;
use Game\Logic\GenerateAiLogic;
use Game\Logic\RankLogic;
use Game\Logic\RoomCustomize\RoomInfoLogic;
use Game\Logic\SeasonLogic;
use Game\Logic\SeasonStatisticsLogic;
use Game\Logic\Task\WarTokenDailyTaskLogic;
use Game\Model\Friend\FriendIntimacyModel;
use Game\Model\Friend\FriendLastGameModel;
use Game\Model\Friend\FriendModel;
use Game\Model\Pvp\PvpBaseModel;
use Game\Model\Rank\RankModel;
use Game\Model\RecordModel;
use Game\Model\RoomCustomizeModel;
use Game\Model\RoomModel;
use Game\Operation\EventLog\CompleteMatchLog;
use Game\Operation\EventLog\EventLog_Manager;
use Game\Operation\EventLog\EventLogType;
use Game\Protobuf\AIInfo;
use Game\Protobuf\GCMatchRecordDetail;
use Game\Protobuf\GMJoinMatch;
use Game\Protobuf\GCPVPMatchingSuccess;
use Framework\Logic\CommonDataLogic;
use Game\Protobuf\MatchRecordResult;
use Game\Protobuf\MatchTimeScoreRange;
use Game\Protobuf\MRGMatchResult;
use Game\Protobuf\PacketId;
use Game\Protobuf\PlayerInfo;
use Game\Protobuf\RaceResult;
use Game\Protobuf\RecordBreakingInfo;
use Game\Protobuf\RewardItem;
use Game\Protobuf\SettlementParameter;

trait PvpLogic
{
    use EventLogic;
    use EventConditionLogic;
    use FriendLogic;
    use RankLogic;
    use CommonDataLogic;
    use GenerateAiLogic;
    use RoomInfoLogic;
    use SeasonLogic;
    use SeasonStatisticsLogic;
    use CarStatisticsLogic;
    use WarTokenDailyTaskLogic;

    use MatchingDBHandler;

    //解析结算参数
    //结算参数说明
    //Client_Room_Packet的PlayerMark和Game_Room_Packet的SettlementPlayer和Client_Game_Packet的PlayerMark一致:
    //protobuf SettlementParameter
    public function analysisSettlementParam(string $string, RaceResultData $raceResult)
    {
        $parameter = new SettlementParameter();
        try {
            $parameter->mergeFromString(base64_decode($string));
        } catch (Exception $e) {
            LogMark::getInstance()->markError(
                ErrorDefine::EXCEPTION_ERROR,
                "[PvpLogic] analysisSettlementParam error,string:".$string,
            );
            $raceResult->_jamNum = 0;
            $raceResult->_helpNum = 0;
            $raceResult->parameter = $parameter;
            return;
        }
        $raceResult->_jamNum = $parameter->getJamNum();
        $raceResult->_helpNum = $parameter->getHelpNum();
        $raceResult->parameter = $parameter;
    }

    //计算排位平均分
    public function getAvgRankingScore(array $rankingScore): int
    {
        //4.当三人组队排位时，按照三匹没好队友的匹配分加权平均（可配置加权平均的值），
        //分数最高的玩家加权值为0.4；分数次高的玩家加权值为0.35；分数最低的玩家加权值为0.25。
        //当两人组队排位时，分数最高的玩家加权值为0.6，另一名玩家为0.4。
        rsort($rankingScore);
        switch (count($rankingScore))
        {
            case 1:
                return $rankingScore[0];
            case 2:
                $constConfig = $this->getTable(TemplateDefine::TYPE_CONST);
                return (int)($rankingScore[0] * $constConfig[TemplateConst::Const_Ranking_Score_Avg_2_Max][TemplateConst::ConstNum]
                    + $rankingScore[1] * $constConfig[TemplateConst::Const_Ranking_Score_Avg_2_Min][TemplateConst::ConstNum]);
            case 3:
                $constConfig = $this->getTable(TemplateDefine::TYPE_CONST);
                return (int)($rankingScore[0] * $constConfig[TemplateConst::Const_Ranking_Score_Avg_3_Max][TemplateConst::ConstNum]
                    + $rankingScore[1] * $constConfig[TemplateConst::Const_Ranking_Score_Avg_3_Mid][TemplateConst::ConstNum] +
                    $rankingScore[2] * $constConfig[TemplateConst::Const_Ranking_Score_Avg_3_Min][TemplateConst::ConstNum]);
        }
        return $rankingScore[0];
    }

    public function getRankingConfig(int $lv): array
    {
        $matchConfig = $this->getTable(TemplateDefine::TYPE_RANK_MATCH);
        $matchTimeProto = array();
        foreach ($matchConfig as $id => $config) {
            if ($lv > $config[TemplateRankMatch::MinLv] && $lv < $config[TemplateRankMatch::MaxLv]) {
                $tmp = explode(";", $config[TemplateRankMatch::Param]);
                foreach ($tmp as $t) {
                    [$timeRange, $scoreRange] = explode("*", $t);
                    $matchTime = new MatchTimeScoreRange();
                    $matchTime->setTimeRange($timeRange);
                    $matchTime->setScoreRange($scoreRange);
                    $matchTimeProto[] = $matchTime;
                }
                return array(
                    $config[TemplateRankMatch::MaxTime],
                    $config[TemplateRankMatch::LvRange],
                    $matchTimeProto,
                );
            }
        }
        $tmp = explode(";", $matchConfig[1][TemplateRankMatch::Param]);
        foreach ($tmp as $t) {
            [$timeRange, $scoreRange] = explode("*", $t);
            $matchTime = new MatchTimeScoreRange();
            $matchTime->setTimeRange($timeRange);
            $matchTime->setScoreRange($scoreRange);
            $matchTimeProto[] = $matchTime;
        }
        return array(
            $matchConfig[1][TemplateRankMatch::MaxTime],
            $matchConfig[1][TemplateRankMatch::LvRange],
            $matchTimeProto,
        );
    }

    //更新比赛记录
    private function updateRecord(RaceResultData $raceResult, int $playerId)
    {
        /**
         * @var RecordModel $recordModel
         */
        $recordModel = ModelManager::getInstance()->getModel(ModelTypeDefine::RECORD);
        $record = $recordModel->getRecordByJoinId($this->joinId, $playerId);
        if (is_null($record)) {
            return;
        }
        //整理并记录比赛结果
        $matchingMsg = new GCPVPMatchingSuccess();
        try {
            $matchingMsg->mergeFromJsonString($record->matchingData);
        } catch (Exception $e) {
            LogMark::getInstance()->markDebug(
                "[PvpLogic] mergeFromJsonString matchingData error,string:".$record->matchingData,
            );
            return;
        }
        //查找昵称
        $playerInfoList = array();
        foreach ($matchingMsg->getPInfo() as $pInfo) {
            /**
             * @var PlayerInfo $pInfo
             */
            $playerInfoList[$pInfo->getPlayerId()] = array(
                "nickname" => $pInfo->getNickName(),
                "groupId" => $pInfo->getGroupID()
            );
        }
        foreach ($matchingMsg->getAInfo() as $aInfo) {
            /**
             * @var AIInfo $aInfo
             */
            $playerInfoList[$aInfo->getPlayerId()] =array(
                "nickname" => $aInfo->getNickName(),
                "groupId" => $aInfo->getGroupID()
            );
        }
        //整理比赛结果--统计信息获取比赛详情用
        $list = array();
        foreach ($this->sendRaceResultList as $rResult) {
            /**
             * @var RaceResult $rResult
             */
            $matchRecordResult = new MatchRecordResult();
            $matchRecordResult->setPlayerId($rResult->getPlayerId())
                ->setRank($rResult->getRank())
                ->setTime($rResult->getTime())
                ->setCarId($rResult->getCarId())
                ->setHelpNum(($rResult->getHelpNum()))
                ->setJamNum($rResult->getJamNum())
                ->setHelpIcon($rResult->getHelpIcon())
                ->setJamIcon($rResult->getJamIcon())
                ->setRaceIcon($rResult->getRaceIcon())
                ->setMvp($rResult->getMvp())
                ->setSVP($rResult->getSVP())
                ->setIsWin($rResult->getIsWin())
                ->setNickName($playerInfoList[$rResult->getPlayerId()]['nickname'])
                ->setGroupId($playerInfoList[$rResult->getPlayerId()]['groupId']);
            $list[] = $matchRecordResult;
        }
        $matchRecordDetail = new GCMatchRecordDetail();
        $matchRecordDetail->setResult($list);

        $changeData = array(
            RecordData::COST_TIME => $raceResult->_costTime,
            RecordData::RACE_RESULT_DATA => $this->sendMessage->serializeToJsonString(),
            RecordData::CAR_ID => $raceResult->_carId,
            RecordData::MATCH_RECORD_DETAIL => $matchRecordDetail->serializeToJsonString(),
        );
        //胜负 根据比赛类型判断 个人赛为对应名次 团队赛0负1胜
        switch ($raceResult->_modeType)
        {
            case GameConstantDefine::MATCH_MODE_SINGLE_PRACTISE:
            case GameConstantDefine::MATCH_MODE_SINGLE_PAI_WEI:
            case GameConstantDefine::MATCH_MODE_SINGLE:
            case GameConstantDefine::MATCH_MODE_PRACTICE:
                $changeData[RecordData::RESULT] = $raceResult->_rank;
                break;
            case GameConstantDefine::MATCH_MODE_TEAM_PRACTISE:
            case GameConstantDefine::MATCH_MODE_TEAM_PAI_WEI:
            case GameConstantDefine::MATCH_MODE_TEAM:
            case GameConstantDefine::MATCH_MODE_SCUFFLE:
                $changeData[RecordData::RESULT] = 0;
                if ($raceResult->_teamWin) {
                    $changeData[RecordData::RESULT] = 1;
                }
                break;
        }
        $recordModel->updateRecordData($this->joinId, $changeData, true);
    }

    //更新好友比赛记录
    private function updateLastGame(array $pIdRankList, int $playerId, int $mapId, string $matchResult)
    {
        /**
         * @var FriendLastGameModel $lastGame
         */
        $lastGame = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND_LAST_GAME);
        $lastGame->updateLastGameRecord($this->joinId, $pIdRankList, $mapId, $matchResult);
        $lastGame->deleteMinTimeList();
        /**
         * @var FriendModel $friend
         */
        $friend = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND);
        $friend->setPlayerId($playerId);
        //检测好友,加入好友列表
        $matchFriend = [];
        foreach ($pIdRankList as $pId => $rank){
            if ($this->checkIsAIPlayer($pId) || $pId == $playerId) {
                continue;
            }
            if (!$this->checkTargetPlayerIsMyFriend($pId)){
                continue;
            }
            $matchFriend[] = $pId;
        }
        if (count($matchFriend) > 0){
            $this->upRoleExtLatelyMatchFriend($matchFriend);
            $param = array(
                GameConstantDefine::EVENT_KEY_FRIEND_IDS => $matchFriend,
            );
            $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_PLAY_WITH_FRIEND, $param, false);
        }
        //增加亲密度 一起比赛
        $point = $this->getTerm(
            TemplateDefine::TYPE_CONST,
            TemplateConst::Const_Intimacy_Add_Point_Match,
            TemplateConst::ConstNum);
        foreach ($matchFriend as $targetPlayerId) {
            $this->addFriendIntimacy($targetPlayerId, $point, GameConstantDefine::INTIMACY_SOURCE_PLAY_GAME);
        }
    }

    public function getRecordData(): ?RecordData
    {
        /**
         * @var RecordModel $recordModel
         */
        $recordModel = ModelManager::getInstance()->getModel(ModelTypeDefine::RECORD);
        return $recordModel->getRecordByJoinId($this->joinId);
    }

    public function getRecordByJoinId(int $joinId): ?RecordData
    {
        /**
         * @var RecordModel $recordModel
         */
        $recordModel = ModelManager::getInstance()->getModel(ModelTypeDefine::RECORD);
        return $recordModel->getRecordByJoinId($joinId);
    }


    public function clearJoinId()
    {
        /**
         * @var PvpBaseModel $pvp
         */
        $pvp = ModelManager::getInstance()->getModel(ModelTypeDefine::PVP_BASE);
        $pvp->clearJoinId();
    }

    public function getMyJoinId(): int
    {
        /**
         * @var PvpBaseModel $pvp
         */
        $pvp = ModelManager::getInstance()->getModel(ModelTypeDefine::PVP_BASE);
        return $pvp->getJoinId();
    }

    public function getJoinIdByPlayerId(int $playerId): int
    {
        /**
         * @var PvpBaseModel $pvp
         */
        $pvp = ModelManager::getInstance()->getModel(ModelTypeDefine::PVP_BASE);
        return $pvp->getJoinIdByPlayerId($playerId);
    }

    public function changePlayerAndRoomState(int $roomID, int $roomType = 0): bool
    {
        //新手引导,没有room
        if ($roomID < 10) {
            return true;
        }
        LogMark::getInstance()->markInfo("change state: roomID: " . $roomID . " roomType: " . $roomType);
        if(empty($roomType)) {
            // 修改房间玩家状态,更新等级连胜等数据
            if(!$this->updatePlayerState($this->playerId, $roomID, RoomCustomizeModel::ROOM_PLAY_NOT_READY)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[PvpLogic] settlement change player state error!',
                    ['roomID' => $roomID]
                );
                return false;
            }
            /**
             * @var RoomModel $roomModel
             */
            $roomModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ROOM);
        } else {
            // 修改房间玩家状态
            if(!$this->updateCustomizePlayerState($roomID, RoomCustomizeModel::ROOM_PLAY_NOT_READY)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[PvpLogic] settlement change customize player state error!',
                    ['roomID' => $roomID]
                );
                return false;
            }
            /**
             * @var RoomCustomizeModel $roomModel
             */
            $roomModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ROOM_CUSTOMIZE);
        }

        $room = $roomModel->newRoom($roomID);
        if(!$room->searchRoomByRoomID()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[PvpLogic] settlement search room error!', (array)$room
            );
            return false;
        }
        $room->setPlayType(RoomModel::ROOM_GAME_READY);
        if(!$room->saveDB()) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[PvpLogic] settlement save room error!', (array)$room
            );
            return false;
        }
        return true;
    }

    //更新房间内玩家数据
    public function updateRoomPlayerData(int $roomID)
    {
        /**
         * @var RoomModel $roomModel
         */
        $roomModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ROOM);
        $room = $roomModel->newRoom($roomID);
        $room->searchRoomByRoomID();
        $showPlayer = $this->getMatchShowPlayer($roomModel->getPlayerID());
        $room->playerInfo[$roomModel->getPlayerID()][RoomData::SCUFFLE_SCORE] = $showPlayer[RoomData::SCUFFLE_SCORE];
        $room->playerInfo[$roomModel->getPlayerID()][RoomData::CONTINUITY_WIN] = $showPlayer[RoomData::CONTINUITY_WIN];
        $room->saveDB();
    }

    public function sendJoinMatchingPacket(GMJoinMatch $packet): bool
    {
        $msgID = PacketId::GM_JoinMatch;
        $joinMatch = base64_encode($packet->serializeToString());
        $sendStr = $msgID. '@'. $joinMatch;
        LogMark::getInstance()->markDebug(
            "[PVPFlowLog][PvpLogic] send Join Matching Packet:".$packet->serializeToJsonString()
        );
        return $this->addQueueByDBKey(
            DBTableDefine::TABLE_PVP,
            GameConstantDefine::DBKEY_COMPETE_SERVER_MATCH,
            $sendStr);
    }

    public function sendMatchRetPacket(MRGMatchResult $packet): bool
    {
        $msgID = PacketId::MRG_MatchResult;
        $matchRet = base64_encode($packet->serializeToString());
        $sendStr = $msgID. '@'. $matchRet;
        LogMark::getInstance()->markDebug(
            "[PvpLogic] send Join Matching Packet"
        );
        return $this->addQueueByDBKey(
            DBTableDefine::TABLE_PVP,
            GameConstantDefine::DBKEY_COMPETE_SERVER_PROXY,
            $sendStr);
    }

    //更新record数据
    public function updateRecordData(int $playerId, int $joinId, array $data)
    {
        /**
         * @var RecordModel $recordModel
         */
        $recordModel = ModelManager::getInstance()->getModel(ModelTypeDefine::RECORD);
        $recordModel->updateRecordData($joinId, $data);
    }

    /**
     * pvp比赛结束
     * @param RaceResultData $raceResult
     * @param RecordData $record
     * @param bool $isWin   胜负标志,个人赛为前3名,团队赛为队伍获胜
     * @param int $playerId
     */
    public function triggerFinishPVPEvent(RaceResultData $raceResult, RecordData $record, bool $isWin, int $playerId)
    {
        //完成比赛相关任务
        $param = array(
            GameConstantDefine::EVENT_KEY_MATCH_TIME => $raceResult->_costTime,
            GameConstantDefine::EVENT_KEY_MATCH_MAP => $record->mapID,
            GameConstantDefine::EVENT_KEY_MATCH_TYPE => $record->matchType,
            GameConstantDefine::EVENT_KEY_CAR_ID => $raceResult->_carId,
            GameConstantDefine::EVENT_KEY_MATCH_WIN => $isWin,
            GameConstantDefine::EVENT_KEY_MVP => $raceResult->_mvpIcon,
            GameConstantDefine::EVENT_KEY_RACE_ICON => $raceResult->_raceIcon,
            GameConstantDefine::EVENT_KEY_JAM_ICON => $raceResult->_jamIcon,
            GameConstantDefine::EVENT_KEY_HELP_ICON => $raceResult->_helpIcon,
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_COMPLETE_MATCH, $param, false);
        //战令每日任务检查
        $this->addWarTokenDailyTaskExp($param);
        //排名任务
        $param = array(
            GameConstantDefine::EVENT_KEY_MATCH_RANK => $raceResult->_rank,
            GameConstantDefine::EVENT_KEY_MATCH_TYPE => $record->matchType,
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_MATCH_RANK, $param, false);
        $this->updateRoomPlayerData($record->roomID);
        //邀请好友
        /**
         * @var RoomModel $roomModel
         */
        $roomModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ROOM);
        $invitedInfo = $roomModel->getMyInvitedInfo($record->roomID, $playerId);
        if (count($invitedInfo) > 0) {
            $param = array(
                GameConstantDefine::EVENT_KEY_INVITED_PLAYER => $invitedInfo,
            );


            // 如果进行排位 则更新赛季分
            if(in_array($record->matchType, [GameConstantDefine::MATCH_MODE_SINGLE_PAI_WEI,
                GameConstantDefine::MATCH_MODE_TEAM_PAI_WEI]))
            {
                $this->updateSeasonScore(TemplateSeasonRewardCondition::PLAY_RANK_FRIEND, $playerId);
            }

            $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_INVITATION_FRIEND, $param, false);
        }

        // 被邀请也更新赛季分
        $invitedInfo2 = $roomModel->getMyInvitedInfo2($record->roomID, $playerId);
        if (!empty($invitedInfo2) && in_array($record->matchType, [GameConstantDefine::MATCH_MODE_SINGLE_PAI_WEI,
                GameConstantDefine::MATCH_MODE_TEAM_PAI_WEI])) {
            // 如果进行排位 则更新赛季分
            $this->updateSeasonScore(TemplateSeasonRewardCondition::PLAY_RANK_FRIEND, $playerId);
        }
    }

    public function updateRankData($raceResult): bool {
        $rankType1 = 0;
        $rankType2 = 0;

        if(true == $raceResult->_raceIcon) {
            $rankType1 = RankModel::RACING_SEASON;
            $rankType2 = RankModel::RACING_FULL;
        }
        if(true == $raceResult->_helpIcon) {
            $rankType1 = RankModel::HELPER_SEASON;
            $rankType2 = RankModel::HELPER_FULL;
        }
        if(true == $raceResult->_jamIcon) {
            $rankType1 = RankModel::DISTURBANCE_SEASON;
            $rankType2 = RankModel::DISTURBANCE_FULL;
        }
        // 判断自己获得什么徽章
        // 调用徽章执行逻辑
        if(!empty($rankType1)) {
            // 获取更新个人排行类型的奖章数据
            $num1 = $this->changeEventPooledValue($rankType1);
            $num2 = $this->changeEventPooledValue($rankType2);
            if(!is_bool($num1) && !$this->changeRankScore($rankType1, $num1)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[pvp logic] update rank data error!',
                    ['rankType' => $rankType1, 'num' => $num1]
                );
                return false;
            }
            if(!is_bool($num2) && !$this->changeRankScore($rankType2, $num2)) {
                LogMark::getInstance()->markError(
                    GameErrorCode::DATA_UPDATE_ERROR,
                    '[pvp logic] update rank data error!',
                    ['rankType' => $rankType2, 'num' => $num2]
                );
                return false;
            }
        }
        return true;
    }

    // 更新地图排行榜
    private function changeRankMap(int $costTime, int $mapID) {
        $rankType1 = RankModel::MAP_SEASON;
        $rankType2 = RankModel::MAP_FULL;
        if ($costTime == 0) {
            return ;
        }
        $num1 = $this->changeRankMapEventPooled($rankType1, $costTime, $mapID);
        $num2 = $this->changeRankMapEventPooled($rankType2, $costTime, $mapID);
        if(!$this->changeRankScore($rankType1, $num1, $mapID, true)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[pvp logic] update map full rank data error!',
                ['rankType' => $rankType1, 'num' => $num1, 'mapID' => $mapID]
            );
            return ;
        }
        if(!$this->changeRankScore($rankType2, $num2, $mapID, true)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[pvp logic] update map full rank data error!',
                ['rankType' => $rankType1, 'num' => $num1, 'mapID' => $mapID]

            );
            return ;
        }
    }

    private function changeEventPooledValue($type, int $mapID = 0)
    {
        $seasonID = $this->getSeasonId();
        if(in_array($type, RankModel::RANK_SEASON_TYPE)) {
            if($seasonID == 0) {
                return false;
            }
        }
        return $this->addEventConditionValue(
            $this->getRankingKey($type, $seasonID, $mapID),
            1
        );
    }

    private function changeRankMapEventPooled($type, $score,int $mapID = 0)
    {
        $res = [];
        $seasonID = $this->getSeasonId();
        if(in_array($type, RankModel::RANK_SEASON_TYPE)) {
            if($seasonID == 0) {
                return false;
            }
        }
        $value = $this->getSingleEventConditionValue(
            $this->getRankingKey($type, $seasonID, $mapID)
        );
        if($value == 0) {
            $this->addEventConditionValue(
                $this->getRankingKey($type, $seasonID, $mapID),
                $score
            );
            $newScore = $score;
        } elseif ($value > $score){
            $this->addEventConditionValue(
                $this->getRankingKey($type, $seasonID, $mapID),
                $score - $value
            );
            $newScore = $score;
        } else {
            $newScore = $value;
        }
        return $newScore;
    }

    //添加战斗通用返回消息
    public function addRaceResultMessage(RaceResultData $raceResult)
    {
        // 返回去除观战
        if($raceResult->_rank < 0) {
            return ;
        }
        $rr = new RaceResult();
        $rr->setPlayerId($raceResult->_playerId);
        $rr->setRank($raceResult->_rank);
        $rr->setTime($raceResult->_costTime);
        $rr->setCarId($raceResult->_carId);
        $rr->setHelpNum($raceResult->_helpNum);
        $rr->setJamNum($raceResult->_jamNum);
        $rr->setHelpIcon($raceResult->_helpIcon);
        $rr->setJamIcon($raceResult->_jamIcon);
        $rr->setRaceIcon($raceResult->_raceIcon);
        $rr->setMvp($raceResult->_mvpIcon);
        $rr->setIsWin($raceResult->_isWin);
        $rr->setSVP($raceResult->_svp);
        $rr->setContinuityWin($raceResult->continuityWinNum);
        $this->sendRaceResultList[] = $rr;
    }

    //发送战斗消息和玩家奖励
    public function sendMessage(int $playerId)
    {
        $this->sendMessage->setResult($this->sendRaceResultList);
        if ($this->addPacket(PacketId::GC_RaceResult, $this->sendMessage, $playerId)) {
            LogMark::getInstance()->markInfo(
                '[PVPFlowLog][20][PvpLogic] match settlement send result to Player success:',
                array("packet" => $this->sendMessage->serializeToJsonString()));
        }
    }

    //整理统计信息,比赛结束统计用
    //只记录排位,练习
    public function tidyStatisticsData(RaceResultData $raceResult)
    {
        $settlementArray = array();     //赛季统计信息
        $carStatisticsArray = array();  //赛车统计信息
        //赛车定位
        switch ($this->carPositioning)
        {
            case TemplateCar::Positioning_Race:
                $settlementArray[SeasonStatisticsData::NS_RACE_POSITION_NUM] = 1;
                break;
            case TemplateCar::Positioning_Jam:
                $settlementArray[SeasonStatisticsData::NS_JAM_POSITION_NUM] = 1;
                break;
            case TemplateCar::Positioning_Help:
                $settlementArray[SeasonStatisticsData::NS_HELP_POSITION_NUM] = 1;
                break;
        }
        //获胜次数 单人前三,组队为团队胜利
        switch ($raceResult->_modeType)
        {
            case GameConstantDefine::MATCH_MODE_SINGLE_PRACTISE:
            case GameConstantDefine::MATCH_MODE_SINGLE_PAI_WEI:
                if ($raceResult->_rank <= 3) {
                    $settlementArray[SeasonStatisticsData::NS_WIN_NUM] = 1;
                    $carStatisticsArray[CarStatisticsData::WIN_NUM] = 1;
                }
                break;
            case GameConstantDefine::MATCH_MODE_TEAM_PRACTISE:
            case GameConstantDefine::MATCH_MODE_TEAM_PAI_WEI:
                if ($raceResult->_teamWin) {
                    $settlementArray[SeasonStatisticsData::NS_WIN_NUM] = 1;
                    $carStatisticsArray[CarStatisticsData::WIN_NUM] = 1;
                }
                break;
            default:
                return;
        }
        //MVP 徽章统计
        if ($raceResult->_mvpIcon) {
            $settlementArray[SeasonStatisticsData::NS_MVP_NUM] = 1;
            $carStatisticsArray[CarStatisticsData::MVP_NUM] = 1;
        }
        if ($raceResult->_raceIcon) {
            $settlementArray[SeasonStatisticsData::NS_ICON_RACE_NUM] = 1;
            $carStatisticsArray[CarStatisticsData::ICON_NUM] = 1;
        }
        if ($raceResult->_jamIcon) {
            $settlementArray[SeasonStatisticsData::NS_ICON_JAM_NUM] = 1;
            $carStatisticsArray[CarStatisticsData::ICON_NUM] = 1;
        }
        if ($raceResult->_helpIcon) {
            $settlementArray[SeasonStatisticsData::NS_ICON_HELP_NUM] = 1;
            $carStatisticsArray[CarStatisticsData::ICON_NUM] = 1;
        }
        //前三次数
        switch ($raceResult->_rank)
        {
            case 1:
                $settlementArray[SeasonStatisticsData::NS_NO1_NUM] = 1;
                break;
            case 2:
                $settlementArray[SeasonStatisticsData::NS_NO2_NUM] = 1;
                break;
            case 3:
                $settlementArray[SeasonStatisticsData::NS_NO3_NUM] = 1;
                break;
        }
        //更新统计信息
        $this->updateSeasonStatistics($settlementArray, $raceResult->_modeType);
        $this->updateCarStatistics($carStatisticsArray, $raceResult->_carId);
    }

    public function changeRoomExpireTime(int $roomID, int $addTime): bool
    {
        $time = Utils::getServerTimestamp() + $addTime;
        if (false === $this->addRank(
                DBTableDefine::TABLE_ROOM_CUSTOMIZE_TIME,
                0,
                $roomID,
                $time
            )){
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                "[RoomModel] change customize room off-line time error!",
            );
            return false;
        }
        return true;
    }

    //获取匹配配置--除排位赛
    public function getMatchMaxTime(int $matchType): int
    {
        $config = $this->getTitle(TemplateDefine::TYPE_PVP_MATCH, $matchType);
        if (is_null($config)) {
            LogMark::getInstance()->markError(
                GameErrorCode::CONFIG_ERROR,
                "[PvpLogic] getMatchParam not found matchType",
                array(
                    "matchType" => $matchType
                )
            );
            return 0;
        }
        return $config[TemplateRankMatch::MaxTime];
    }

    //检查是否和亲密好友一起游戏
    public function checkPlayerWithIntimacyFriend(int $roomId, int $playerId): bool
    {
        /**
         * @var RoomModel $roomModel
         */
        $roomModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ROOM);
        $invitedFriends = array();
        //自己邀请的玩家
        $invitedInfo = $roomModel->getMyInvitedInfo($roomId, $playerId);
        if (count($invitedInfo) > 0) {
            $invitedFriends = $invitedInfo;
        }
        //查询邀请自己的玩家
        $invitePlayerId = $roomModel->getMyInvitedInfo2($roomId, $playerId);
        if ($invitePlayerId > 0) {
            $invitedFriends[] = $invitePlayerId;
        }
        if (count($invitedFriends) == 0) {
            return false;
        }
        //检查是否为亲密关系
        /**
         * @var FriendIntimacyModel $friendIntimacyModel
         */
        $friendIntimacyModel = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND_INTIMACY);
        foreach ($invitedFriends as $targetPlayerId) {
            $friendIntimacyModel->setRespondentPlayerId($targetPlayerId);
            //检查与对方是否有关系
            if ($friendIntimacyModel->checkHasIntimacy()) {
                return true;
            }
        }
        return false;
    }

    //完成比赛打点
    public function addCompletaMatchLog(RecordData $recordData, RaceResultData $raceResultData, array $playerList)
    {
        $log = EventLog_Manager::getInstance()->getEventLog(EventLogType::CompleteMatch);
        if (is_null($log)) {
            return;
        }
        EventLog_Manager::getInstance()->cliInitAccount();
        /**
         * @var CompleteMatchLog $log
         */
        $log->matchType = $raceResultData->_modeType;
        $log->matchUid = $this->sendMessage->getMatchId();
        $log->mapId = $recordData->mapID;
        $log->perfectMatch = 0;
        //检查完美搭配--团队排位用,同队三个位置的车都有,为完美搭配
        if ($raceResultData->_modeType == GameConstantDefine::MATCH_MODE_TEAM_PAI_WEI) {
            $carPosition = 0;
            foreach ($playerList as $pid => $raceResult) {
                /**
                 * @var RaceResultData $raceResult
                 */
                if ($raceResultData->_groupId == $raceResult->_groupId) {
                    $carPosition += $this->getTerm(TemplateDefine::TYPE_CAR, $raceResult->_carId, TemplateCar::Positioning);
                }
            }
            if ($carPosition == 6) {
                $log->perfectMatch = 1;
            }
        }
        //获取玩家结算数据
        $log->playerId = $this->playerId;
        $log->playerJoinId = $recordData->joinId;
        $log->playerTeamWin = (int)$raceResultData->_teamWin;
        $log->addCarProficiency = $this->sendMessage->getAddCarProficiency();
        $log->addScore = $this->sendMessage->getAddScore();
        $log->playerRaceResultData = $raceResultData;
        $log->raceResultList = $this->sendRaceResultList;
        //大乱斗数据
        if ($log->matchType == GameConstantDefine::MATCH_MODE_SCUFFLE) {
            $log->addGuardScore = 0;
            $log->matchCarScore = 0;
            $log->playerBreakingInfo = new RecordBreakingInfo();
        } else {
            $log->addGuardScore = $this->sendMessage->getAddGuardScore();
            $log->matchCarScore = $this->sendMessage->getCarScore();
            $log->playerBreakingInfo = $this->sendMessage->getMyBreakingInfo();
        }

        $reward = array();
        foreach ($this->sendMessage->getItem() as $item) {
            /**
             * @var RewardItem $item
             */
            $reward[$item->getId()] = $item->getNum();
        }
        $log->reward = $reward;
        foreach ($this->sendMessage->getResult() as $result) {
            /**
             * @var RaceResult $result
             */
            if ($this->playerId == $result->getPlayerId()) {
                $log->playerRaceResult = $result;
                $log->playerCarId = $result->getCarId();
                $car = $this->searchCarDataByCarID($result->getCarId());
                if (is_null($car)) {
                    $log->playerCarPerformance = 0;
                    $log->playerCarLv = 0;
                    $log->playerCarProficiencyLv = 0;
                } else {
                    $log->playerCarPerformance = $car->performance;
                    $log->playerCarLv = $car->level;
                    $log->playerCarProficiencyLv = $car->proficiencyLv;
                }
                break;
            }
        }
        if (method_exists($this->sendMessage, "getParameter")) {
            foreach ($this->sendMessage->getParameter() as $parameter) {
                /**
                 * @var SettlementParameter $parameter
                 */
                if ($this->playerId == $parameter->getPlayerId()) {
                    $log->playerParameter = $parameter;
                    break;
                }
            }
        } else {
            $log->playerParameter = new SettlementParameter();
        }
        $log->markLog();
    }
}
