548 lines
26 KiB
TypeScript
548 lines
26 KiB
TypeScript
// 征战中原相关
|
||
|
||
import moment = require("moment");
|
||
import { GVG_PERIOD, GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, VESTIGE_OPP_STATUS, VESTIGE_STATUS } from "../../consts";
|
||
import { ArtifactModel } from "../../db/Artifact";
|
||
import { GVGConfigModel } from "../../db/GVGConfig";
|
||
import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague";
|
||
import { GVGUserDataModel } from "../../db/GVGUserData";
|
||
import { GVGVestigeModel } from "../../db/GVGVestige";
|
||
import { GVGVestigeLeagueRankModel, GVGVestigeLeagueRankType } from "../../db/GVGVestigeLeagueRank";
|
||
import { GVGVestigeLockModel } from "../../db/GVGVestigeLock";
|
||
import { GVGVestigeRankModel, GVGVestigeRankType, GVGVestigeRankUpdate } from "../../db/GVGVestigeRank";
|
||
import { GVGVestigeRecModel, GVGVestigeRecType, GVGVestigeRecUpdate } from "../../db/GVGVestigeRec";
|
||
import { GVGVestigeSumRankModel, GVGVestigeSumRankType } from "../../db/GVGVestigeSumRank";
|
||
import { HeroModel, HeroType } from "../../db/Hero";
|
||
import { RoleModel } from "../../db/Role";
|
||
import { OppDetailData, OppPlayerHeroInfo, OppPlayerInfo } from "../../domain/gvgField/gvgDb";
|
||
import { GVGVestigeOppPlayer } from "../../domain/gvgField/returnData";
|
||
import { KeyNameParam, LeagueRankInfo, myIdInter, RoleRankInfo } from "../../domain/rank";
|
||
import { gameData, getGVGVestigeLeagueRank, getGVGVestigePlayerRank, getGVGVestigeRange } from "../../pubUtils/data";
|
||
import { GVG } from "../../pubUtils/dicParam";
|
||
import { RewardInter } from "../../pubUtils/interface";
|
||
import { getTimeFun, nowSeconds } from "../../pubUtils/timeUtil";
|
||
import { getRandEelm } from "../../pubUtils/util";
|
||
import { getNumberArr, uniqueArr } from "../ladderService";
|
||
import { sendMailByContent } from "../mailService";
|
||
import { getHeroesAttributes } from "../playerCeService";
|
||
import { sendMessageToUserWithSuc } from "../pushService";
|
||
import { Rank } from "../rankService";
|
||
import { findKeys, getAllServerName, redisClient } from "../redisService";
|
||
import { isDevelopEnv } from "../utilService";
|
||
import { addGVGReward, combinePushItem } from "./gvgItemService";
|
||
import { calFighterContribute } from "./gvgPrepareService";
|
||
import { addVestigeLeagueRankRec, addVestigeRankMessage } from "./gvgRecService";
|
||
import { getGroupKey, getGVGServerType, getPeriodByTime } from "./gvgService";
|
||
import { Combo } from "../../domain/battleField/pvp";
|
||
import { getRemoteRplPrefix } from "../../pubUtils/battleUtils";
|
||
import { pinus } from "pinus";
|
||
import { pushIconShow } from "../connectorService";
|
||
|
||
let gvgFightTime = undefined;
|
||
|
||
// !!注意,这个函数会改动内存,线上不应该使用
|
||
export function setPeriodTime(startFightTime: number, endFightTime: number) {
|
||
gvgFightTime = { startFightTime, endFightTime }
|
||
}
|
||
|
||
export function resetPeriodTime() {
|
||
gvgFightTime = undefined;
|
||
}
|
||
|
||
// 备战期的遗迹和激战期的开始结束战斗时间
|
||
export function getFightTimeByPeriod(period: GVG_PERIOD, time?: number) {
|
||
let dicPeriod = gameData.gvgPeriod.get(period);
|
||
if(!dicPeriod) return { startFightTime: 0, endFightTime: 0 };
|
||
|
||
if(isDevelopEnv() && gvgFightTime) {
|
||
return gvgFightTime;
|
||
}
|
||
|
||
return {
|
||
startFightTime: <number>getTimeFun(time).getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond),
|
||
endFightTime: <number>getTimeFun(time).getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond),
|
||
}
|
||
}
|
||
|
||
export function checkFightTime() {
|
||
let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.PREPARE);
|
||
let now = nowSeconds();
|
||
return startFightTime <= now && endFightTime >= now;
|
||
}
|
||
|
||
// 征战中原每天随机的遗迹点
|
||
export async function getVestiges(serverId: number) {
|
||
let groupKey = await getGroupKey(serverId);
|
||
let serverType = await getGVGServerType(serverId);
|
||
let vestige = await GVGVestigeModel.getVestige(groupKey);
|
||
if(!vestige) {
|
||
let dicGVGVestige = gameData.gvgVestigeByServerType.get(serverType)||[];
|
||
let cnt = gameData.gvgVestigeCntByServerType.get(serverType)||0;
|
||
let randResult = getRandEelm(dicGVGVestige, cnt);
|
||
vestige = await GVGVestigeModel.initTodayVestige(groupKey, randResult);
|
||
}
|
||
return vestige.vestiges||[];
|
||
}
|
||
|
||
export async function getMyVestiges(serverId: number, roleId: string) {
|
||
let vestiges = await getVestiges(serverId);
|
||
let myRanks = await GVGVestigeRankModel.findAllByRole(roleId);
|
||
let result: { vestigeId: number, position: string, myRank: number }[] = [];
|
||
for(let vestige of vestiges) {
|
||
let myRank = myRanks.find(cur => cur.vestigeId == vestige.vestigeId);
|
||
result.push({ ...vestige, myRank: myRank?.rank||0 });
|
||
}
|
||
return result;
|
||
}
|
||
|
||
export async function checkVestige(serverId: number, vestigeId: number) {
|
||
let vestiges = await getVestiges(serverId);
|
||
return !!vestiges.find(cur => cur.vestigeId == vestigeId);
|
||
}
|
||
|
||
// 根据自己排名随机出对手排名
|
||
export function refreshVestigeOppRanks(rank: number) {
|
||
let dicRange = getGVGVestigeRange(rank);
|
||
if(!dicRange) return [];
|
||
|
||
let { rangeBeforeFrom, rangeBeforeTo, rangeBeforeNum, rangeAfterFrom, rangeAfterTo, rangeAfterNum } = dicRange;
|
||
let beforeRanks = randomRank(rangeBeforeFrom == -1? rank: rangeBeforeFrom, rangeBeforeTo == -1? rank: rangeBeforeTo, rangeBeforeNum);
|
||
let afterRanks = randomRank(rangeAfterFrom == -1? rank: rangeAfterFrom, rangeAfterTo == -1? rank: rangeAfterTo, rangeAfterNum);
|
||
|
||
let topRanks = getNumberArr(dicRange.topChallengeFrom, dicRange.topChallengeTo);
|
||
let ranks = [...topRanks, ...beforeRanks, ...afterRanks];
|
||
return uniqueArr(ranks.sort((a, b) => a - b));
|
||
}
|
||
|
||
function randomRank(min: number, max: number, len: number) {
|
||
if(min == max || len == 0) return [];
|
||
let arr = getNumberArr(min + 1, max);
|
||
return getRandEelm(arr, len);
|
||
}
|
||
|
||
// 根据ranks获取oppPlayer显示数据
|
||
export async function getOppPlayerByRanks(serverId: number, groupKey: string, vestigeId: number, ranks: number[]) {
|
||
let serverNames = await getAllServerName();
|
||
let opps = await GVGVestigeRankModel.findByRanks(groupKey, vestigeId, ranks);
|
||
let roleIds = opps.map(cur => cur.roleId);
|
||
let roles = await RoleModel.findByRoleIds(roleIds, 'roleId roleName head frame spine heads frames spines title lv guildName serverId updatedAt')
|
||
let dicRankMap = gameData.gvgVestige.get(vestigeId);
|
||
if(!dicRankMap) return [];
|
||
let result: GVGVestigeOppPlayer[] = [];
|
||
for(let rank of ranks) {
|
||
let obj = new GVGVestigeOppPlayer(rank);
|
||
let opp = opps.find(cur => cur.rank == rank);
|
||
let dicCurRank = dicRankMap.get(rank);
|
||
if(opp) {
|
||
let role = roles.find(cur => cur.roleId == opp.roleId);
|
||
if(!role) continue;
|
||
let lineupce = opp.lineup.reduce((pre, cur) => pre + cur.ce, 0);
|
||
const { leagueCode, name } = opp;
|
||
obj.setByRole(role, serverNames, lineupce, dicCurRank?.score||0, leagueCode, name);
|
||
} else {
|
||
obj.setByDic(dicCurRank, serverNames[serverId]);
|
||
}
|
||
result.push(obj);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 获取其他遗迹里使用过的武将
|
||
export async function getVestigeUsedHeroes(roleId: string, curVestigeId: number) {
|
||
let myDatas = await GVGVestigeRankModel.findAllByRole(roleId);
|
||
let result: number[] = [];
|
||
for(let { vestigeId, lineup = [] } of myDatas) {
|
||
if(vestigeId == curVestigeId) continue;
|
||
for(let { actorId, subHid } of lineup) {
|
||
result.push(actorId);
|
||
if(subHid) result.push(subHid);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// 是否在其他遗迹中使用过这个武将
|
||
export async function checkHeroIsUsedInOtherVestige(roleId: string, curVestigeId: number, heroes: { actorId: number, subHid: number }[]) {
|
||
let usedHeroes = await getVestigeUsedHeroes(roleId, curVestigeId);
|
||
for(let { actorId, subHid } of heroes) {
|
||
if(usedHeroes.indexOf(actorId) != -1) return true;
|
||
// 查副将
|
||
if(subHid) {
|
||
if(usedHeroes.indexOf(subHid) != -1) return true;
|
||
|
||
let hasSubHero = heroes.find(hero => hero.actorId == subHid);
|
||
if(hasSubHero) return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 检查我的排名是否可以挑战对方的排名
|
||
export function checkVestigeRank(myRank: number, targetRank: number) {
|
||
let dicRange = getGVGVestigeRange(myRank);
|
||
if(!dicRange) return false;
|
||
if(myRank == targetRank || targetRank == 0) return false;
|
||
|
||
// 是否可以挑战最前的几个排名
|
||
if(dicRange.topChallengeFrom <= targetRank && dicRange.topChallengeTo >= targetRank) return true;
|
||
if(dicRange.rangeBeforeTo == -1) {
|
||
if(dicRange.rangeBeforeFrom < targetRank && myRank > targetRank) return true;
|
||
} else {
|
||
if(dicRange.rangeBeforeFrom < targetRank && dicRange.rangeBeforeTo >= targetRank) return true;
|
||
}
|
||
if(dicRange.rangeAfterTo == -1) {
|
||
if(dicRange.rangeAfterFrom < targetRank && myRank > targetRank) return true;
|
||
} else {
|
||
if(dicRange.rangeAfterFrom < targetRank && dicRange.rangeAfterTo >= targetRank) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
export function isRobot(roleId: string) {
|
||
if(!roleId) roleId = '';
|
||
return roleId.startsWith('robot');
|
||
}
|
||
|
||
export async function checkVestigeOppStatus(configId: number, groupKey: string, vestigeId: number, roleId: string, myRank: number, targetRoleId: string, rank: number) {
|
||
|
||
let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId);
|
||
if(!myData || myData.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE;
|
||
|
||
if(isRobot(targetRoleId)) {
|
||
let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank);
|
||
if(targetData) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE;
|
||
} else {
|
||
let targetData = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId);
|
||
if(targetData?.rank != rank) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE;
|
||
}
|
||
let lockResult = await GVGVestigeLockModel.chooseOppLock(groupKey, vestigeId, rank, configId, roleId, targetRoleId);
|
||
if(!lockResult) return VESTIGE_OPP_STATUS.OPP_IS_LOCKED;
|
||
|
||
return VESTIGE_OPP_STATUS.BATTLE;
|
||
}
|
||
|
||
// 生成防守数据
|
||
export async function generateDefenseInfo(roleId: string, vestigeId: number, rank: number) {
|
||
if(isRobot(roleId)) {
|
||
let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); // 调用之前已经验证过了
|
||
let dicWar = gameData.war.get(dicRank?.warId);
|
||
let dicWarJson = gameData.warJson.get(dicWar?.dispatchJsonId);
|
||
if(!dicWarJson) return new OppPlayerInfo();
|
||
|
||
let heroes: OppPlayerHeroInfo[] = [];
|
||
for(let json of dicWarJson) {
|
||
if(json.relation == 2) {
|
||
let hero = new OppPlayerHeroInfo();
|
||
hero.setByWarJson(json);
|
||
heroes.push(hero);
|
||
}
|
||
}
|
||
let info = new OppPlayerInfo();
|
||
info.initByRobot(dicRank, heroes, true);
|
||
return info;
|
||
} else {
|
||
let playerVestigeData = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
|
||
if(!playerVestigeData) return null;
|
||
let lineup = playerVestigeData.lineup||[];
|
||
let hids = lineup.map(cur => cur.actorId);
|
||
let role = await RoleModel.findByRoleId(playerVestigeData.roleId, 'roleId roleName heads head frames frame spines spine title lv');
|
||
let heroes = await HeroModel.findByHidRange(hids, playerVestigeData.roleId, 'hid skinId lv star colorStar quality ce');
|
||
let league = await GVGLeagueModel.findByCode(playerVestigeData.leagueCode);
|
||
|
||
let info = new OppPlayerInfo();
|
||
info.initByPlayer(playerVestigeData.rank, role, league, true);
|
||
info.setPlayerHeroes(heroes, lineup, playerVestigeData.combo||[]);
|
||
return info;
|
||
}
|
||
}
|
||
|
||
export async function generateAttackInfo(roleId: string, league: GVGLeagueType, rank: number) {
|
||
let role = await RoleModel.findByRoleId(roleId, 'roleId roleName heads head frames frame spines spine title lv');
|
||
let info = new OppPlayerInfo();
|
||
info.initByPlayer(rank, role, league, false);
|
||
return info;
|
||
}
|
||
|
||
export async function generateAttackHeroInfo(lineup: { actorId: number, dataId: number, order: number, subHid: number }[], dbHeroes: HeroType[], combo: Combo[]) {
|
||
let info = new OppPlayerInfo();
|
||
info.setPlayerHeroes(dbHeroes, lineup, combo);
|
||
return info;
|
||
}
|
||
|
||
export async function getOppDetailData(rec: GVGVestigeRecType) {
|
||
let isRobot = rec.defenseInfo.isRobot;
|
||
let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank);
|
||
let result = new OppDetailData(rec, getVestigeRecStatus(rec));
|
||
if(!isRobot) {
|
||
const dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
|
||
const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
|
||
const defenseInfo = rec.defenseInfo.heroes||[];
|
||
const hids: number[] = [];
|
||
for(let { hid, subHid } of defenseInfo) {
|
||
hids.push(hid);
|
||
if(subHid) hids.push(subHid);
|
||
}
|
||
const heroes = await HeroModel.findByHidRange(hids, rec.defenseRoleId, 'hid lv quality star colorStar skins ce skinId');
|
||
const artifactSeids = heroes.map(hero => hero.artifact);
|
||
const artifacts = await ArtifactModel.findbySeqIds(rec.defenseRoleId, artifactSeids);
|
||
result.setByPlayer(dicWarJson, defenseInfo, heroes, artifacts, rec.defenseInfo.combo);
|
||
let attrByHid = await getHeroesAttributes(rec.defenseRoleId);
|
||
for(let [hid, attribute] of attrByHid) {
|
||
result.setAttribute(hid, attribute.getAttributesToString());
|
||
}
|
||
}
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
// 根据记录里的时间判断当前状态
|
||
export function getVestigeRecStatus(rec: GVGVestigeRecType) {
|
||
let { checkTime = 0, battleTime = 0, endTime = 0, cancel } = rec;
|
||
if(cancel) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) };
|
||
if(endTime > 0 && endTime <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) };
|
||
if(battleTime > 0 && battleTime <= Date.now() && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.BATTLE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN };
|
||
if(checkTime > 0 && checkTime <= Date.now() && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.CHECK, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN };
|
||
// 超时的
|
||
if(battleTime > 0 && endTime == 0 && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN };
|
||
if(checkTime > 0 && battleTime == 0 && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN };
|
||
return { status: VESTIGE_STATUS.NO, time: 0 };
|
||
}
|
||
|
||
// 将开始战斗时候的阵容存到防守阵容
|
||
export async function updateMyVestigeRank(isChange: boolean, atkData: GVGVestigeRankType, defData: GVGVestigeRankType, historyRank: number, rec: GVGVestigeRecType) {
|
||
let update: GVGVestigeRankUpdate = {}, needUpdate = false;
|
||
if(isChange) {
|
||
if(atkData && !atkData.hasDefense) { // 只有第一次挑战且自己没有主动保存过阵容的时候才会这么保存
|
||
let heroes = rec.attackInfo.heroes||[];
|
||
let lineup = heroes.map(hero => ({ actorId: hero.hid, dataId: hero.dataId, order: hero.order, ce: hero.ce, subHid: hero.subHid }));
|
||
update.lineup = lineup;
|
||
update.hasDefense = true;
|
||
needUpdate = true;
|
||
}
|
||
if(atkData && (historyRank == 0 || atkData.rank < historyRank)) { // 更新历史最高排名
|
||
update.historyRank = atkData.rank;
|
||
needUpdate = true;
|
||
}
|
||
if(atkData) { // 排名变化时刷新对手
|
||
let oppRanks = refreshVestigeOppRanks(atkData.rank);
|
||
update.oppRanks = oppRanks;
|
||
needUpdate = true;
|
||
}
|
||
}
|
||
if(needUpdate) {
|
||
atkData = await GVGVestigeRankModel.updateByRoleId(atkData.vestigeId, atkData.roleId, update);
|
||
}
|
||
if(isChange && defData) {
|
||
let oppRanks = refreshVestigeOppRanks(defData.rank);
|
||
defData = await GVGVestigeRankModel.updateByRoleId(defData.vestigeId, defData.roleId, { oppRanks });
|
||
}
|
||
return atkData
|
||
}
|
||
|
||
export function calBreakGoods(vestige: number, historyRank: number, rank: number) {
|
||
let dicRankMap = gameData.gvgVestige.get(vestige);
|
||
if(!dicRankMap) return { rewards: [], leagueRewards: [] };
|
||
let rewards: RewardInter[] = [], leagueRewards: RewardInter[] = [];
|
||
for(let i = historyRank + 1; i <= rank; i++) {
|
||
let dicRank = dicRankMap.get(i);
|
||
if(!dicRank) continue;
|
||
combinePushItem(rewards, dicRank.onceReward);
|
||
combinePushItem(leagueRewards, dicRank.onceLeagueReward);
|
||
}
|
||
return { rewards, leagueRewards }
|
||
}
|
||
|
||
// 玩家当天的驻扎记录,没有的话就创建一个
|
||
export async function getMyVestigeRank(configId: number, groupKey: string, vestigeId: number, roleId: string, myLeague?: GVGLeagueType) {
|
||
|
||
let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
|
||
if(!myVestigeRank) {
|
||
let role = await RoleModel.findByRoleId(roleId, 'roleId guildCode');
|
||
let oppRanks = refreshVestigeOppRanks(-1);
|
||
if(!myLeague) {
|
||
myLeague = await GVGLeagueModel.findLeagueByGuild(role.guildCode);
|
||
if(!myLeague) return null
|
||
}
|
||
const { leagueCode, name } = myLeague;
|
||
myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupKey, role, leagueCode, name, oppRanks );
|
||
}
|
||
return myVestigeRank;
|
||
}
|
||
|
||
// 保存排行榜
|
||
export async function saveScoreToRank(rec: GVGVestigeRecType) {
|
||
await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.attackInfo);
|
||
await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.defenseInfo);
|
||
}
|
||
|
||
export function getDayKeyInfo() {
|
||
return moment().format('YYMMDD');
|
||
}
|
||
|
||
export async function savePlayerRank(configId: number, groupKey: string, vestigeId: number, playerInfo: Partial<OppPlayerInfo>) {
|
||
if(playerInfo.isRobot) return
|
||
let dicRankMap = gameData.gvgVestige.get(vestigeId);
|
||
let newRank = dicRankMap?.get(playerInfo.newRank)?.score||0;
|
||
let oldRank = dicRankMap?.get(playerInfo.oldRank)?.score||0;
|
||
|
||
let nextWeek = <number>getTimeFun().getAfterDayWithHour(7);
|
||
let myScore = await GVGVestigeSumRankModel.incScore(playerInfo.roleId, playerInfo.leagueCode, configId, groupKey, newRank - oldRank);
|
||
let r1 = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day: getDayKeyInfo() });
|
||
await r1.setExpire(nextWeek);
|
||
await r1.setRankWithRoleInfo(playerInfo.roleId, myScore.score, myScore.updatedAt.getTime());
|
||
let leagueScore = await GVGVestigeLeagueRankModel.incScore(configId, playerInfo.leagueCode, groupKey, newRank - oldRank);
|
||
let r2 = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day: getDayKeyInfo() });
|
||
await r2.setExpire(nextWeek);
|
||
await r2.setRankWithLeagueInfo(playerInfo.leagueCode, leagueScore.score, leagueScore.updatedAt.getTime());
|
||
}
|
||
|
||
export async function getVestigeRank(redisKey: REDIS_KEY, isSimple: boolean, keyParam: KeyNameParam, myId: myIdInter, serverNames?: any) {
|
||
let r = new Rank(redisKey, keyParam);
|
||
r.setGenerFieldsFun((obj => {
|
||
if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL && obj instanceof RoleRankInfo) {
|
||
if(isSimple) {
|
||
return { rank: obj.rank, name: obj.roleName, serverName: serverNames[obj.serverId], score: obj.num }
|
||
} else {
|
||
return { ...obj, serverName: serverNames[obj.serverId], score: obj.num }
|
||
}
|
||
}
|
||
if(redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE && obj instanceof LeagueRankInfo) {
|
||
if(isSimple) {
|
||
return { rank: obj.rank, name: obj.name, score: obj.num }
|
||
} else {
|
||
return { ...obj, score: obj.num, leader: {...obj.leader, serverName: serverNames[obj.leader.serverId]}};
|
||
}
|
||
}
|
||
return obj
|
||
}));
|
||
|
||
let { ranks, myRank } = await r.getRankListWithMyRank(myId);
|
||
if (!myRank) {
|
||
if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) {
|
||
myRank = await r.generMyRankWithRole(myId.roleId, 0, 0);
|
||
} else if (redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE) {
|
||
myRank = await r.generMyRankWithLeague(myId.leagueCode, 0, 0);
|
||
}
|
||
}
|
||
return { ranks, myRank }
|
||
}
|
||
|
||
// systimer 服 每天晚上22点
|
||
export async function saveVestigeRankSchedule() {
|
||
let config = await GVGConfigModel.findConfig();
|
||
let period = getPeriodByTime(config.teamTime, config.prepareTime, config.battleTime, config.scheduleTime);
|
||
if(period != GVG_PERIOD.PREPARE) return;
|
||
let day = getDayKeyInfo();
|
||
let keys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_LEAGUE}:${day}:`);
|
||
for(let key of keys) {
|
||
let [,, groupKey] = key.split(':');
|
||
let r = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day});
|
||
let ranks = await r.getRankByRangeRaw();
|
||
await GVGVestigeLeagueRankModel.saveRank(groupKey, ranks);
|
||
await addVestigeLeagueRankRec(config.configId, groupKey, ranks);
|
||
await addVestigeRankMessage(ranks);
|
||
}
|
||
|
||
let memberKeys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_MEMBER_ALL}:${day}:`);
|
||
for(let key of memberKeys) {
|
||
let [,, groupKey] = key.split(':');
|
||
let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day});
|
||
let ranks = await r.getRankByRangeRaw();
|
||
await GVGVestigeSumRankModel.saveRank(groupKey, ranks);
|
||
}
|
||
let playerSumRanks = await GVGVestigeSumRankModel.findAllScores();
|
||
let userDatas = await GVGUserDataModel.addVestigeScores(config.configId, playerSumRanks);
|
||
for(let userData of userDatas) {
|
||
await sendMessageToUserWithSuc(userData.roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode: userData.leagueCode, job: LEAGUE_JOB.FIGHTER, sumContribute: calFighterContribute(userData.contribute) });
|
||
}
|
||
}
|
||
|
||
// systimer 服,每周六5点
|
||
export async function gvgBattlePeriodSchedule() {
|
||
const config = await GVGConfigModel.findConfig();
|
||
await sendUngotVestigeReward(config.configId);
|
||
}
|
||
|
||
export async function sendUngotVestigeReward(configId: number) {
|
||
const playerDatas = await GVGVestigeSumRankModel.getAllCanReceiveRanks(configId);
|
||
const leagueCodes: string[] = [];
|
||
const dataByLeague = new Map<string, Map<string, { playerRanks: {_id: string, rank: number }[], leagueRanks: { _id: string, rank: number }[] }>>(); // leagueCode => playerdata
|
||
const receiveLeagueParam: { _id: string, roleIds: string[] }[] = [], receivePlayerParam: string[] = [];
|
||
for(let player of playerDatas) {
|
||
if(leagueCodes.indexOf(player.leagueCode) == -1) {
|
||
leagueCodes.push(player.leagueCode);
|
||
}
|
||
if(!dataByLeague.has(player.leagueCode)) dataByLeague.set(player.leagueCode, new Map());
|
||
if(!dataByLeague.get(player.leagueCode).has(player.roleId)) dataByLeague.get(player.leagueCode).set(player.roleId, { playerRanks: [], leagueRanks: [] });
|
||
dataByLeague.get(player.leagueCode).get(player.roleId).playerRanks.push({ _id: player._id, rank: player.rank });
|
||
|
||
receivePlayerParam.push(player._id);
|
||
}
|
||
|
||
const leagueDatas = await GVGVestigeLeagueRankModel.getAllCanReceiveRanks(configId, leagueCodes);
|
||
for(let leagueData of leagueDatas) {
|
||
let players = dataByLeague.get(leagueData.leagueCode);
|
||
if(!players) continue;
|
||
for(let [roleId, data] of players) {
|
||
if(leagueData.receiveMembers.indexOf(roleId) == -1) {
|
||
data.leagueRanks.push({ _id: leagueData._id, rank: leagueData.rank });
|
||
let index = receiveLeagueParam.findIndex(cur => cur._id == leagueData._id);
|
||
if(index == -1) {
|
||
receiveLeagueParam.push({ _id: leagueData._id, roleIds: [ roleId ] });
|
||
} else {
|
||
receiveLeagueParam[index].roleIds.push(roleId);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
for(let [ leagueCode, players ] of dataByLeague) {
|
||
for(let [ roleId, { playerRanks, leagueRanks }] of players) {
|
||
let { leagueReward, rewards } = calVestigeLeagueBoxRewards(leagueRanks, playerRanks);
|
||
if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, null, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK);
|
||
if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.VESTIGE_REWARD, roleId, { params: [`${configId}`], goods: rewards });
|
||
}
|
||
}
|
||
|
||
await GVGVestigeSumRankModel.receiveRanks(receivePlayerParam);
|
||
await GVGVestigeLeagueRankModel.receiveManyRanks(receiveLeagueParam);
|
||
}
|
||
|
||
export function calVestigeLeagueBoxRewards(canReceiveRanks: { rank: number }[], canReceivePlayerRanks: { rank: number }[]) {
|
||
let rewards: RewardInter[] = [], leagueReward: RewardInter[] = [];
|
||
for(let { rank } of canReceiveRanks) {
|
||
let dicRank = getGVGVestigeLeagueRank(rank);
|
||
if(!dicRank) { console.error('dic_zyz_GVGVestigeLeagueRank error'); continue; }
|
||
// console.log('###### league', rank, dicRank)
|
||
combinePushItem(rewards, dicRank.rankReward);
|
||
combinePushItem(leagueReward, dicRank.rankLeagueReward);
|
||
}
|
||
for(let { rank } of canReceivePlayerRanks) {
|
||
let dicRank = getGVGVestigePlayerRank(rank);
|
||
if(!dicRank) { console.error('dic_zyz_GVGVestigPlayerRank error'); continue; }
|
||
// console.log('###### player', rank, dicRank)
|
||
combinePushItem(rewards, dicRank.rankPlayerReward);
|
||
combinePushItem(leagueReward, dicRank.rankPlayerLeagueReward);
|
||
}
|
||
let boxPreview: { id: number, count: number, itemType: number }[] = [];
|
||
for(let { id, count } of rewards) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM });
|
||
for(let { id, count } of leagueReward) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM });
|
||
return {
|
||
leagueReward, rewards, boxPreview, canReceiveBox: canReceiveRanks.length > 0 || canReceivePlayerRanks.length > 0
|
||
}
|
||
}
|
||
|
||
export async function pushGvgFightIconShow(roleId: string, battleCode: string) {
|
||
const rec = await GVGVestigeRecModel.findByBattleCode(battleCode);
|
||
let result: (GVGVestigeRecUpdate & { rplFileUrl: string })[] = [];
|
||
const { attackRoleId, hasRpl, remoteUrl } = rec;
|
||
const rplFileUrl = battleCode && hasRpl ? remoteUrl : '';
|
||
const obj = getVestigeRecStatus(rec);
|
||
if (obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl });
|
||
let gvgFightRecs = { list: result, rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) };
|
||
|
||
await pushIconShow(roleId, false, gvgFightRecs)
|
||
} |