<?php

namespace loyalsoft;

/**
 * 战斗 -  关卡
 * @author gwang
 */
class SweepGatesProc {

    /**
     * 提取某个对象的某个字段(利用后面2个参数组合为字段名)
     * @param type $obj
     * @param type $name
     * @param type $index
     * @return type
     */
    private static function getProperty_n($obj, $name, $index) {
        if (is_object($obj)) {
            $ke = "$name$index";
            if (property_exists($obj, $ke)) {
                return $obj->$ke;
            }
        }
        return null;
    }

    /**
     * [6800] 关卡战斗 - 预计算掉落 
     */
    public static function Arenas_preFight() {
        list($gateId, $difficulty) = req()->paras;                               # 提取参数 
        my_Assert($gateId > 0, "关卡id非法");
        $isFirst = self::isFirstChallenge($gateId, $difficulty);                # 是否首次通关 
        $smGate = GameConfig::gate_getItem($gateId);                            # 关卡配置数据
        $i = $difficulty + 1;                                                   # 按三个难度取不同的值.
//        $tili = self::getProperty_n($smGate, "tili", $i);                     # 体力暂时未用上
        $rwdstr = self::getProperty_n($smGate, "reward", $i);
        $firstPassRewardStr = self::getProperty_n($smGate, 'first_reward', $i);
        if ($isFirst) {                                                         # 是否首次通关切换奖励内容
            $rwdstr = $firstPassRewardStr;
        }
        $rsarr = explode(';', $rwdstr);
        my_Assert(count($rsarr) > 0, "关卡奖励数据异常");
        $dic = array();
        foreach ($rsarr as $rs) {
            $rarr = explode(',', $rs);
            $id = intval($rarr[0]);
            $num = intval($rarr[1]);
            $percent = intval(rtrim($rarr[2], '%'));
            if (CommUtil::randomPercent($percent)) {                            # 投骰子 决定是否本次掉落
                $dic[] = array($id => $num);                                    # 掉落
            }
        }
        $arr = array();                                                         # 拼接返回字符串
        foreach ($dic as $item) {
            foreach ($item as $k => $v) {
                $arr[] = sprintf("%s,%s", $k, $v);
            }
        }
        $_rewards = implode(";", $arr);                                         # 最终奖励字符串
        $redis_key = MemKey_User::temp_arenas_pre_reward_md5_str(req()->zoneid, req()->uid);
        $md5 = md5($gateId . $difficulty . $_rewards);
        gMem()->set($redis_key, $md5, 86400);                                   # 有效期一天,有新的就覆盖
        return Resp::ok(array("r" => $_rewards));                               # 返回奖励字符串
// 生成奖励串, 写入redis一个md5(过期时间1day)
// 奖励串返回客户端
// 客户端根据奖励串展示奖励
// 最后再将奖励串通过挑战接口返回给服务端,
// 服务端计算奖励传的md5并与redis中的md5做对比.(这里最好采用字段排序后的字符串或者啥的,避免中间因json序列化/反序列化时改变字符串)
    }

    /**
     * [6806] 领取章节星数奖励
     */
    public static function DrawChapterStarsReward() {
        list($chapterId, $hard, $stars) = req()->paras;                         # 参数: 章节id, 难度, 分数
        $hard = $hard + 1;
        $userGates = ctx()->gates();
        if (!property_exists($userGates->chapterStarsRwd, $chapterId)) {        # 防御第一次读取本章节数据
            $userGates->chapterStarsRwd->$chapterId = ObjectInit();
        }
        $chapterInfo = $userGates->chapterStarsRwd->$chapterId;                 # 本章节数据
        if (!property_exists($chapterInfo, $hard)) {                            # 防御当前难度数据未创建
            $chapterInfo->$hard = array();
        }
        $starsArr = $chapterInfo->$hard;                                        # 当前章节,当前难度的领取记录 
        my_Assert(!in_array($stars, $starsArr), ErrCode::err_arenas_hasgetstarreward); # 奖励已领取
        $rwdCfgArr = GameConfig::gate_starreward_getItem($chapterId, $hard);    # 奖励配置数组 
        $starCfg = StlUtil::arrayFind($rwdCfgArr, function ($v, $k)use ($stars) { # 在数组中查找到对应星数的奖励
                    return ($v->star == $stars);
                });
        my_Assert(null != $starCfg, ErrCode::err_arenas_starreward_const_no);   # 找不到指定星数的配置数据
        $sumOfStars = 0;
        $userGateL = null;
        switch ($hard) {                                                        # 取不同难度数据记录
            case 1:
                $userGateL = new Ins_UserGatesModel($userGates->normal);
                break;
            case 2:
                $userGateL = new Ins_UserGatesModel($userGates->hard);
                break;
            case 3:
                $userGateL = new Ins_UserGatesModel($userGates->elite);
                break;
            default:
                break;
        }
        my_Assert(null != $userGateL, ErrCode::err_innerfault);                 # 玩家数据有问题 
        array_walk($userGateL->gates, function ($v, $k)use (&$sumOfStars) {     # 累加星数
            $sinfo = new GateStar($v->star);
            $sumOfStars += $sinfo->Stars();
        });
        my_Assert($stars <= $sumOfStars, ErrCode::err_arenas_starreward_starNotEnough); # 星数未达标
        StoreProc::AddMultiItemInStore($starCfg->reward);                       # 发放奖励
        $starsArr[] = $stars;                                                   # 领奖记录
        $userGates->chapterStarsRwd->$chapterId->$hard = $starsArr;             # 回写数据

        UserProc::updateUserInfo();
        return Resp::ok(array("store" => ctx()->store(),
                    'gold' => ctx()->base()->gold,
                    'cash' => ctx()->base()->cash
        ));         # 返回值  
    }

