import { dicHero, loadHero } from "./dictionary/DicHero";
import { dicGoods, figureCondition, loadGoods } from "./dictionary/DicGoods";
import { dicDaily, loadDaily } from "./dictionary/DicDaily";
import { dicEvent, dicEventList, loadEvent } from "./dictionary/DicEvent";
import { dicExpedition, DicExpedition, loadExpedition } from "./dictionary/DicExpedition";
import { dicExpeditionPoint, loadExpeditionPoint } from "./dictionary/DicExpeditionPoint";
import { dicJob, jobClassAndgrades, jobClassMaxGrades, loadJob, talentPointOfJob } from "./dictionary/DicJob";
import { dicKingExp, maxPlayerLv, loadKingExp } from "./dictionary/DicKingExp";
import { dicCharExp, loadCharExp } from "./dictionary/DicCharExp";
import { dicQuestion, loadQuestion } from "./dictionary/DicQuestion";
import { dicSe, loadSe } from "./dictionary/DicSe";
import { dicTower, loadTower } from "./dictionary/DicTower";
import { dicTowerTask, loadTowerTask } from "./dictionary/DicTowerTask";
import { dicWar, dicWarPvp, dicDailyWarByType, loadWar, dicHeroIdByWar, dicComBattleReward } from "./dictionary/DicWar";
import { dicWarJson, loadWarJson } from "./dictionary/DicWarJson";
import { AUCTION_TIME } from "../consts";
import { dicFashions, dicFashionsByHeroId, loadFashions } from "./dictionary/DicFashions";
import { friendShips, friendShipsByLv, friendShipsMax, loadFriendShip } from "./dictionary/DicFriendShip";
import { dicHeroQualityUp, loadHeroQualityUp } from "./dictionary/DicHeroQualityUp";
import { dicHeroStar, loadHeroStar } from "./dictionary/DicHeroStar";
import { dicHeroWake, loadHeroWake } from "./dictionary/DicHeroWake";
import { dicRandomEffectPool, loadRandomEffectPool, dicRandomEffectPoolByGroupAndLv } from './dictionary/DicRandomEffectPool';
import { dicTitle, loadTitle } from './dictionary/DicTitle';
import { dicTeraph, loadTeraph } from './dictionary/DicTeraph';
import { dicSchool, loadSchool } from './dictionary/DicSchool';
import { dicSchoolRate, loadSchoolRate } from './dictionary/DicSchoolRate';
import { dicHeroScroll, preHeroScroll, loadHeroScroll } from './dictionary/DicHeroScroll';
import { dicPvpOpponent, loadPvpOpponent } from './dictionary/DicPvpOpponent';
import { dicPvpTeamLevel, loadPvpTeamLevel } from './dictionary/DicPvpTeamLevel';
import { dicPvpRefreshConsume, maxPvpRefreshCnt, loadPvpRefreshConsume } from './dictionary/DicPvpRefreshConsume';
import { dicHeroRewads, loadPvpHeroReward } from './dictionary/DicPvpHeroReward';
import { dicRankRewads, dicRankMax, loadPvpRankReward, DicRankRewads } from './dictionary/DicPvpRankReward';
import { DicPvpBox, dicPvpBoxesBySeasonNum, dicPvpBoxs, loadPvpBox } from './dictionary/DicPvpBox';
import { dicGuildAuth, loadGuildAuth } from './dictionary/DicGuildAuth';
import { dicCenterBase, dicEquipPriduceBase, dicBossBase, dicTrainBase, dicDonateBase, dicStructureConsume, dicBossBaseByBossLv, loadStructure } from "./dictionary/DicStructure";
import { dicGuildActiveDayReward, loadGuildActiveDayReward } from './dictionary/DicGuildActiveDayReward';
import { dicGuildActiveWeekReward, loadGuildActiveWeekReward } from './dictionary/DicGuildActiveWeekReward';
import { dicGuildActiveWays, loadGuildActiveWays } from './dictionary/DicGuildActiveWays';
import { dicGuildPosition, loadGuildPosition } from "./dictionary/DicGuildPosition";
import { dicMail, loadMail } from "./dictionary/DicMail";
import { dicArmyTrainJuDian, loadArmyTrainJuDian, dicLastGuildTrainIdOfLv, dicFirstGuildTrainIdOfLv } from './dictionary/DicArmyTrainJuDian';
import { dicTrainSoloReward, loadTrainSoloReward } from './dictionary/DicTrainSoloReward';
import { RewardInter } from "./interface";
import { dicArmyDevelopConsume, loadArmyDevelopConsume } from './dictionary/DicArmyDevelopConsume';
import { dicArmyBossRank, loadArmyBossRank } from './dictionary/DicArmyBossRank';
import { dicArmyDonate, loadArmyDonate } from './dictionary/DicArmyDonateBoxReward';
import { dicRoleFriend, DicRoleFriend, loadRoleFriend } from "./dictionary/DicRoleFriend";
import { dicRoleFriendLv, loadRoleFriendLv } from "./dictionary/DicRoleFriendLv";
import { AttributeCal } from "../domain/roleField/attribute";
import { dicGuildActivity, DicGuildActivity, loadGuildActivity } from './dictionary/DicGuildActivity';
import { dicGateActivityPoint, loadGateActivityPoint } from './dictionary/DicGateActivityPoint';
import { dicGuildAuction, loadGuildAuction } from './dictionary/DicGuildAuction';
import { getCurDay } from "./timeUtil";
import { dicCityActivity, dicJuniorCities, loadCityActivity } from "./dictionary/DicCityActivity";
import { dicChatAccuse, loadChatAccuse } from "./dictionary/DicChatAccuse";
import { dicCityActivityReward, loadCityActivityReward } from "./dictionary/DicCityActivityReward";
import { dicRaceActivity, dicRaceTypes, loadRaceActivity } from './dictionary/DicRaceActivity';
import { GUILDACTIVITY, RECRUIT } from "./dicParam";
import * as param from "./dicParam";
import { decodeIdCntArrayStr, parseGoodStr, decodeArrayListStr, getRandEelm, readTsFile, getRandSingleEelm, parseNumberList } from "./util";
import { RACE_EVENT_TYPE } from "../consts";
import { dicShopByType, dicShopItem, loadShop } from "./dictionary/DicShop";
import { dicShopType, loadShopType } from "./dictionary/DicShopType";
import { dicRank, loadRank } from "./dictionary/DicRank";
import { dicRankReward, loadRankReward } from "./dictionary/DicRankReward";
import { dicTaskType, taskMap, dicMainTask, dicDailyTask, dicAchievement, loadTask, dicPvpDailyTask } from "./dictionary/DicTask";
import { dicMainTaskStage, loadMainTaskStage } from "./dictionary/DicMainTaskStage";
import { dicTaskBox, loadTaskBox } from './dictionary/DicTaskBox';
import { dicGacha, dicGachaByGachaType, loadGacha } from "./dictionary/DicGacha";
import { dicGachaPlan, dicGachaPlanQuality, loadGachaPlan } from "./dictionary/DicGachaPlan";
import { dicGachaFloor, loadGachaFloor } from "./dictionary/DicGachaFloor";
import { dicGiftPackage, loadGiftPackage } from "./dictionary/DicGiftPackage";
import { dicRecruit, loadRecruit } from './dictionary/DicRecruit';
import { loadRMB, dicRMB } from './dictionary/DicRMB';
import { dicActivityType, loadActivityType } from './dictionary/DicActivityType';
import { DicTaskType, dicTaskTypeDesc, loadTaskType, taskDescByType } from './dictionary/DicTaskType';
import { dicServerName, loadServerName } from "./dictionary/DicServerName";
import { dicAp, loadAp, dicApMaxLevel } from './dictionary/DicAp';
import { dicApBuy, dicApMaxBuyTimes, loadApBuy } from "./dictionary/DicApBuy";
import { dicKingExpRatio, loadKingExpRatio } from './dictionary/DicKingExpRatio';
import { dicHoliday, loadHoliday } from './dictionary/DicHoliday';
import { dicExpeditionSubAttr, loadExpeditionSubAttr } from './dictionary/DicExpeditionSubAttr';
import { dicAuctionPool, loadAuctionReward } from './dictionary/DicAuctionReward';
import { dicGuildTrainInfo, loadGuildTrainInfo } from './dictionary/DicGuildTrainInfo';
import { dicPvpDifficultRatio, loadPvpDifficultRatio } from './dictionary/DicPvpDifficultRatio';
import { dicWhiteIp, loadWhiteIp } from './dictionary/DicWhiteIp';
import { dicGuildWishReward, loadGuildWishReward } from './dictionary/DicGuildWishReward';
import { dicApiById, dicApiByUrl, loadApi } from './dictionary/DicApi';
import { dicServerConst, loadServerConst } from './dictionary/DicServerConst';
const _ = require("underscore");
import { dicEquipById, dicEquipIdByJobClassAndEplace, loadEquip } from "./dictionary/DicEquip";
import { dicBlueprt, dicBlueprtByLv, dicJewel, loadJewel } from "./dictionary/DicJewel";
import { dicStone, loadStone } from './dictionary/DicStone';
import { dicEquipStrength, loadEquipStrength } from "./dictionary/DicEquipStrength";
import { dicEquipQuality, dicEquipQualityIdByEquipIdAndPoint, loadEquipQuality } from "./dictionary/DicEquipQuality";
import { dicEquipStar, dicEquipStarIdByEquipId, loadEquipStar } from './dictionary/DicEquipStar';
import { dicEquipQualityExtra, loadEquipQualityExtra } from './dictionary/DicEquipQualityExtra';
import { dicEquipSuit, dicEquipSuitByJobClass, loadEquipSuit } from "./dictionary/DicEquipSuit";
import { dicJewelCondition, loadJewelCondition } from './dictionary/DicJewelCondition';
import { dicMainStarBox, dicMainStarBoxByChapter, loadMainStarBox } from './dictionary/DicMainStarBox';
import { dicHeroTalent, initTalents, loadHeroTalent } from './dictionary/DicHeroTalent';
import { Talent } from "../db/Hero";
import { dicEquipStrengthAttr, loadEquipStrengthAttr } from './dictionary/DicEquipStrengthAttr';
import { dicTowerGift, loadTowerGift } from './dictionary/DicTowerGift';
import { dicTowerPvpSubAttr, loadTowerPvpSubAttr } from './dictionary/DicTowerPvpSubAttr';
import { dicSystemOpenTime, loadSystemOpenTime } from "./dictionary/DicSystemOpenTime";
import { dicRandomEffectPoolPlan, loadRandomEffectPoolPlan } from './dictionary/DicRandomEffectPoolPlan';
import { dicMainWarRewardByChapter, loadMainWarReward } from './dictionary/DicMainWarReward';
import { dicLadderMatch, loadLadderMatch } from "./dictionary/DicLadderMatch";
import { dicLadderDifficultRatio, loadLadderDifficultRatio } from "./dictionary/DicLadderDifficultRatio";
import { dicLadderRankReward, loadLadderRankReward } from "./dictionary/DicLadderRankReward";
import { dicGeneralGoods, loadGeneralGoods } from "./dictionary/DicGeneralGoods";
import { dicArtifact, dicArtifactByGid, dicArtifactByGidAndType, dicArtifactsByGroup, loadArtifact } from "./dictionary/DicArtifact";
import { DicArtifactLvPlan, dicArtifactLvPlan, loadArtifactLvPlan } from "./dictionary/DicArtifactLvPlan";
import { dicArtifactQuality, dicArtifactQualityById, loadArtifactQuality } from "./dictionary/DicArtifactQuality";
import { dicArtifactQualityPlan, loadArtifactQualityPlan } from "./dictionary/DicArtifactQualityPlan";
import { dicArtifactSeid, loadArtifactSeid } from "./dictionary/DicArtifactSeid";
import { DicArtifact } from "./dictionary/DicArtifact";
import { DicArtifactQuality } from "./dictionary/DicArtifactQuality";
import { dicGiftPackagePlan, loadGiftPackagePlan } from "./dictionary/DicGiftPackagePlan";
import { dicGiftPackageFloor, loadGiftPackageFloor } from "./dictionary/DicGiftPackageFloor";
import { dicGVGPeriod, loadGVGPeriod } from './dictionary/DicGVGPeriod';
import { dicGVGTech, loadGVGTech } from "./dictionary/DicGVGTech";
import { dicGVGItem, loadGVGItem } from "./dictionary/DicGVGItems";
import { dicGVGLeagueLv, loadGVGLeagueLv } from "./dictionary/DicGVGLeagueLv";
import { dicGVGResourceBase, dicGVGResourceBaseByType, dicGVGResourceBaseByLv, loadGVGResourceBase, DicGVGResourceBase } from './dictionary/DicGVGResourceBase';
import { dicGVGContributeBox, loadGVGContributeBox } from './dictionary/DicGVGContributeBox';
import { dicGVGArea, dicGVGCity, loadGVGArea } from './dictionary/DicGVGArea';
import { dicGVGCityAdd, loadGVGCityAdd } from './dictionary/DicGVGCityAdd';
import { dicGVGTask, dicGVGTaskByType, loadGVGTask } from './dictionary/DicGVGTask';
import { dicGVGVestigeByType, dicGVGVestigeName, loadGVGVestigeType } from './dictionary/DicGVGVestigeType';
import { dicGVGVestige, loadGVGVestige } from './dictionary/DicGVGVestige';
import { DicGVGVestigeRange, dicGVGVestigeRange, loadGVGVestigeRange } from './dictionary/DicGVGVestigeRange';
import { DicGVGVestigeLeagueRank, dicGVGVestigeLeagueRank, loadGVGVestigeLeagueRank } from "./dictionary/DicGVGVestigeLeagueRank";
import { DicGVGVestigePlayerRank, dicGVGVestigePlayerRank, loadGVGVestigePlayerRank } from "./dictionary/DicGVGVestigePlayerRank";
import { dicGVGAreaPoint, loadGVGAreaPoint, dicGVGPointsByAreaId } from "./dictionary/DicGVGAreaPoint";
import { DicGVGBattleRankReward, dicGVGBattleRankReward, loadGVGBattleRankReward } from './dictionary/DicGVGBattleRankReward';