    /**
     * [6801] 关卡挑战1次 
     */
    public static function Arenas_Fight() {
        list($gateId, $difficulty, $star, $TeamObj) = req()->paras;             # 提取参数: 挑战的关卡Id, 关卡难度(0,1,2), 几星, 队伍, 奖励字符串
        my_Assert($gateId > 0, ErrCode::err_arenasgate_indexillegal);           # 关卡id非法
//        $md5 = gMem()->get(MemKey_User::temp_arenas_pre_reward_md5_str($req->zoneid, $req->uid));
//        $_md5 = md5($gateId . $difficulty . $rewardStr);
//        my_Assert($md5 == $_md5, ErrCode::err_arenas_rewardIllegal);            # 奖励不匹配
        $isFirst = false;                                                       # 是否首次通关
        self::recordFight($gateId, $difficulty, $star, $isFirst);         # 更新挑战记录 
        $smGate = GameConfig::gate_getItem($gateId);                            # 关卡配置数据
        $i = $difficulty + 1;                                                   # 按三个难度取不同的值. 
//        $gold = self::getProperty_n($smGate, "gold", $i);
        $exp = self::getProperty_n($smGate, "exp", $i);
        $firstExp = self::getProperty_n($smGate, "first_exp", $i);
        $firstHero = self::getProperty_n($smGate, "first_hero", $i);
        $heroExp = self::getProperty_n($smGate, "heroExp", $i);
        if ($isFirst) {                                                         # 是否首次通关切换奖励内容
            $exp = $firstExp;
            if ($firstHero > 0) {                                               # 首次通关解锁英雄
                HeroProc::AddHeroWithStar(req(), $firstHero, 0);                 # 添加英雄
            }
        }

//        $rewardArr = self::SetRewards($req, $rewardStr);                        # 发通关奖励 
//        Data_UserGame::Add_Gold($req->userInfo->game->baseInfo, $gold);         # 发金币
//        Data_UserGame::Add_Exp(req()->userInfo->game->baseInfo, $exp);           # 给玩家(指挥官)增加经验
        req()->userInfo->game->base()->Add_Exp($exp);                           # 给玩家(指挥官)增加经验
        foreach ($TeamObj as $heroUID) {
            if ($heroUID > 0) {
                echoLine("$heroUID");
                HeroProc::HeroAddEXP($heroUID, $heroExp);                       # 增加英雄经验 
            }
        }
        UserProc::updateUserInfo();                                             # 回写玩家数据.
#
        TaskProc::OnPassGateN($gateId, $difficulty + 1);
        $user = req()->userInfo->game;
        $result = array(
            'store' => $user->store,
            'heros' => $user->heros,
            'gates' => $user->gates,
            'tili' => $user->base()->tili,
            'time' => $user->privateState->TiliTime,
            'gold' => $user->base()->gold,
            'resPoint' => $user->base()->resPoint,
            'cash' => $user->base()->cash,
            'exp' => $exp,
//            'rewardstr' => implode(';', $rewardArr),
            'isFirst' => $isFirst,
        );
        return Resp::ok($result);
    }

    /**
     * 发放奖励串
     * @param Req $req
     * @param type $rewardStr
     */
    public static function SetRewards($rewardStr) {
        $getedArr = array();                                                    # 统计所获奖励物品
        $rewardsArr = explode(";", $rewardStr);
        foreach ($rewardsArr as $r) {                                           #    
            if (strlen($r) > 0) {
//            $percentStr = explode(',', $r)[2];
//            $percent = intval(trim($percentStr, "%"));                          # 剔除%
//            if (CommUtil::randomPercent($percent)) {
                $err = StoreProc::AddMultiItemInStore($r);                      # 发放奖励物品
                my_Assert($err == ErrCode::ok, $err);                           # 出错了
                $getedArr[] = $r;                                               # 剔除最后一段概率字符串
//            }
            }
        }
        return $getedArr;
    }

    /**
     * 更新战斗记录 
     * @param type $gateId
     * @param type $difficulty
     * @param type $star
     */
    private static function isFirstChallenge($gateId, $difficulty) {
        $userGates = req()->userInfo->game->gates;
        if ($difficulty == 0) {                                                 # 按照难度查找
            $diffCult = $userGates->normal;
        } else if ($difficulty == 1) {
            $diffCult = $userGates->hard;
        } else if ($difficulty == 2) {
            $diffCult = $userGates->elite;
        } else {
            Err(ErrCode::err_arenas_difficulty);                                # 找不到难度类型
        }

        $typeId = substr($diffCult->highest, 0, 3);                             # 防御: 分类头不对
        if ($typeId != '503') {
            $diffCult->highest = 503000;                                        # 设置为关卡第一关
        }
        if ($gateId > $diffCult->highest + 1) {                                 # 不能跳关
            Err(ErrCode::err_arenasgate_indexillegal);
        }

        $uGate = new Ins_UGate();                                               # 当前关卡的记录数据
        if (isset($diffCult->gates->$gateId)) {
            $uGate = $diffCult->gates->$gateId;
        }

        return !$uGate->cleared;
    }

    /**
     * 更新战斗记录 
     * @param type $gateId
     * @param type $difficulty
     * @param type $star
     */
    private static function recordFight($gateId, $difficulty, $star, &$isFirst = false) {
        $userGates = req()->userInfo->game->gates;
        if ($difficulty == 0) {                                                 # 按照难度查找
            $diffCult = $userGates->normal;
        } else if ($difficulty == 1) {
            $diffCult = $userGates->hard;
        } else if ($difficulty == 2) {
            $diffCult = $userGates->elite;
        } else {
            Err(ErrCode::err_arenas_difficulty);                                # 找不到难度类型
        }

        $typeId = substr($diffCult->highest, 0, 3);                             # 防御: 分类头不对
        if ($typeId != '503') {
            $diffCult->highest = 503000;                                        # 设置为关卡第一关
        }

        if ($gateId > $diffCult->highest + 1) {                                 # 不能跳关
            Err(ErrCode::err_arenasgate_indexillegal);
        }

        if ($gateId == $diffCult->highest + 1 && $star > 0) {                   # 星级大于等于0,才可以推关
            $diffCult->highest += 1;                                            # 更新最高记录
            RankProc::recordNewPassGateInfo(req()->uid, $gateId);                # 更新通关记录
        }
        $diffCult->latest = $gateId;                                            # 记录上次挑战关卡id

        $uGate = new Ins_UGate();                                               # 当前关卡的记录数据
        if (isset($diffCult->gates->$gateId)) {
            $uGate = $diffCult->gates->$gateId;
        }
        $uGate->challengeTimes++;                                               # 当前关卡挑战次数
        $uGate->star |= $star;                                                  # 当前关卡得分评星 
        if (!$uGate->cleared) {
            $uGate->cleared = 1;                                                # 当前关卡是否已通关     
            $isFirst = true;
        }
        $diffCult->gates->$gateId = $uGate;                                     # 回写关卡记录

        $userGates->TotalNum++;                                                 # 总战斗次数+1 
        $userGates->Times++;
        req()->userInfo->game->gates = $userGates;                               # 回写数据
    }

    /**
     * 清理每个难度副本的每日战斗次数 
     */
    public static function ClearGateTimes() {
        req()->userInfo->game->gates->Times = 0;
    }

//
// <editor-fold defaultstate="collapsed" desc=" 扫荡  ">

    /**
     * [6802]新扫荡 
     */
    public static function Arenas_NewSweepFight() {
        Err(ErrCode::err_method_obsoleted);                                     # 没开扫荡功能
        list($gateId, $difficulty, $costItemId) = req()->paras;                 # 关卡id, 难度 difficulty, 扫荡券id

        $user = req()->userInfo->game;
        $smGate = GameConfig::gate_getItem($gateId);
        my_default_Obj($user->gates->newGateRecord);                            # 防御未初始化的变量
        $gatesRecord = $user->gates->newGateRecord;
        my_default_Obj($gatesRecord->record);                                   # 防御未初始化的变量

        $i = $difficulty + 1;                                                   // 按三个难度取不同的值.
        $tili = self::getProperty_n($smGate, "tili", $i);
        $reward = self::getProperty_n($smGate, "reward", $i);
        $gold = self::getProperty_n($smGate, "gold", $i);
        $exp = self::getProperty_n($smGate, "exp", $i);
        $err = StoreProc::removeItemFromStore($user->store, $costItemId, 1);
        my_Assert(ErrCode::ok == $err, $err);                                   # 扣除失败
        $canfighterr = SweepGatesProc::CanFight($gateId, $difficulty);          # 补充战斗记录
        if ($canfighterr) {#不能符合战斗要求
            return $canfighterr;
        }
        $user->gates->newGateRecord = $gatesRecord;                             # 回写数据
        ActiveProc::ChangeTili(- $tili);                                        # 扣减体力
        $user->gates->TotalNum++;                                               # 更新战斗次数统计
        $user->gates->Times++;

        $rewardsArr = explode(";", $reward);
        $rwds = array();
        foreach ($rewardsArr as $r) {                                          // 按照概率规则发放奖品
            $arr = explode(',', $r);
            $itemid = intval($arr[0]);
            $num = intval($arr[1]);
            $probability = intval($arr[2]);
            if (CommUtil::randomPercent($probability)) {                        # 投色子
                $err = StoreProc::AddMultiItemInStore("$itemid,$num");
                my_Assert(ErrCode::ok == $err, $err);
                $rwds[] = "$itemid,$num";
            }
        }
        $user->base()->Add_Gold($gold);                                         # 发放金币奖励 
        my_Assert(ErrCode::ok == $err, $err);                                   # 失败
//        Data_UserGame::Add_Exp($user->baseInfo, $exp);                          # 发放经验奖励
        $user->base()->Add_Exp($exp);                                           # 发放经验奖励
        UserProc::updateUserInfo();                                             # 在获取战利品哪里已经update了.
        $result = array(
            'store' => $user->store,
            'heros' => $user->heros,
            'gates' => $user->gates,
            'tili' => $user->base()->tili,
            'time' => $user->privateState->TiliTime,
            'gold' => $gold,
            'exp' => $exp,
            'rewardstr' => implode(';', $rwds)
        );
        return Resp::ok($result);
    }