export const gameData = {
    daily: dicDaily,
    event: dicEvent,
    eventList: dicEventList,
    expedition: dicExpedition,
    expeditionPoint: dicExpeditionPoint,
    goods: dicGoods,
    hero: dicHero,
    heroQualityUp: dicHeroQualityUp,
    heroStar: dicHeroStar,
    heroWake: dicHeroWake,
    job: dicJob,
    jobClassMaxGrades: jobClassMaxGrades,
    jobClassAndgrades: jobClassAndgrades,
    kingexp: dicKingExp,
    maxPlayerLv: maxPlayerLv,
    charexp: dicCharExp,
    question: dicQuestion,
    se: dicSe,
    tower: dicTower,
    towerTask: dicTowerTask,
    towerGift: dicTowerGift,
    war: dicWar,
    warJson: dicWarJson,
    dailyWarByType: dicDailyWarByType,
    btlBossHpSum: new Map<number, number>(),
    btlBossHp: new Map<number, Array<{ dataId: number, hp: number, actorId: number }>>(),
    fashion: dicFashions,
    fashionBySkinId: dicFashionsByHeroId,
    friendShips: friendShips,
    friendShipsByLv: friendShipsByLv,
    friendShipsMax: friendShipsMax,
    randomEffectPool: dicRandomEffectPool,
    randomEffectPoolByGroupAndLv: dicRandomEffectPoolByGroupAndLv,
    title: dicTitle,
    teraphs: dicTeraph,
    school: dicSchool,
    schoolRate: dicSchoolRate,
    heroScroll: dicHeroScroll,
    preHeroScroll: preHeroScroll,
    pvpOpponent: dicPvpOpponent,
    pvpTeamLevel: dicPvpTeamLevel,
    pvpWar: dicWarPvp,
    pvpRefreshConsume: dicPvpRefreshConsume,
    pvpDifficultRatio: dicPvpDifficultRatio,
    maxPvpRefreshCnt: maxPvpRefreshCnt,
    pvpHeroRewards: dicHeroRewads,
    pvpRankRewards: dicRankRewads,
    pvpBoxs: dicPvpBoxs,
    pvpBoxesBySeasonNum: dicPvpBoxesBySeasonNum,
    pvpRankMax: dicRankMax,
    guildAuth: dicGuildAuth,
    centerBase: dicCenterBase,
    equipProduceBase: dicEquipPriduceBase,
    bossBase: dicBossBase,
    bossBaseByBossLv: dicBossBaseByBossLv,
    trainBase: dicTrainBase,
    donateBase: dicDonateBase,
    guildTrainInfo: dicGuildTrainInfo,
    structureConsume: dicStructureConsume,
    guildActiveDayReward: dicGuildActiveDayReward,
    guildActiveWeekReward: dicGuildActiveWeekReward,
    guildPosition: dicGuildPosition,
    armyTrainJuDian: dicArmyTrainJuDian,
    lastGuildTrainIdOfLv: dicLastGuildTrainIdOfLv,
    firstGuildTrainIdOfLv: dicFirstGuildTrainIdOfLv,
    trainSoloReward: dicTrainSoloReward,
    mail: dicMail,
    guildActiveWays: dicGuildActiveWays,
    armyDevelopConsume: dicArmyDevelopConsume,
    armyBossRank: dicArmyBossRank,
    armyDonateBox: dicArmyDonate,
    roleFriend: dicRoleFriend,
    roleFriendLv: dicRoleFriendLv,
    figureCondition: figureCondition,
    guildActivity: dicGuildActivity,
    gateActivityPoint: dicGateActivityPoint,
    guildAuction: dicGuildAuction,
    cityActivity: dicCityActivity,
    juniorCities: dicJuniorCities,
    chatAccuse: dicChatAccuse,
    cityActivityReward: dicCityActivityReward,
    raceActivityEvents: dicRaceActivity,
    raceTypes: dicRaceTypes,
    raceActivityEncounter: { events: new Map<number, number>(), eventNum: 0 },
    raceNormalItems: new Array<{id: number, total: number, max: number}>(),
    raceEventItems: new Array<{id: number, count: number}>(),
    shopItemByType: dicShopByType,
    shopItem: dicShopItem,
    shopType: dicShopType,
    rank: dicRank,
    generalRankReward: dicRankReward,
    taskType: dicTaskType,
    tasks: taskMap,
    mainTask: dicMainTask,
    dailyTask: dicDailyTask,
    achievement: dicAchievement,
    pvpDailyTask: dicPvpDailyTask,
    mainTaskStage: dicMainTaskStage,
    taskBox: dicTaskBox,
    gacha: dicGacha,
    gachaByType: dicGachaByGachaType,
    gachaPlan: dicGachaPlan,
    gachaPlanQuality: dicGachaPlanQuality,
    gachaFloor: dicGachaFloor,
    gachaHope: new Array<{id: number, weight: number}>(),
    gachaTurntable: new Array<{quality: number, count: number, planId: number}>(),
    gachaPickHeroCnt: new Map<number, number>(),
    heroTransPiece: new Map<number, number>(),
    giftPackage: dicGiftPackage,
    giftPackagePlan: dicGiftPackagePlan,
    giftPackageFloor: dicGiftPackageFloor,
    comBtlLvRange: new Map<number, {min: number, max: number}>(),
    recruit: dicRecruit,
    rmb: dicRMB,
    activityType: dicActivityType,
    taskTypeDesc: dicTaskTypeDesc,
    taskDescByType: taskDescByType,
    serverNames: dicServerName,
    ap: dicAp,
    apMaxLevel: dicApMaxLevel,
    apBuy: dicApBuy,
    apMaxBuyTimes: dicApMaxBuyTimes,
    kingExpRaio: dicKingExpRatio,
    equipAttributeRatio: new Map<number, number>(),
    ceRatio: new Array<{type: number, val: number}>(),
    holiday: dicHoliday,
    expeditionSubAttr: dicExpeditionSubAttr,
    auctionPool: dicAuctionPool,
    auctionTime: new Map<number, { hour: number, minute: number, seconds: number}>(),
    whiteip: dicWhiteIp,
    guildWishReward: dicGuildWishReward,
    apiById: dicApiById,
    apiByUrl: dicApiByUrl,
    serverConst: dicServerConst,
    equipById: dicEquipById,
    equipIdByJobAndEPlace: dicEquipIdByJobClassAndEplace,
    jewel: dicJewel,
    stone: dicStone,
    equipStrengthenCost: dicEquipStrength,
    equipQuality: dicEquipQuality,
    equipQualityIdByEquipIdAndPoint: dicEquipQualityIdByEquipIdAndPoint,
    equipStar: dicEquipStar,
    equipStarIdByEquipId: dicEquipStarIdByEquipId,
    equipQualityExtra: dicEquipQualityExtra,
    equipSuit: dicEquipSuit,
    equipSuitByJobClass: dicEquipSuitByJobClass,
    jewelCondition: dicJewelCondition,
    blueprt: dicBlueprt,
    blueprtByLv: dicBlueprtByLv,
    heroIdByWar: dicHeroIdByWar,
    mainBox: dicMainStarBox,
    mainBoxByChapter: dicMainStarBoxByChapter,
    mainWarReward: dicMainWarRewardByChapter,
    heroTalent: dicHeroTalent, 
    initTalents: initTalents,
    talentPointOfJob: talentPointOfJob,
    equipStrengthAttr: dicEquipStrengthAttr,
    towerPvpSubAttr: dicTowerPvpSubAttr,
    sysOpenTime: dicSystemOpenTime,
    randomEffectPoolPlan: dicRandomEffectPoolPlan,
    ladderConsume: new Array<{id: number, count: number, times: number}>(),
    ladderMatch: dicLadderMatch,
    ladderDifficultRatio: dicLadderDifficultRatio,
    ladderRankReward: dicLadderRankReward,
    comBattleRewardTime: new Array<{from: string, to: string}>(),
    comBattleReward: dicComBattleReward,
    relationGoods: dicGeneralGoods,
    artifact: dicArtifact,
    artifactByGid: dicArtifactByGid,
    artifactByGidAndType: dicArtifactByGidAndType,
    artifactLvPlan: dicArtifactLvPlan,
    artifactQuality: dicArtifactQuality,
    artifactQualityById: dicArtifactQualityById,
    artifactQualityPlan: dicArtifactQualityPlan,
    artifactSeid: dicArtifactSeid,
    artifactByGroupAndQuality: dicArtifactsByGroup,
    gvgPeriod: dicGVGPeriod,
    gvgTech: dicGVGTech,
    gvgItem: dicGVGItem,
    gvgActive: new Map<number, number>(),
    gvgLeagueLv: dicGVGLeagueLv,
    gvgResource: dicGVGResourceBase,
    gvgResourceBaseByType: dicGVGResourceBaseByType,
    gvgResourceBaseByLv: dicGVGResourceBaseByLv,
    gvgFieldAddType: new Map<number, number>(),
    gvgPlayerFieldAddType: new Map<number, number>(),
    gvgContributeBox: dicGVGContributeBox,
    gvgArea: dicGVGArea,
    gvgCity: dicGVGCity,
    gvgCityAdd: dicGVGCityAdd,
    gvgTask: dicGVGTask,
    gvgTaskByType: dicGVGTaskByType,
    gvgVestigeByServerType: dicGVGVestigeByType,
    gvgVestigeCntByServerType: new Map<number, number>(), // 单服or跨服 => 遗迹数量
    gvgVestige: dicGVGVestige,
    gvgVestigeRange: dicGVGVestigeRange,
    gvgVestigeLeagueRank: dicGVGVestigeLeagueRank,
    gvgVestigePlayerRank: dicGVGVestigePlayerRank,
    gvgVestigeName: dicGVGVestigeName,
    gvgAreaPoint: dicGVGAreaPoint,
    gvgBattleRankReward: dicGVGBattleRankReward,
    gvgBattleDurabilityMinus: { win: 0, fail: 0 },
    gvgTeamDurability: new Map<number, number>(),
    gvgPointByAreaId: dicGVGPointsByAreaId,
    gvgReviveGold: new Map<number|'max', number>(),
};