    /**
     * 是否可以战斗 
     * @param $gateId
     * @param $difficulty
     * @return type
     */
    static function CanFight($gateId, $difficulty) {
        $gatesRecord = req()->userInfo->game->gates->newGateRecord;
        $smGate = GameConfig::gate_getItem($gateId);
        if (!CommUtil::isPropertyExists($gatesRecord->record, $gateId)) {
            $gatesRecord->record->$gateId = ObjectInit();
        }
        if ($difficulty > 2) {
            return Resp::err(ErrCode::err_arenasgate_indexillegal);
        }
        if ($difficulty == 0) {
            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "normal")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }

            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "normalToday")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            if ($smGate->cishu1 - $gatesRecord->record->$gateId->normalToday < 1) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            $gatesRecord->record->$gateId->normalToday += 1;
        } else if ($difficulty == 1) {

            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "hard")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "hardToday")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }

            if ($smGate->cishu2 - $gatesRecord->record->$gateId->hardToday < 1) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            $gatesRecord->record->$gateId->hardToday += 1;
        } else if ($difficulty == 2) {
            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "elite")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }

            if (!CommUtil::isPropertyExists($gatesRecord->record->$gateId, "eliteToday")) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            if ($smGate->cishu3 - $gatesRecord->record->$gateId->eliteToday < 1) {
                return Resp::err(ErrCode::err_arenas_normalgate_numno);
            }
            $gatesRecord->record->$gateId->eliteToday += 1;
        }
        return null;   // false
    }

// </editor-fold> 
//
// <editor-fold defaultstate="collapsed" desc="    好友租借   ">
//    /**
//     * [6805] 查询租借好友记录
//     * @param Req $req
//     */
//    public static function GetBorrowedFriends($req) {
//// 查询好友借用记录中的数据
//        $rentedfriends = $req->userInfo->game->privateState->rentedFriends;
//        if (!$rentedfriends || !is_array($rentedfriends)) {
//            $rentedfriends = ArrayInit();
//        }
//        return Resp::ok(array('ret' => $rentedfriends));
//    }
//
//    /**
//     * 清理战斗租借好友记录
//     *
//     */
//    public static function ClearFightRentRecord($req) {
//        $req->userInfo->game->privateState->rentedFriends = ArrayInit();
//    }
//
//    /**
//     * [6806] 扣除借用好友费用
//     * @param Req $req
//     */
//    public static function ConsumeBorrowFriend($req) {
//// 提取参数:好友id
//        $friend_uid = $req->paras[0];
//// 验证好友关系
//        if (!FriendProc::isFriendship($req->zoneid, $req->uid, $friend_uid)) {
//            return Resp::err(ErrCode::friend_no_err);
//        }
//// 验证尚未租借过
//        $rentedfriends = $req->userInfo->game->privateState->rentedFriends;
//        if (!$rentedfriends || !is_array($rentedfriends)) {
//            $rentedfriends = ArrayInit();
//        }
//        if (in_array($friend_uid, $rentedfriends)) {
//            return Resp::err(array('err' => -1, 'msg' => 'has rented this player today!'));
//        }
//// 验证好友出借英雄
//        $friend_info = UserProc::getUserInfo(gMem(), $req->zoneid, $friend_uid);
//        if (!$friend_info) {
//            return Resp::err(ErrCode::user_no_err, '找不到好友的游戏数据!');
//        }
//// todo:啦啦啦... 先不写了,管它用的是哪个英雄呢
////
//// 扣除费用,失败->金币不足
//        $arr = explode(',', glc()->User_Friends_HireFriendForBattle_Cost);
//        if (count($arr) < 2) {
//            return Resp::err(ErrCode::err_const_no);
//        }
//        $itemid = $arr[0];   # 道具id
//        $amt = $arr[1];      # 数量
//        if ($itemid == META_GOLD_ITEMID) {
//            $user = $req->userInfo->game;
//            if ($user->gold < $amt) {
//                return Resp::err(array('err' => -2, 'msg' => 'gold not enough!'));
//            }
//            UserGameModel::Consume_Gold($user, $amt);
//// todo: 给好友发送金币 邮件
//            EmailProc::SendHireCoinFromFight($req->zoneid, $friend_uid, #
//                    $req->userInfo->game->name, $req->uid, $amt); # 好友收益需要扣除系统税率.
//        } else {
//            return Resp::err(ErrCode::err_const_no);
//        }
//// 添加借用记录
//        $rentedfriends[] = $friend_uid;
//        $req->userInfo->game->privateState->rentedFriends = $rentedfriends;
//// 回写数据
//        UserProc::updateUserInfo($req);                     // 玩家数据
////        UserProc::setUserInfo(global_mem(), $friend_info);  // 好友数据
//// 返回
//        return Resp::ok(array('err' => 0, 'curgold' => $user->gold));
//    }
// </editor-fold>
// 
// <editor-fold defaultstate="collapsed" desc="黄金挑战">
//    /**
//     * [6804] 扣除买buffer的费用
//     * @param type $req
//     * @return type
//     */
//    public static function ConsumeBufferGold($req) {
//        $user = $req->userInfo->game; # user引用
//        $money = $req->paras[0]; //需要的手工费
//// echo var_dump($money);
//        $bDeal = UserGameModel::Consume_Gold($user, $money);
//        if ($bDeal) {
//            $result = array(
//                'resp' => "succeed!"
//            );
////  更新数据库数据
//
//            $resp = Resp::ok($result);
//        } else {
//
////   $user->gold=0;
//            $result = array(
//                'resp' => "succeed!"
//            );
////  更新数据库数据
//
//            $resp = Resp::ok($result);
//        }
//        UserProc::updateUserInfo($req);
//        return $resp;
//    }
//    /**
//     * [6807] 挑战黄金 无穷无尽战斗模式
//     * @param type $req
//     */
//    public static function ChallengeEndlessFightMode_Gold($req) {
//        $gateForeverId = $req->paras[0];
//        $difficuty = $req->paras[1];
//        $bociCount = $req->paras[2];
////判断是否已经达到挑战的次数上限
//        $gates = $req->userInfo->game->gates;
//
//        if (!CommUtil::isPropertyExists($gates, "forever_Gold_FightTimes")) {
//            $gates->forever_Gold_FightTimes = 0;
//        }
//
//        if ($gates->forever_Gold_FightTimes >= glc()->Battle_Forever_MaxCountEveryDay) {
//            return Resp::err(ErrCode::err_gateForever_countIsFull, '挑战次数已经用尽!');
//        }
////1.取出无尽模式的关卡常量数据
//        $gateForeverConst = GameConfig::gateforever_getItem($gateForeverId);   // ConstProc::getGold_GateForeverGoldConst($gateForeverId);
//        $gateBattleBociConst = GameConfig::gatecombat_getItem($gateForeverId);
//        if (!$gateForeverConst) {
//            return Resp::err(ErrCode::err_gateForever_const_no);
//        }
////判断次数是否合法
//        $bociArr = explode(",", $gateBattleBociConst->level);
//        if ($bociCount > count($bociArr)) {
//            return Resp::err(ErrCode::err_gateForever_countillegal);
//        }
////2.取出模式下的奖励数据
//        $rewardStr = $gateForeverConst->reward1;
//
//        $arr_reward = explode(";", $rewardStr);
//        foreach ($arr_reward as $value) {
//            if (strlen($value) > 0) {
//
//                $arr_RealReward = explode(",", $value);
//                $itemId = $arr_RealReward[0];
//                $itemNum = $arr_RealReward[1];
//
//                $str1 = substr($itemId, 0, 3);
////3.根据挑战的波次数据，重复累计获得奖励
//                for ($i = 0; $i < $bociCount; $i++) {
//
//                    switch ($str1) {
/////怪物卡或者英雄卡牌获取
//                        case "101":
//                        case "201":
////                            HeroProc::AddHeroTFromStore($req, $itemId);
//                            break;
/////装备物品的获取.
//                        case "301":
//                        case "302":
//                        case "303":
//                            StoreProc::PutEquipInStore($itemId, $req);
//                            break;
/////宝石的获取
//                        case "304":
//                            StoreProc:: PutOverlyingItemInStore($itemId, $itemNum, $req);
//                            break;
////金币的获取
//                        case "399":
//                            if ($itemId == "399002") {
//                                UserGameModel::Add_Gold($req->mem, $req->userInfo->game, $itemNum);
//                            }
//                            break;
//                        default:
//                            break;
//                    }
//                }
//            }
//        }
////4、存储玩家的挑战次数
//        $gates->forever_Gold_FightTimes = $gates->forever_Gold_FightTimes + 1;
//// 回写数据
//        UserProc::updateUserInfo($req);
//        $result = ObjectInit();
//        $result->result = "succeed";
//        $result->forever_Gold_FightTimes = $gates->forever_Gold_FightTimes;
//        $resp = Resp::ok($result);
//        return $resp;
//    }
//    /**
//     * 清理挑战无尽模式的 次数记录
//     *
//     */
//    public static function ClearGateForeverGold_FightCountEveryDay($req) {
//        $req->userInfo->game->gates->forever_Gold_FightTimes = 0;
//    }
// </editor-fold>
//
// <editor-fold defaultstate="collapsed" desc="    副本    ">
//
//    /**
//     * [6801] 开启副本
//     * @param Req $req
//     * @deprecated since version 0
//     */
//    public static function OpenTheCarbon($req) {
//        $gates = $req->userInfo->game->gates;
//        $openedcarbons = $gates->carbons->openedCarbons;
//# 提取参数
//        $carbonId = $req->paras[0];     # 副本ID
//        $difficulty = $req->paras[1];   # 难度等级 1,2,3
//        $key = "$carbonId-$difficulty"; # 键值
//        if (!($gates && $openedcarbons)) {
//            return Resp::err(ErrCode::err_innerfault);
//        }
//        if ($difficulty > 3 || $difficulty < 1) {
//            return Resp::err(ErrCode::carbon_wrongdifficult);
//        }
//
//        if (CommUtil::isPropertyExists($openedcarbons, $key)) {
//            $carbon = $openedcarbons->$key;
//        } else {
//            $carbon = new CarbonModel();
//        }
//        if ($carbon->closeTs > now()) {
//            return Resp::err(ErrCode::carbon_opened);
//        }
//        $carbonModel = GameConfig::gate_carbon_getItem($carbonId); # 常量
//# 扣除开启消耗的道具
//        $keyid = "keyId$difficulty";
//        $keynum = "keyNum$difficulty";
//        $costItemId = $carbonModel->$keyid;
//        $costItemNum = $carbonModel->$keynum;
//
//        $err = StoreProc::removeItemFromStore($req->userInfo->game->store, $costItemId, $costItemNum);
//        if ($err) { # 扣除失败
//            return Resp::err($err);
//        }
//        $carbon->closeTs = now() + $carbonModel->duration;    # 关闭倒计时
//        $carbon->curIndex = 0;                                # 索引重置为0
//        $openedcarbons->$key = $carbon;
//        $req->userInfo->game->gates->carbons->openedCarbons = $openedcarbons;
//        UserProc::updateUserInfo($req);
//        return Resp::ok(array('err' => 0, 'carbons' => $openedcarbons));
//    }
//    /**
//     * 挑战副本关卡
//     * @param Req $req
//     * @deprecated since version number
//     */
//    public static function ChallengeCarbon($req) {
//        $gates = $req->userInfo->game->gates;
//        $carbons = $gates->carbons->openedCarbons;
//# 提取参数
//        $carbonId = $req->paras[0];     # 副本ID
//        $difficulty = $req->paras[1];   # 难度等级 1,2,3
//        $gateindex = $req->paras[2];    # 关卡索引 0,1,2,...
//        $star = $req->paras[3];         # 战斗评价(几星)
//        $TeamObj = $req->paras[4];      # 队伍信息
////        $bossId = $req->paras[5];       # 本关消灭的bossid (<=0代表本关卡未出现boss)
//        if ($difficulty > 3 || $difficulty < 1) {
//            return Resp::err(ErrCode::carbon_wrongdifficult);
//        }
//        $key = "$carbonId-$difficulty"; # 键值
//# 0 当前副本处于开启状态
//# 1 当前关卡索引,不能跳着打,
//# 2 记录下战斗评价(几星), 也许以后用得着,比如最后通关后,给个啥奖励
//# 3 决定掉落物品, 发给客户端
//# 4 发放对应的经验之类的东西
//# 5 检查是否最后一个关卡, 是, 关闭副本
//# 6 回存数据,返回
//
//        isEditor() && $carbon = new CarbonModel;
//        if (CommUtil::isPropertyExists($carbons, $key)) {
//            $carbon = $carbons->$key;
//        } else {
//            $carbon = null;
//        }
//        if (!$carbon || $carbon->closeTs < now()) {
//            return Resp::err(ErrCode::carbon_closed);
//        }
//
//        $carbonModel = GameConfig::gate_carbon_getItem($carbonId); # 副本常量数据
//        $gateIds = explode(',', $carbonModel->gateids);
//        if ($gateindex < 0 || $gateindex >= count($gateIds)) {
//            return Resp::err(ErrCode::carbon_gateIndex);
//        }
//        if ($carbon->curIndex == $gateindex || $gateindex == 0) {
//            $carbon->curIndex += 1; # 更新进度
//        } else { # 不能跳关
//            return Resp::err(ErrCode::carbon_gateIndex);
//        }
//
//        $gateId = $gateIds[$gateindex];    # 通过索引获得关卡ID
//        $tl = "tili$difficulty";           # 体力难度
//        $rwd = "reward$difficulty";        # 奖励难度
//        $arr = array("normal", 'hard', 'elite');  # 难度名称
//        $gt = $arr[$difficulty - 1];       # 关卡分类
//        $gateModel = GameConfig::gate_carbon_content_getItem($gateId); # 副本关卡常量数据
//        $tili = $gateModel->$tl;                        # 扣除体力
//        $reward = $gateModel->$rwd;                     # 获得奖励
//#
//# 打副本呢也要扣除体力
//        ActiveProc::ChangeTili(-$tili, $req);
//# 扣除多少体力就给账号增加多少经验 -by 李宁, reconfirmed by wg 20170519144109
//        UserGameModel::Add_Exp($req, $tili);
//# 增加英雄经验(也是依据扣除的体力数)
//        foreach ($TeamObj as $heroUID) {
//            HeroProc::HeroAddEXP($heroUID, $tili, $req);
//        }
////        $carbon->stars;  暂不记录了
//# 掉落战利品->获取
//        $err = StoreProc::AddMultiItemInStore($req, $reward);
//        if ($err) {
//            return Resp::err($err);
//        }
//        if (count($gateIds) == $gateindex + 1) { # 最后一个关卡
//            unset($carbons->$key);               # 关闭掉关卡,或者是直接删掉
//        } else {
//            $carbons->$key = $carbon;            # 回存数据
//        }
//        $req->userInfo->game->gates->carbons->openedCarbons = $carbons;
//        UserProc::updateUserInfo($req); //在获取战利品哪里已经update了.
//        # Ps.备注,奖品是固定的,所以不必返回
//        $result = array(
//            'store' => $req->userInfo->game->store,
//            'heros' => $req->userInfo->game->heros,
//            'gates' => $req->userInfo->game->gates,
//            'tili' => $req->userInfo->game->tili,
//            'time' => $req->userInfo->game->privateState->TiliTime
//        );
//        return Resp::ok($result);
//    }
//    /**
//     * [6809]新版本的挑战 副本胜利
//     * @param Req $req
//     * @deprecated since version 0
//     */
//    public static function NewChallengeCarbon($req) {
//        $gates = $req->userInfo->game->gates;
//        $carbons = $gates->carbons->openedCarbons;
//# 提取参数
//        $carbonId = $req->paras[0];     # 副本ID
//        $gateId = $req->paras[1]; # 关卡ID
//        $difficulty = $req->paras[2];   # 难度等级 1,2,3
//
//        $star = $req->paras[3];         # 战斗评价(几星)
//        $TeamObj = $req->paras[4];      # 队伍信息
//
//        if ($difficulty > 3 || $difficulty < 1) {
//            return Resp::err(ErrCode::carbon_wrongdifficult);
//        }
//        $key = "$carbonId-$difficulty"; # 键值
//        # 0 当前副本处于开启状态
//        # 1 战斗胜利之后，副本直接关闭
//        # 2 记录下战斗评价(几星), 也许以后用得着,比如最后通关后,给个啥奖励
//        # 3 决定掉落物品, 发给客户端
//        # 4 发放对应的经验之类的东西
//        # 5 检查是否最后一个关卡, 是, 关闭副本
//        # 6 回存数据,返回
//
//        isEditor() && $carbon = new CarbonModel;
//        if (CommUtil::isPropertyExists($carbons, $key)) {
//            $carbon = $carbons->$key;
//        } else {
//            $carbon = null;
//        }
//        if (!$carbon || $carbon->closeTs < now()) {
//            return Resp::err(ErrCode::carbon_closed);
//        }
//        unset($carbons->$key);
//        $tl = "tili$difficulty";           # 体力难度
//        $rwd = "reward$difficulty";        # 奖励难度
//
//        $gateModel = GameConfig::gate_carbon_content_getItem($gateId); # 副本关卡常量数据
//        $tili = $gateModel->$tl;                        # 扣除体力
//        $reward = $gateModel->$rwd;                     # 获得奖励
//        #
//        # 打副本呢也要扣除体力
//        ActiveProc::ChangeTili(-$tili, $req);
//
//        // 按照概率规则发放奖品
//        $rewardsArr = explode(";", $reward);
//        $rwds = array();
//        foreach ($rewardsArr as $r) {
//            $arr = explode(',', $r);
//            $itemid = intval($arr[0]);
//            $num = intval($arr[1]);
//            $probability = floatval($arr[2]);                                   # 掉落概率精度精确到±0.01%
//            if (CommUtil::randomPercent($probability)) {                        # 投色子
//                $err = StoreProc::AddMultiItemInStore($req, "$itemid,$num");
//                if ($err) {
//                    return Resp::err($err);
//                }
//                $rwds[] = "$itemid,$num";
//            }
//        }
//
//        if ($err) {
//            return Resp::err($err);
//        }
//
//        $req->userInfo->game->gates->carbons->openedCarbons = $carbons;
//        UserProc::updateUserInfo($req); //在获取战利品哪里已经update了.
//        # Ps.备注,奖品是固定的,所以不必返回
//        SystemProc::Carbon_Win($req->zoneid, $req->userInfo->game, $carbonId, $difficulty); # 插入通过副本消息
//        $result = array(
//            'store' => $req->userInfo->game->store,
//            'heros' => $req->userInfo->game->heros,
//            'gates' => $req->userInfo->game->gates,
//            'tili' => $req->userInfo->game->tili,
//            'time' => $req->userInfo->game->privateState->TiliTime,
//            'gold' => 0,
//            'exp' => 0,
//            'rewardstr' => implode(';', $rwds)
//        );
//        return Resp::ok($result);
//    }
//    /**
//     * [6816] 挑战剧情关卡
//     * @param type $req
//     * @deprecated since version 0
//     */
//    public static function ChallengeStoryGate($req) {
//        $gates = $req->userInfo->game->gates;
//# 提取参数
//        $storyId = $req->paras[0];      # 剧情ID
//        $difficulty = $req->paras[1];   # 难度等级 1,2,3
//        $star = $req->paras[2];         # 战斗评价(几星)
//        $TeamObj = $req->paras[3];      # 队伍信息
//        $bossId = $req->paras[4];       # 本关消灭的bossid (<=0代表本关卡未出现boss)
////
//#1.   判断是否有记录过剧情的战斗信息
//        if (!CommUtil::isPropertyExists($gates, "story")) {
//            $gates->story = ObjectInit();
//            $gates->story->lastFinishedStoryGateId = 0;
//            $gates->story->allFinishedStoryGateIdList = ArrayInit();
//        }
//        $storrRecord = $gates->story;
//#2.取出模式下的奖励数据
//        $memStoryModel = GameConfig::gatestory_getItem($storyId);
//        $tili = 0;
//        $rewardStr = $memStoryModel->storyGateReward;
//
//#3 同步下剧情的推进进度数据
//        if ($storrRecord->lastFinishedStoryGateId == $storyId || in_array($storyId, $storrRecord->allFinishedStoryGateIdList)) {
//            return Resp::err(ErrCode::story_repeatfight); #剧情关卡不能重复战斗 只能打一次
//        } else {
//            $storrRecord->lastFinishedStoryGateId = $storyId;
//            $storrRecord->allFinishedStoryGateIdList[] = $storyId;
//        }
//#
//# 4 万一打剧情也扣除体力呢
//        if ($tili > 0) {
//            ActiveProc::ChangeTili(-$tili, $req);
//# 扣除多少体力就给账号增加多少经验 -by 李宁, reconfirmed by wg 20170519144109
//            UserGameModel::Add_Exp($req, $tili);
//# 增加英雄经验(也是依据扣除的体力数)
//            foreach ($TeamObj as $heroUID) {
//                HeroProc::HeroAddEXP($heroUID, $tili, $req);
//            }
//        }# 5 玩家获得 剧情的战斗奖励
//        $err = StoreProc::AddMultiItemInStore($req, $rewardStr);
//        if ($err) {
//            return Resp::err($err);
//        }# 6 回存玩家的战斗记录
//        $req->userInfo->game->gates->story = $storrRecord;
//        UserProc::updateUserInfo($req); //在获取战利品哪里已经update了.
//        # Ps.备注,奖品是固定的,所以不必返回
//        $result = array(
//            'store' => $req->userInfo->game->store,
//            'heros' => $req->userInfo->game->heros,
//            'gates' => $req->userInfo->game->gates,
//            'tili' => $req->userInfo->game->tili,
//            'time' => $req->userInfo->game->privateState->TiliTime
//        );
//        return Resp::ok($result);
//    }
//
// </editor-fold>
//
}

/**
 * 任务/挑战目标达成记录(三星评价)
 * @author gwang
 */
class GateStar {

    /**
     * 根据后台记录的数值构造(反向提供给前端显示层)
     * @param int $i
     */
    public function __construct($i) {
        $this->S1 = ($i & 1) > 0;
        $this->S2 = ($i & 2) > 0;
        $this->S3 = ($i & 4) > 0;
    }

    /**
     * @var bool 第一个目标达成
     */
    public $S1;

    /**
     * @var bool 第二个目标达成
     */
    public $S2;

    /**
     * @var bool 第三个目标达成
     */
    public $S3;

    /**
     * 统计总星数
     * @return int
     */
    public function Stars() {
        return ($this->S3 ? 1 : 0) + ($this->S2 ? 1 : 0) + ($this->S1 ? 1 : 0);
    }

}