// 在此提供一些原先在gamedata中提供的方法，以便更方便获取gameData数据

/**
 * 根据主公当前经验获得当前等级
 * @param exp 累积经验
 */
export function getLvByExp(exp: number) {
    let curLv = 0;
    let entries = gameData.kingexp.entries();
    for (let [lv, { sum }] of entries) {
        curLv = lv;
        if (exp < sum) break;
    }

    return curLv;
}

/**
 * 根据主公当前等级，获得累积经验，1=> 1级满经验
 * @param lv 等级
 */
export function getExpByLv(lv: number) {
    return gameData.kingexp.get(lv);
}

/**
 * 根据武将当前经验获得当前等级
 * @param exp 累积经验
 */
export function getHeroLvByExp(exp: number) {
    let curLv = 0;
    let entries = gameData.charexp.entries();
    for (let [lv, sum] of entries) {
        curLv = lv;
        if (exp < sum) break;
    }

    return curLv;
}

/**
 * 根据武将当前等级，获得累积经验，1=> 1级满经验
 * @param lv 
 */
export function getHeroExpByLv(lv: number) {
    return gameData.charexp.get(lv);
}


export function getConnectMaxLv(actorId: number, shipId: number) {
    return gameData.friendShipsMax.get(`${actorId}_${shipId}`)||0;
}

/**
 * 根据武将当前好感获得好感等级
 * @param exp 累积经验
 */
export function getConnectLvByExp(actorId: number, shipId: number, newExp: number) {
    let exps = gameData.friendShips.get(`${actorId}_${shipId}`)||[];
    exps.sort((a, b) => a.level - b.level);
    let newLv = 0;
    for(let { level, shipExp } of exps) {
        if(newExp >= shipExp) newLv = level;
    }
    return newLv
}

export function getBossHpByWarId(warId: number) {
    let bossHpSum = gameData.btlBossHpSum.get(warId) || 0;
    let bossHpArr = gameData.btlBossHp.get(warId) || [];
    if (!bossHpSum || !bossHpArr) {
        const warInfo = dicWarJson.get(warId);
        if (warInfo && warInfo.length) {
            warInfo.forEach(hero => {
                let { attribute, dataId, relation, actorId } = hero;
                if (relation === 2) {
                    let newAttr = new AttributeCal();
                    newAttr.setByWarJson(actorId, attribute, 1);
                    let attrJson = newAttr.getAttributes();

                    const hp = attrJson.hp || 0;
                    if (hp > 0) {
                        bossHpArr.push({ dataId, hp, actorId });
                        bossHpSum += hp;
                    }
                }
            })
            gameData.btlBossHp.set(warId, bossHpArr);
            gameData.btlBossHpSum.set(warId, bossHpSum);
        }
    }
    return { bossHpSum, bossHpArr };
}

export function getBossHpByBlueprtId(blueprtId: number) {
    let { dispatchJsonId } = getWarByBlueprtId(blueprtId);
    let bossHpInfo = getBossHpByWarId(dispatchJsonId);
    return bossHpInfo;
}

export function getWarByBlueprtId(blueprtId: number) {
    let dicBlueprt = getDicBlueprtById(blueprtId);
    return gameData.war.get(dicBlueprt.gkId);
}

export function getRewardByBlueprtId(blueprtId: number) {
    let { war_id } = getWarByBlueprtId(blueprtId);
    return gameData.comBattleReward.get(war_id);
}

function parseComBtlLvRange() {
    const lvRange = decodeArrayListStr(param.TREASURE.TREASURE_ASSIST_LIMITED);
    lvRange.forEach(range => {
        gameData.comBtlLvRange.set(parseInt(range[0]), { min: parseInt(range[1]), max: parseInt(range[2]) });
    });
}

export function comBtlRanges() {
    return Array.from(gameData.blueprtByLv.keys());
}


export function getHeroStarByQuality(classType: number, quality: number, star: number) {
    return gameData.heroStar.get(`${classType}_${quality}_${star}`);
}

export function getHeroWakeByQuality(classType: number, quality: number, star: number) {
    return gameData.heroWake.get(`${classType}_${quality}_${star}`);
}

export function getMaxGradeByjobClass(jobClass: number) {
    const job = gameData.jobClassMaxGrades.get(jobClass);
    return job?.jobid;
}

export function getJobByGradeAndClass(jobClass: number, grade: number) {
    return gameData.jobClassAndgrades.get(jobClass + '_' + grade);
}

export function getFriendShipByIdAndLv(actorId: number, shipId: number, level: number) {
    return gameData.friendShipsByLv.get(`${actorId}_${shipId}_${level}`);
}

export function getGoodById(gid: number) {
    return gameData.goods.get(gid);
}

export function randomGoodsByItid(itid: number) {
    let result: number[] = [];
    for(let [id, dicGoods] of gameData.goods) {
        if(dicGoods.randomShow == 1 && dicGoods.itid == itid) {
            result.push(id);
        }
    }
    return getRandSingleEelm(result)
}

export function getHeroJob(jobId: number) {
    const job = gameData.job.get(jobId);
    return job;
}

export function getTitle(titleLv: number) {
    const titleInfo = gameData.title.get(titleLv);
    return titleInfo;
}

export function getTeraph(id: number, grade: number) {
    const teraphInfo = gameData.teraphs.get(id + '_' + grade);
    return teraphInfo;
}

export function getSchoolRateByStar(star: number, colorStar: number, quality: number) {
    const schoolRate = gameData.schoolRate.get(`${star}_${colorStar}_${quality}`);
    return schoolRate;
}

export function getScollByStar(quality: number, star: number, curQuality: number, colorStar: number) {
    const heroScroll = gameData.heroScroll.get(`${quality}_${star}_${curQuality}_${colorStar}`);
    return heroScroll;
}

export function getPLvByScore(score: number) {
    let lv = 0;
    for (let { teamLv, topLineupMin, topLineupMax } of gameData.pvpTeamLevel) {
        if (score >= topLineupMin) lv = teamLv;
        if (score < topLineupMax) break;
    }
    return lv;
}

export function getPlvAndScore(scores: number[] = []) {
    if(scores.length <= 0) scores = [0];
    let maxScore = Math.max(...scores); // 等级：军功最高者的军功*6
    let score = scores.reduce((pre, cur) => pre + cur, 0);
    return { score, pLv: getPLvByScore(maxScore * param.PVP.PVP_LINEUP_HEROS)};
}

export function getPvpHeroRewardsByScore(score: number) {
    for (let item of gameData.pvpHeroRewards) {
        if ((item.max >= score || item.max == -1) && score >= item.min) {
            return item;
        }
    }
    return null
}


function getPvpRankRewardsBySeasonNum(seasonNum: number) {
    if(gameData.pvpRankRewards.has(seasonNum)) {
        return gameData.pvpRankRewards.get(seasonNum);
    } else {
        let result: DicRankRewads[] = [];
        for(let [_seasonNum, ranks] of gameData.pvpRankRewards) {
            result = ranks;
            if(_seasonNum >= seasonNum) break;
        }
        return result
    }
}


export function getPvpRankMaxRewardsBySeasonNum(seasonNum: number) {
    if(gameData.pvpRankMax.has(seasonNum)) {
        return gameData.pvpRankMax.get(seasonNum);
    } else {
        let result: DicRankRewads = undefined;
        for(let [_seasonNum, max] of gameData.pvpRankMax) {
            result = max;
            if(_seasonNum >= seasonNum) break;
        }
        return result
    }
}

export function getPvpRankRewardsByRank(seasonNum: number, rankLv: number) {
    if(rankLv == 0) return null
    let ranks = getPvpRankRewardsBySeasonNum(seasonNum)??[];

    for (let item of ranks) {
        if ((item.max >= rankLv || item.max == -1) && rankLv >= item.min) {
            return item;
        }
    }
    return getPvpRankMaxRewardsBySeasonNum(seasonNum);
}

function getPvpBoxKeysBySeasonNum(seasonNum: number) {
    if(gameData.pvpBoxesBySeasonNum.has(seasonNum)) {
        return gameData.pvpBoxesBySeasonNum.get(seasonNum);
    } else {
        let result = new Map<number, string>();
        for(let [_seasonNum, key] of gameData.pvpBoxesBySeasonNum) {
            result = key;
            if(_seasonNum >= seasonNum) break;
        }
        return result
    }
}

export function getPvpBoxBySeasonNumAndIndex(seasonNum: number, index: number) {
    let indexToKey = getPvpBoxKeysBySeasonNum(seasonNum);
    let key = indexToKey?.get(index);
    return key? gameData.pvpBoxs.get(key): null;
}

export function getPvpBoxsBySeasonNum(seasonNum: number) {
    let result: DicPvpBox[] = []
    let indexToKey = getPvpBoxKeysBySeasonNum(seasonNum);
    for(let [_, key] of indexToKey) {
        let pvpBox = gameData.pvpBoxs.get(key);
        if(pvpBox) result.push(pvpBox);
    }
    return result;
}

export function getStructureConsume(structureId: number, level: number) {
    return gameData.structureConsume.get(structureId).get(level);
}

export function hasStructureConsume(structureId: number, level: number) {
    return gameData.structureConsume.get(structureId).has(level);
}

export function getBossByLv(lv: number) {
    return gameData.bossBase.get(lv);
}

export function getArmyTrainJuDian(trainId: number) {
    return gameData.armyTrainJuDian.get(trainId);
}

export function getTrainSoloReward(id: number) {
    return gameData.trainSoloReward.get(id);
}

export function getTrainBaseByLv(lv: number) {
    return gameData.trainBase.get(lv);
}

export function getGuildActiveWeekReward(rank: number) {
    let result = gameData.guildActiveWeekReward.find(cur => {
        let { rankMax, rankMin } = cur;
        return rank >= rankMin && (rank <= rankMax || rankMax == -1);
    });
    let reward = new Array<RewardInter>();
    if (result) reward = result.reward;
    return reward;
}

export function getGuildActiveByIdAndType(id: number, type: number) {
    let dicWay = gameData.guildActiveWays.get(id);
    if (!dicWay) return 0;
    return dicWay.activePoint.get(type.toString());
}
export function getArmyDevelopConsumeById(id: number) {
    let result = gameData.armyDevelopConsume.get(id);
    return result;
}

export function getArmyDevelopConsume() {
    return gameData.armyDevelopConsume;
}

export function getArmyBossRank() {
    return gameData.armyBossRank;
}

export function getArmyDonateBaseByLv(lv: number) {
    return gameData.donateBase.get(lv);
}

export function getArmyDonateBoxBaseById(id: number) {
    return gameData.armyDonateBox.get(id);
}
export function getFriendLvByExp(exp: number) {
    let resultLv = 1;
    for (let [lv, { sum }] of gameData.roleFriendLv.entries()) {
        resultLv = lv;
        if (exp < sum) break;
    }
    return resultLv;
}

/**
 * 根据主公当前经验获得当前等级
 * @param exp 累积经验
 */
export function getDicFriendByLv(lv: number) {
    let dicFriend: DicRoleFriend;
    let entries = gameData.roleFriend.entries();
    for (let [dicLv, dic] of entries) {
        if (lv >= dicLv || !dicFriend) dicFriend = dic;
    }

    return dicFriend;
}


/**
 * @description 获取今天开启的活动的配置
 */
export function getTodayGuildActivity() {
    let today = getCurDay();
    let dic: DicGuildActivity;
    for (let [_id, dicGuildActivity] of gameData.guildActivity) {
        if (dicGuildActivity.openDay.includes(today)) {
            dic = dicGuildActivity;
            break;
        }
    }
    return dic;
}

/**
 * 根据军团活动排名获得功勋奖励
 * @param type 城池类型
 * @param guildRank 军团排名
 * @param rank 成员在军团内部排名
 */
export function getCityActivityRewards(type: number, guildRank: number, rank: number) {
    let ranksReward = gameData.cityActivityReward.get(type) || [];
    let dic = ranksReward.find(cur => {
        return (guildRank >= cur.guildRankMin && (guildRank <= cur.guildRankMax || cur.guildRankMax == 0)) && (rank >= cur.min && (rank <= cur.max || cur.max == 0));
    });
    return dic ? dic.honour : 0;
}

function decodeRaceActivityEncounter() {
    let str = GUILDACTIVITY.RACEACTIVITY_ENCOUNTER;
    let map = decodeIdCntArrayStr(str, 1);
    let newMap = new Map<number, number>();
    let eventNum = 0;
    for (let [key, value] of map) {
        if (value == RACE_EVENT_TYPE.EVENT) eventNum++;
        newMap.set(parseInt(key), value);
    }
    gameData.raceActivityEncounter = { events: newMap, eventNum };
}

function decodeRaceNormalItems() {
    let str = GUILDACTIVITY.RACEACTIVITY_NORMAL_ITEMS;

    let result = new Array<{ id: number, total: number, max: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [id, total, max] of decodeArr) {
        if (isNaN(parseInt(id)) || isNaN(parseInt(total)) || isNaN(parseInt(max))) {
            throw new Error('data table format wrong');
        }
        result.push({ id: parseInt(id), total: parseInt(total), max: parseInt(max) });
    }
    gameData.raceNormalItems = result;
}

function decodeRaceEventItems() {
    let str = GUILDACTIVITY.RACEACTIVITY_EVENT_ITEMS || "";
    gameData.raceEventItems = parseGoodStr(str);
}

export function getRaceEventItems() {
    let items = new Map<number, { total: number, max: number }>();
    for(let {id, total, max} of gameData.raceNormalItems) {
        items.set(id, { total, max });
    }
    return items;
}

// export function getRaceEventItems(members: WoodenHorseMember[], items: { id: number, total: number, max: number }[]) {
//     let result = new Array<RewardInter>();
//     for (let { id, min, max } of items) {
//         let count = getRandValueByMinMax(min, max, 0);
//         result.push({ id, count });
//     }
//     return result;
// }

// 根据保底类型获得保底数量
export function getDicGachaFloor(id: number) {
    let map = decodeIdCntArrayStr(RECRUIT.RECRUIT_MUST, 1);
    return map.get(id.toString())
}


export function getRandExpedition(cnt = 1) {
    let arr: DicExpedition[] = [];
    for (let [_id, dicExpedition] of gameData.expedition) {
        arr.push(dicExpedition);
    }
    return getRandEelm(arr, cnt);
}

// 抽卡心愿单概率
function getGachaHopePercent() {
    let arr = decodeArrayListStr(RECRUIT.RECRUIT_WISH_LIST);
    gameData.gachaHope = arr.map(cur => {
        return { id: parseInt(cur[0]), weight: parseInt(cur[1]) }
    });
}

// 抽卡转盘概率
function getGachaTurntablePercent() {
    let arr = decodeArrayListStr(RECRUIT.RECRUIT_BONUS_HERO_QUANTITY);
    gameData.gachaTurntable = arr.map(cur => {
        return { quality: parseInt(cur[0]), count: parseInt(cur[1]), planId: parseInt(cur[2]) }
    });
}

function getGachaPickHeroCnt() {
    let arr = decodeArrayListStr(RECRUIT.RECRUIT_GET_HERO_HIGH_RECRUIT);
    arr.forEach(cur => {
        gameData.gachaPickHeroCnt.set(parseInt(cur[0]), parseInt(cur[1]));
    });
}

function getHeroTransPiece() {
    let map = decodeIdCntArrayStr(RECRUIT.RECRUIT_CHANGE_SHARD, 1);
    let newMap = new Map<number, number>();
    for (let [id, count] of map) {
        newMap.set(parseInt(id), count);
    }
    gameData.heroTransPiece = newMap
}

function getCeRatio() {
    let arr = decodeArrayListStr(param.ATTRIBUTE.ATTRIBUTE_POWER);
    gameData.ceRatio = arr.map(cur => {
        return { type: parseInt(cur[0]), val: parseFloat(cur[1]) }
    });
}

// 根据服务器id获得当前大区名
export function getServerName(id: number) {
    let name = gameData.serverNames.get(id);
    if(!name) {
        let maxId = 0;
        gameData.serverNames.forEach((sname, id) => {
            if(id > maxId) {
                maxId = id;
                name = sname;
            }
        })
    }
    return name;
}

export function getDicApByLv(level: number) {
    if(level > gameData.apMaxLevel.max) {
        return gameData.ap.get(gameData.apMaxLevel.max);
    } else {
        return gameData.ap.get(level);
    }
}

export function getWishPoolReward(id: number) {
    let dicGoods = gameData.goods.get(id);
    if(!dicGoods) return false;
    return gameData.guildWishReward.get(`${dicGoods.itid}_${dicGoods.quality}`);
}

/**
 * 根据TrainJuDian的id和武将id，获得信息（包括多个难度）
 * @param trainId 据点id
 * @param heroId 武将id
 */
export function getGuildTrainGkInfo(trainId: number, heroId: number) {
    return gameData.guildTrainInfo.get(`${trainId}_${heroId}`);
}

export function getPvpDifficultByScore(score: number) {
    for(let obj of gameData.pvpDifficultRatio) {
        if(obj.teamLineupMin <= score && (obj.teamLineupMax >= score || obj.teamLineupMax == -1)) {
            return obj;
        }
    }
    return getMaxPvpDifficultRatio();
}

function getMaxPvpDifficultRatio() {
    if(gameData.pvpDifficultRatio.length <= 0) return null
    return gameData.pvpDifficultRatio.reduce((pre, cur) => {
        return cur.teamLineupMax > pre.teamLineupMax ? cur: pre
    }, gameData.pvpDifficultRatio[0])
}


function loadEquipAttributeRatio() {
    let arr = decodeArrayListStr(param.ATTRIBUTE.ATTRIBUTE_EQUIP_RATIO);
    for(let [id, ratio] of arr) {
        gameData.equipAttributeRatio.set(parseInt(id), parseInt(ratio));
    }
}

function loadAuctionTime() {
    gameData.auctionTime.set(AUCTION_TIME.GUILD_PREVIEW, splitTime(param.AUCTION.GUILD_AUCTION_PREVIEW_TIME));
    gameData.auctionTime.set(AUCTION_TIME.GUILD_OPEN, splitTime(param.AUCTION.GUILD_AUCTION_OPEN_TIME));
    gameData.auctionTime.set(AUCTION_TIME.GUILD_CLOSE, splitTime(param.AUCTION.GUILD_AUCTION_CLOSE_TIME));
    gameData.auctionTime.set(AUCTION_TIME.WORLD_PREVIEW, splitTime(param.AUCTION.WORLD_AUCTION_PREVIEW_TIME));
    gameData.auctionTime.set(AUCTION_TIME.WORLD_OPEN, splitTime(param.AUCTION.WORLD_AUCTION_OPEN_TIME));
    gameData.auctionTime.set(AUCTION_TIME.WORLD_CLOSE, splitTime(param.AUCTION.WORLD_AUCTION_CLOSE_TIME));
}

function splitTime(str: string) {
    let arr = str.split(':');
    return { hour: parseInt(arr[0]), minute: parseInt(arr[1]), seconds: parseInt(arr[2]) }
}

export function getEquipByJobClassAndEPlace(jobClass: number, ePlaceId: number) {
    let equipId = gameData.equipIdByJobAndEPlace.get(`${jobClass}_${ePlaceId}`);
    return gameData.equipById.get(equipId);
}

export function getEquipQualityIdByEquipIdAndPoint(equipId: number, quality: number, point: number) {
    let equipQualityId = gameData.equipQualityIdByEquipIdAndPoint.get(`${equipId}_${quality}_${point}`);
    return equipQualityId?gameData.equipQuality.get(equipQualityId): null;
}

export function getNextEquipQuality(equipId: number, quality: number, point: number) {
    let equipQuality = getEquipQualityIdByEquipIdAndPoint(equipId, quality, point);
    if(equipQuality) {
        let nextId = equipQuality.id + 1;
        let nextEquipQuality = gameData.equipQuality.get(nextId);
        if(nextEquipQuality && nextEquipQuality.equipId == equipQuality.equipId) {
            return nextEquipQuality
        }
    }
    return null
}

export function getEquipStarIdByEquipId(equipId: number, star: number) {
    let equipStarId = gameData.equipStarIdByEquipId.get(`${equipId}_${star}`);
    return equipStarId?gameData.equipStar.get(equipStarId): null;
}

export function getNextEquipStar(equipId: number, star: number) {
    let equipStar = getEquipStarIdByEquipId(equipId, star);
    if(equipStar) {
        let nextId = equipStar.id + 1;
        let nextEquipStar = gameData.equipStar.get(nextId);
        if(nextEquipStar && nextEquipStar.equipId == equipStar.equipId) {
            return nextEquipStar;
        }
    }
    return null;
}

export function getPreEquipStar(equipId: number, star: number) {
    let equipStar = getEquipStarIdByEquipId(equipId, star);
    if(equipStar) {
        let nextId = equipStar.id - 1;
        let nextEquipStar = gameData.equipStar.get(nextId);
        if(nextEquipStar && nextEquipStar.equipId == equipStar.equipId) {
            return nextEquipStar;
        }
    }
    return null;
}

export function getEquipStarAttrByStage(equipId: number, star: number, starStage: number) {
    if(starStage == 0) {
        let preEquipStar = getPreEquipStar(equipId, star);
        if(!preEquipStar || preEquipStar.equipId != equipId) {
            return { mainAttr: [], subAttr: [] };
        } else {
            return {
                mainAttr: preEquipStar.mainAttr.get(preEquipStar.count),
                subAttr: preEquipStar.subAttr,
            }
        }
    } else {
        let preEquipStar = getPreEquipStar(equipId, star);
        let equipStar = getEquipStarIdByEquipId(equipId, star);
        return {
            mainAttr: equipStar.mainAttr.get(starStage),
            subAttr: preEquipStar?.subAttr||[],
        }
    }
}

export function getEquipSuitByHero(skinId: number) {
    let dicHero = gameData.hero.get(skinId);
    let equipSuitId = gameData.equipSuitByJobClass.get(dicHero.jobClass);
    return gameData.equipSuit.get(equipSuitId);
}

export function getJewelConditionByLvAndSeId(lv: number, randSeId: number) {
    return gameData.jewelCondition.get(`${lv}_${randSeId}`);
}

export function getDicBlueprtById(id: number) {
    let jewel = gameData.blueprt.get(id);
    return gameData.jewel.get(jewel);
}

export function getRandEffectByGroupAndLevel(group: number, level: number) {
    let id = gameData.randomEffectPoolByGroupAndLv.get(`${group}_${level}`);
    return gameData.randomEffectPool.get(id);
}

// 根据皮肤获得他的初始天赋id
export function getHeroInitTalent(skinId: number) {
    let dicHero = gameData.hero.get(skinId);
    if(!dicHero) return [];
    let ids = gameData.initTalents.get(dicHero.talentId)||[];
    return ids.map(id => (new Talent(id)));
}

export function getEquipStrenthenAttr(equipId: number, lv: number) {
    let result = gameData.equipStrengthAttr.get(`${equipId}_${lv}`);
    return result
}

export function decodeLadderBuyCost() {
    gameData.ladderConsume = [];
    let str = param.LADDER.LADDER_CHALLENGE_BUY_TIMES_COST;
    let arrs = decodeArrayListStr(str);
    let sumTimes = 0;
    for (let [ id, count, times] of arrs) {
        sumTimes += parseInt(times);
        gameData.ladderConsume.push({ id: parseInt(id), count: parseInt(count), times: sumTimes });
    }
}

export function getDicLadderMatchByMyRank(myRank: number) {
    for(let dic of gameData.ladderMatch) {
        let { rankMin, rankMax } = dic;
        if(rankMin < myRank && (rankMax >= myRank || rankMax == -1) ) {
            return dic;
        }
    }
    return null
}

export function getLadderRankReward(myRank: number) {
    for(let dic of gameData.ladderRankReward) {
        let { rankMin, rankMax } = dic;
        if(rankMin < myRank && (rankMax >= myRank || rankMax == -1) ) {
            return dic;
        }
    }
    return null
}

export function hasShopType(shop: number, type: number) {
    return gameData.shopType.has(`${shop}_${type}`);
}

export function getShopType(shop: number, type: number) {
    let key = `${shop}_${type}`;
    return gameData.shopType.get(key)||null;
}

export function getDefArtifactByGid(gid: number): DicArtifact {
    let artifactId = gameData.artifactByGid.get(gid);
    return gameData.artifact.get(artifactId);
}

export function getDicArtifactQualityByStage(quality: number, qualityStage: number): DicArtifactQuality {
    let uniqId = gameData.artifactQuality.get(`${quality}_${qualityStage}`);
    return gameData.artifactQualityById.get(uniqId);
}

export function getNextArtifactQuality(quality: number, qualityStage: number): DicArtifactQuality {
    let dicArtifactQuality = getDicArtifactQualityByStage(quality, qualityStage);
    if(!dicArtifactQuality) return null;
    return gameData.artifactQualityById.get(dicArtifactQuality.nextId);
}

export function getNextArtifact(artifactId: number): (DicArtifact&DicArtifactQuality) {
    let dicArtifact = gameData.artifact.get(artifactId);
    if(!dicArtifact) return null;
    let dicNextArtifactQuality = getNextArtifactQuality(dicArtifact.quality, dicArtifact.qualityStage);
    if(!dicNextArtifactQuality) return null;
    let dicNextArtifact = getArtifactByGroupAndQuality(dicArtifact.group, dicArtifact.type, dicNextArtifactQuality.quality, dicNextArtifactQuality.qualityStage);    
    if(!dicNextArtifact) return null;
    return {...dicNextArtifact, ...dicNextArtifactQuality}
}

export function getArtifactStageZero(artifactId: number): (DicArtifact&DicArtifactQuality) {
    let dicArtifact = getArtifactWithQuality(artifactId);
    if(!dicArtifact) return null;
    let dicZeroArtifact = gameData.artifactByGroupAndQuality.get(`${dicArtifact.group}_${dicArtifact.type}_${dicArtifact.quality}_${0}`);
    if(!dicZeroArtifact) return null;
    let dicZeroArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
    if(!dicZeroArtifactQuality) return null;
    return {...dicZeroArtifact, ...dicZeroArtifactQuality}
}

export function getArtifactByGroupAndQuality(group: string, type: number, quality: number, qualityStage: number): DicArtifact {
    return gameData.artifactByGroupAndQuality.get(`${group}_${type}_${quality}_${qualityStage}`);
}

export function getDicArtifactLvByPlanId(planId: number, lv: number): DicArtifactLvPlan {
    let map = gameData.artifactLvPlan.get(planId);
    return map?.get(lv);
}

export function getArtifactByGidAndType(goodId: number, type: number): DicArtifact {
    let artifactId = gameData.artifactByGidAndType.get(`${goodId}_${type}`);
    return gameData.artifact.get(artifactId);
}

export function getArtifactWithQuality(artifactId: number): (DicArtifact&DicArtifactQuality) {
    let dicArtifact = gameData.artifact.get(artifactId);
    if(!dicArtifact) return null;
    let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage);
    if(!dicArtifactQuality) return null;
    return {...dicArtifact, ...dicArtifactQuality}
}

function parseGVGActive() {
    let arr = decodeArrayListStr(param.GVG.GVG_LEAGUE_ACTIVE_POINT);
    for(let [id, active] of arr) {
        gameData.gvgActive.set(parseInt(id), parseInt(active));
    }
}

export function calLeagueLv(resources: { food: number, mineral: number, wood: number }) {
    let lv = 1;
    for(let [curLv, dic] of gameData.gvgLeagueLv) {
        lv = curLv;
        if(resources.food < dic.food || resources.mineral < dic.mineral || resources.wood < dic.wood) {
            break;
        }
    }
    return lv
}

export function getGVGResourceBasesByType(type: number) {
    const ids = gameData.gvgResourceBaseByType.get(type)||[];
    const result: DicGVGResourceBase[] = [];
    for(let id of ids) {
        let dicResource = gameData.gvgResource.get(id);
        if(dicResource) result.push(dicResource);
    }
    return result;
}

export function getGVGResourceBaseByTypeAndLv(type: number, lv: number) {
    let id = gameData.gvgResourceBaseByLv.get(`${type}_${lv}`);
    return gameData.gvgResource.get(id);
}

// 获取农庄小游戏最多能有多少特殊加成田
export function getFieldMaxAddType(farmId: number) {
    let add = new Map<number, number>();
    let dicResource = gameData.gvgResource.get(farmId);
    if(!dicResource) return add;
    for(let [type, ratio] of gameData.gvgFieldAddType) {
        add.set(type, Math.floor(dicResource.sum * ratio / 100))
    }
    return add;
}

function parseGVGFieldAdd() {
    let arr = decodeArrayListStr(param.GVG.GVG_FIELD_TYPE_RATIO);
    for(let [type, ratio] of arr) {
        gameData.gvgFieldAddType.set(parseInt(type), parseFloat(ratio));
    }
    let arr2 = decodeArrayListStr(param.GVG.GVG_SP_FIELD_RATIO);
    for(let [type, ratio] of arr2) {
        gameData.gvgPlayerFieldAddType.set(parseInt(type), parseFloat(ratio));
    }
}

export function getGVGTasksByType(taskType: number) {
    let taskIds = gameData.gvgTaskByType.get(taskType)||[];
    return taskIds.map(taskId => {
        let dic = gameData.gvgTask.get(taskId);
        return dic
    });
}

function parseGVGVestigeCnt() {
    let arr = decodeArrayListStr(param.GVG.GVG_SERVICETYPE_VESTIGE);
    for(let [type, cnt] of arr) {
        gameData.gvgVestigeCntByServerType.set(parseInt(type), parseInt(cnt));
    }
}

export function getGVGVestigeRange(myRank: number) {
    let lastRank: DicGVGVestigeRange;
    for(let dic of gameData.gvgVestigeRange) {
        lastRank = dic;
        let { rankMin, rankMax } = dic;
        if((rankMin < myRank && (rankMax >= myRank || rankMax == -1))) {
            return dic;
        }
    }
    return lastRank
}

export function getGVGVestigeLeagueRank(myLeagueRank: number) {
    let lastRank: DicGVGVestigeLeagueRank;
    for(let dic of gameData.gvgVestigeLeagueRank) {
        lastRank = dic;
        let { rankMin, rankMax } = dic;
        if(rankMin <= myLeagueRank && (rankMax >= myLeagueRank || rankMax == 0)) {
            return dic;
        }
    }
    return lastRank
}

export function getGVGVestigePlayerRank(myRank: number) {
    let lastRank: DicGVGVestigePlayerRank;
    for(let dic of gameData.gvgVestigePlayerRank) {
        lastRank = dic;
        let { rankMin, rankMax } = dic;
        if(rankMin <= myRank && (rankMax >= myRank || rankMax == 0)) {
            return dic;
        }
    }
    return lastRank
}

export function getGVGBattleRankReward(type: number, rank: number) {
    let arr = gameData.gvgBattleRankReward.get(type)||[];
    let lastRank: DicGVGBattleRankReward;
    for(let dic of arr) {
        lastRank = dic;
        let { min, max } = dic;
        if(min <= rank && (max >= rank || max == -1)) {
            return dic;
        }
    }
    return lastRank
}

function parseGVGDurabilityMinus() {
    const range = parseNumberList(param.GVG.GVG_DEFAULT_DURABILITY_MINUS);
    gameData.gvgBattleDurabilityMinus.win = range[0];
    gameData.gvgBattleDurabilityMinus.fail = range[1];
}

function parseGVGTeamDurability() {
    let arr = decodeArrayListStr(param.GVG.GVG_TEAM_NUMBER);
    for(let [index, _lv, durability] of arr) {
        gameData.gvgTeamDurability.set(parseInt(index), parseInt(durability));
    }

}

function parseGVGReviveCoin() {
    let arr = decodeArrayListStr(param.GVG.GVG_REVIVE_GOLD);
    for(let [_cnt, _gold] of arr) {
        let cnt = parseInt(_cnt);
        let gold = parseInt(_gold);
        gameData.gvgReviveGold.set(cnt, gold);
        gameData.gvgReviveGold.set('max', gold);
    }
}

export function getReviveGold(cnt: number) {
    if(gameData.gvgReviveGold.has(cnt)) return gameData.gvgReviveGold.get(cnt)||0;
    return gameData.gvgReviveGold.get('max')||0;
}

// 初始加载
function initDatas() {
    parseDicParam();
    loadDatas();
}

// 解析一部分dicParam的数据
function parseDicParam() {
    decodeRaceActivityEncounter();
    decodeRaceNormalItems();
    decodeRaceEventItems();
    getGachaHopePercent();
    getGachaTurntablePercent();
    getGachaPickHeroCnt();
    getHeroTransPiece();
    parseComBtlLvRange();
    getCeRatio();
    loadAuctionTime();
    decodeLadderBuyCost();
    parseComBattleRewardTime();
    parseGVGActive();
    parseGVGFieldAdd();
    parseGVGVestigeCnt();
    parseGVGDurabilityMinus();
    parseGVGTeamDurability();
    parseGVGReviveCoin();
}

/**
 * 处理任务的group属性
 * group为如果两个任务，除了condition以外的其他所有taskParam都是一样的，他们的group相同
 */
function treatTaskGroup() {
    // console.log('****** treatTaskGroup')
    let taskType2Desc = new Map<number, DicTaskType>();
    for(let obj of gameData.taskTypeDesc) {
        taskType2Desc.set(obj.id, obj);
    }
    let taskByGroup = new Map<number, { params: number[], ids: string[] }[]>(); // taskType => obj
    for(let [taskType, tasks] of gameData.taskType) {
        for(let obj of tasks) {
            let dicTaskType = taskType2Desc.get(taskType);
            let index = dicTaskType.param.split('&').indexOf(dicTaskType.condition);
            let params = obj.taskParam.filter((_, i) => index != i);
            // console.log('params： ', obj.id, obj.type, obj.taskType, obj.taskParam, obj.condition, params);

            if(!taskByGroup.has(taskType)) {
                taskByGroup.set(taskType, [{ params, ids: [`${obj.type}_${obj.id}`]}]);
            } else {
                let arr = taskByGroup.get(taskType)||[];
                let hasGroup = arr.find(cur => {
                    return _.isEqual(cur.params, params);
                });
                if(hasGroup) {
                    hasGroup.ids.push(`${obj.type}_${obj.id}`);
                } else {
                    arr.push({ params, ids: [`${obj.type}_${obj.id}`] });
                }
                taskByGroup.set(taskType, arr);
            }
        }
    }
    // console.log('****** taskByGroup', JSON.stringify([...taskByGroup]))

    for(let [taskType, arr] of taskByGroup) {
        let tasks = gameData.taskType.get(taskType);
        for(let i = 0; i < arr.length; i++) {
            let { params, ids } = arr[i];
            for(let id of ids) {
                let task = tasks.find(cur => `${cur.type}_${cur.id}` == id);
                task.group = params.join('&');
                gameData.tasks.get(task.type).get(task.id).group = params.join('&');
            }
        }
        gameData.taskType.set(taskType, tasks);
    }
}

function parseComBattleRewardTime() {
    let str = param.TREASURE.TIME_REWARD;
    if (!str) return
    let result: { from: string, to: string }[] = [];
    let decodeArr = decodeArrayListStr(str);
    for (let [from, to] of decodeArr) {
        result.push({ from, to });
    }
    gameData.comBattleRewardTime = result;
}

// 加载json
function loadDatas() {
    loadHero();
    loadGoods();
    loadDaily();
    loadEvent();
    loadExpedition();
    loadExpeditionPoint();
    loadJob();
    loadKingExp();
    loadCharExp();
    loadQuestion();
    loadSe();
    loadTower();
    loadTowerTask();
    loadTowerGift();
    loadWar();
    loadWarJson();
    loadFashions();
    loadFriendShip();
    loadHeroQualityUp();
    loadHeroStar();
    loadHeroWake();
    loadRandomEffectPool();
    loadTitle();
    loadTeraph();
    loadSchool();
    loadSchoolRate();
    loadHeroScroll();
    loadPvpOpponent();
    loadPvpTeamLevel();
    loadPvpRefreshConsume();
    loadPvpHeroReward();
    loadPvpRankReward();
    loadPvpBox();
    loadGuildAuth();
    loadStructure();
    loadGuildActiveDayReward();
    loadGuildActiveWeekReward();
    loadGuildActiveWays();
    loadGuildPosition();
    loadMail();
    loadArmyTrainJuDian();
    loadTrainSoloReward();
    loadArmyDevelopConsume();
    loadArmyBossRank();
    loadArmyDonate();
    loadRoleFriend();
    loadRoleFriendLv();
    loadGuildActivity();
    loadGateActivityPoint();
    loadGuildAuction();
    loadCityActivity();
    loadChatAccuse();
    loadCityActivityReward();
    loadRaceActivity();
    loadShop();
    loadShopType();
    loadRank();
    loadRankReward();
    loadTask();
    loadMainTaskStage();
    loadTaskBox();
    loadGacha();
    loadGachaPlan();
    loadGachaFloor();
    loadGiftPackage();
    loadGiftPackagePlan();
    loadGiftPackageFloor();
    loadRecruit();
    loadRMB();
    loadActivityType();
    loadTaskType();
    loadServerName();
    loadAp();
    loadApBuy();
    loadKingExpRatio();
    loadEquipAttributeRatio();
    loadHoliday();
    loadExpeditionSubAttr();
    loadAuctionReward();
    loadGuildTrainInfo();
    loadPvpDifficultRatio();
    loadWhiteIp();
    treatTaskGroup();
    loadGuildWishReward();
    loadApi();
    loadServerConst();
    loadEquip();
    loadEquipStrength();
    loadEquipQuality();
    loadEquipStar();
    loadEquipSuit();
    loadEquipQualityExtra();
    loadJewel();
    loadStone();
    loadJewelCondition();
    loadMainStarBox();
    loadHeroTalent();
    loadEquipStrengthAttr();
    loadTowerPvpSubAttr();
    loadSystemOpenTime();
    loadRandomEffectPoolPlan();
    loadMainWarReward();
    loadLadderMatch();
    loadLadderDifficultRatio();
    loadLadderRankReward();
    loadGeneralGoods();
    loadArtifact();
    loadArtifactLvPlan();
    loadArtifactQuality();
    loadArtifactQualityPlan();
    loadArtifactSeid();
    loadGVGPeriod();
    loadGVGTech();
    loadGVGItem();
    loadGVGLeagueLv();
    loadGVGResourceBase();
    loadGVGContributeBox();
    loadGVGArea();
    loadGVGCityAdd();
    loadGVGTask();
    loadGVGVestigeType();
    loadGVGVestige();
    loadGVGVestigeRange();
    loadGVGVestigeLeagueRank();
    loadGVGVestigePlayerRank();
    loadGVGAreaPoint();
    loadGVGBattleRankReward();
}

// 重载dicParam
export function reloadDicParam() {
    let file = readTsFile('dicParam');
    if(file) {
        let lines = file.split('\n');
        let outer = '';
        lines.forEach(line => {
            if(line.replace(/ /g, '')) {
                if(line.indexOf('export') != -1) {
                    outer = line.split(' ')[2];
                    // console.log(outer)
                }
                if(line.indexOf('export') == -1 && line.indexOf('}') == -1) {
                    let s = line.split(', //')[0];
                    let key = s.slice(0, s.indexOf(':')).replace(/ /g, '');
                    let value = s.slice(s.indexOf(':' + 1)).replace(/ /g, '');
                    let isString = value.match(/(?<=')[^']*/);
                    if(!param[outer]) {
                        param[outer] = {}
                    }
                    if(isString) {
                        param[outer][key] = isString[0];
                    } else {
                        param[outer][key] = parseFloat(value);
                    }
                }
            }
        });
        parseDicParam();
    }

}

// 后台调用重载资源
export function reloadResources() {
    loadDatas();
    reloadDicParam();
}

initDatas();
