feat(gvg): 征战中原排行榜奖励

This commit is contained in:
luying
2023-02-04 12:08:29 +08:00
parent fc2a86ad81
commit eb772484c2
21 changed files with 678 additions and 100 deletions

View File

@@ -3,6 +3,7 @@ import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, ITEM_CHANGE_REASON, REDIS_KEY, R
import { BattleRecordModel } from "../../../db/BattleRecord";
import { GVGLeagueModel } from "../../../db/GVGLeague";
import { GVGUserItemModel } from "../../../db/GVGUserItem";
import GVGVestigeLeagueRank, { GVGVestigeLeagueRankModel } from "../../../db/GVGVestigeLeagueRank";
import { GVGVestigeLockModel } from "../../../db/GVGVestigeLock";
import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank";
import { GVGVestigeRecModel, GVGVestigeRecUpdate } from "../../../db/GVGVestigeRec";
@@ -11,12 +12,13 @@ import { RoleModel } from "../../../db/Role";
import { GVGVestigeOppLineup, VestigeRank } from "../../../domain/gvgField/returnData";
import { RoleRankInfo } from "../../../domain/rank";
import { getRemoteRplFilePath, getRemoteRplPrefix } from "../../../pubUtils/battleUtils";
import { gameData } from "../../../pubUtils/data";
import { gameData, getGVGVestigeLeagueRank } from "../../../pubUtils/data";
import { GVG } from "../../../pubUtils/dicParam";
import { RewardInter } from "../../../pubUtils/interface";
import { resResult } from "../../../pubUtils/util";
import { isHeroHidden } from "../../../services/dataService";
import { calBreakGoods, checkHeroIsUsedInOtherVestige, checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackHeroInfo, generateAttackInfo, generateDefenseInfo, getOppDetailData, getOppPlayerByRanks, getVestigeRecStatus, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks, updateMyVestigeRank } from "../../../services/gvg/gvgFightService";
import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService";
import { calBreakGoods, checkHeroIsUsedInOtherVestige, checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackHeroInfo, generateAttackInfo, generateDefenseInfo, getDayKeyInfo, getMyVestigeRank, getOppDetailData, getOppPlayerByRanks, getVestigeRecStatus, getVestigeRank, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks, saveScoreToRank, updateMyVestigeRank, saveVestigeRankSchedule } from "../../../services/gvg/gvgFightService";
import { addGVGReward, combinePushItem, handleGVGCost } from "../../../services/gvg/gvgItemService";
import { addGVGActive } from "../../../services/gvg/gvgPrepareService";
import { getGroupIdOfServer, getGVGPeriodData, getGVGServerType } from "../../../services/gvg/gvgService";
import { checkBattleHeroesByHid } from "../../../services/normalBattleService";
@@ -38,6 +40,7 @@ export class GVGProduceHandler {
async getVestige(msg: { vestigeId: number }, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const { vestigeId } = msg;
let { configId, period } = getGVGPeriodData();
@@ -46,20 +49,20 @@ export class GVGProduceHandler {
if(!await checkVestige(serverId, vestigeId)) {
return resResult(STATUS.GVG_VESTIGE_ERR);
}
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let dicRankMap = gameData.gvgVestige.get(vestigeId);
if(!dicRankMap) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
if(!myVestigeRank) {
let role = await RoleModel.findByRoleId(roleId, 'roleId');
let oppRanks = refreshVestigeOppRanks(-1);
myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupId, serverType, role, oppRanks );
}
let myVestigeRank = await getMyVestigeRank(configId, groupId, serverType, vestigeId, roleId, myLeague);
if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let { rank, lineup, oppRanks, refreshCnt } = myVestigeRank;
let score = dicRankMap?.get(rank)||0;
let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0);
let oppPlayers = await getOppPlayerByRanks(serverId, groupId, serverType, vestigeId, oppRanks);
@@ -68,7 +71,7 @@ export class GVGProduceHandler {
return resResult(STATUS.SUCCESS, {
vestigeId,
myRank: rank,
score,
score: dicRankMap?.get(rank)?.score||0,
lineup, lineupCe,
oppPlayers,
refreshCnt,
@@ -88,12 +91,8 @@ export class GVGProduceHandler {
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
if(!myVestigeRank) {
let role = await RoleModel.findByRoleId(roleId, 'roleId');
let oppRanks = refreshVestigeOppRanks(-1);
myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupId, serverType, role, oppRanks );
}
let myVestigeRank = await getMyVestigeRank(configId, groupId, serverType, vestigeId, roleId);
if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
for(let { actorId } of heroes) {
if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN);
@@ -162,13 +161,7 @@ export class GVGProduceHandler {
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名
if(!myVestigeRank) {
let role = await RoleModel.findByRoleId(roleId, 'roleId');
let oppRanks = refreshVestigeOppRanks(-1);
myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupId, serverType, role, oppRanks );
}
let myVestigeRank = await getMyVestigeRank(configId, groupId, serverType, vestigeId, roleId);
let refreshCnt = myVestigeRank.refreshCnt||0;
if(refreshCnt >= GVG.GVG_REFRESH_TIME) return resResult(STATUS.GVG_VESTIGE_REFESH_CNT_MAX);
@@ -226,7 +219,7 @@ export class GVGProduceHandler {
// 消耗征战令的获得活跃
let active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_FIGHT_COIN);
// 创建rec
const attackInfo = await generateAttackInfo(roleId, myRank);
const attackInfo = await generateAttackInfo(roleId, myLeague.leagueCode, myRank);
const defenseInfo = await generateDefenseInfo(targetRoleId, vestigeId, rank);
const rec = await GVGVestigeRecModel.createRec(configId, vestigeId, groupId, serverType, dicRank.warId, attackInfo, defenseInfo, leagueGoods);
const oppDetail = await getOppDetailData(rec);
@@ -343,14 +336,14 @@ export class GVGProduceHandler {
let { rewards, leagueRewards } = calBreakGoods(rec.vestigeId, historyRank, atkData.rank);
let breakGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewards, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_END);
// TODO 更新redis排行榜
await saveScoreToRank(rec);
return resResult(STATUS.SUCCESS, {
vestigeId: rec.vestigeId,
battleCode: rec.battleCode,
leagueGoods: rec.leagueGoods,
rank: atkData.rank,
score: gameData.gvgVestige.get(rec.vestigeId)?.get(atkData.rank)?.score,
score: gameData.gvgVestige.get(rec.vestigeId)?.get(atkData.rank)?.score??0,
historyRank: atkData.historyRank,
...getVestigeRecStatus(rec),
oppPlayers: await getOppPlayerByRanks(serverId, rec.groupId, rec.serverType, rec.vestigeId, atkData.oppRanks),
@@ -381,11 +374,48 @@ export class GVGProduceHandler {
// 征战中原简单小排行榜
async getLeagueRank(msg: {}, session: BackendSession) {
const roleId = session.get('roleId');
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let serverNames = await getAllServerName();
const { ranks: leagueRank, myRank: myLeagueRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, true, { groupId, serverType, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode });
const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, true, { groupId, serverType, day: getDayKeyInfo() }, { roleId }, serverNames);
return resResult(STATUS.SUCCESS, {
leagueRank, myLeagueRank, memberRank, myMemberRank
})
}
// 联军详细排名
async getLeagueDetailRank(msg: {}, session: BackendSession) {
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let groupId = await getGroupIdOfServer(serverId);
let serverType = await getGVGServerType(serverId);
let serverNames = await getAllServerName();
let { configId } = getGVGPeriodData();
const { ranks, myRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, false, { groupId, serverType, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }, serverNames);
let yesterdayRank = await GVGVestigeLeagueRank.getYesterdayRank(myLeague.leagueCode);
let canReceiveRanks = await GVGVestigeLeagueRank.getCanReceiveRanks(configId, myLeague.leagueCode);
return resResult(STATUS.SUCCESS, {
ranks, myRank,
latestRank: yesterdayRank?.rank||0,
canReceiveBox: canReceiveRanks.length > 0
})
}
// 玩家排行
@@ -432,7 +462,42 @@ export class GVGProduceHandler {
}
// 领取排行榜获得的每日奖励
async receiveBox(msg: { vestigeId: number }, session: BackendSession) {
async receiveBox(msg: { }, session: BackendSession) {
const guildCode = session.get('guildCode');
const roleId = session.get('roleId');
const roleName = session.get('roleName');
const sid = session.get('sid');
const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
let { configId } = getGVGPeriodData();
let canReceiveRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode);
if(canReceiveRanks.length <= 0) return resResult(STATUS.GVG_RECEIVE_NO_RANK_REWARD);
let rewards: RewardInter[] = [], leagueReward: RewardInter[] = [];
for(let { rank } of canReceiveRanks) {
let dicRank = getGVGVestigeLeagueRank(rank);
if(!dicRank) { console.error('dic_zyz_GVGVestigeLeagueRank error'); continue; }
combinePushItem(rewards, dicRank.rankReward);
combinePushItem(leagueReward, dicRank.rankLeagueReward);
}
let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK)
await GVGVestigeLeagueRankModel.receiveRanks(canReceiveRanks.map(cur => cur._id));
return resResult(STATUS.SUCCESS, {
leagueGoods,
canReceiveRanks: false
})
}
async debugCalRec(msg: { battleCode: string }, session: BackendSession) {
let rec = await GVGVestigeRecModel.findByBattleCode(msg.battleCode);
await saveScoreToRank(rec);
return resResult(STATUS.SUCCESS);
}
async debugSaveScore(msg: {}, session: BackendSession) {
await saveVestigeRankSchedule();
return resResult(STATUS.SUCCESS);
}
}

View File

@@ -146,8 +146,11 @@ export class GVGProduceHandler {
let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);
await lockField(myLeague.leagueCode, roleId, roleName, farmId);
let dicResource = gameData.gvgResource.get(farmId);
if(dicResource.type == GVG_RESOURCE_TYPE.FOOD) {
await lockField(myLeague.leagueCode, roleId, roleName, farmId);
}
const myRank = await getmyDistributeRank(myLeague.leagueCode, myLeague.members, roleId);
return resResult(STATUS.SUCCESS, {

View File

@@ -11,7 +11,7 @@ export async function getGVGCities(league: GVGLeagueType) {
/**
* TODO 获取当前城池状态
* @returns [{cityId: number, guardLeagueName: string, teamCnt: number }]
* @returns [{cityId: number, guardLeagueCode: string, guardLeagueName: string, teamCnt: number }]
*/
export async function getGVGCitiesInfo(league: GVGLeagueType): Promise<{cityId: number, guardLeagueName: string, teamCnt: number }[]> {
return [];

View File

@@ -1,24 +1,30 @@
// 征战中原相关
import { GVG_PERIOD, STATUS, VESTIGE_OPP_STATUS, VESTIGE_STATUS } from "../../consts";
import moment = require("moment");
import { GVG_PERIOD, REDIS_KEY, VESTIGE_OPP_STATUS, VESTIGE_STATUS } from "../../consts";
import { ArtifactModel } from "../../db/Artifact";
import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague";
import { GVGVestigeModel } from "../../db/GVGVestige";
import { GVGVestigeLeagueRankModel } from "../../db/GVGVestigeLeagueRank";
import { GVGVestigeLockModel } from "../../db/GVGVestigeLock";
import { GVGVestigeRankModel, GVGVestigeRankType, GVGVestigeRankUpdate } from "../../db/GVGVestigeRank";
import { GVGVestigeRecType } from "../../db/GVGVestigeRec";
import { GVGVestigeSumRankModel } from "../../db/GVGVestigeSumRank";
import { HeroModel, HeroType } from "../../db/Hero";
import { RoleModel, RoleType } from "../../db/Role";
import { OppDetailData, OppDetailHeroData, OppPlayerHeroInfo, OppPlayerInfo } from "../../domain/gvgField/gvgDb";
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, getGVGVestigeRange } from "../../pubUtils/data";
import { GVG } from "../../pubUtils/dicParam";
import { RewardInter } from "../../pubUtils/interface";
import { getTimeFun } from "../../pubUtils/timeUtil";
import { getRandEelm, getRandValueByMinMax, resResult } from "../../pubUtils/util";
import { getRandEelm } from "../../pubUtils/util";
import { getNumberArr, uniqueArr } from "../ladderService";
import { getHeroesAttributes } from "../playerCeService";
import { getAllServerName } from "../redisService";
import { combineItems } from "../role/util";
import { Rank } from "../rankService";
import { findKeys, getAllServerName, redisClient } from "../redisService";
import { combinePushItem } from "./gvgItemService";
import { getGroupIdOfServer, getGVGServerType } from "./gvgService";
// 备战期的遗迹和激战期的开始结束战斗时间
@@ -147,13 +153,8 @@ export function isRobot(roleId: string) {
export async function checkVestigeOppStatus(configId: number, groupId: number, serverType: number, vestigeId: number, roleId: string, myRank: number, targetRoleId: string, rank: number) {
let myData = await GVGVestigeRankModel.findByRole(vestigeId, roleId);
if(!myData) {
let role = await RoleModel.findByRoleId(roleId, 'roleId');
let oppRanks = refreshVestigeOppRanks(-1);
myData = await GVGVestigeRankModel.initRank(configId, vestigeId, groupId, serverType, role, oppRanks );
}
if(myData?.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE;
let myData = await getMyVestigeRank(configId, groupId, serverType, vestigeId, roleId);
if(!myData || myData.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE;
if(isRobot(targetRoleId)) {
let targetData = await GVGVestigeRankModel.findByRank(vestigeId, rank);
@@ -196,16 +197,16 @@ export async function generateDefenseInfo(roleId: string, vestigeId: number, ran
let heroes = await HeroModel.findByHidRange(hids, playerVestigeData.roleId, 'hid skinId lv star colorStar quality ce');
let info = new OppPlayerInfo();
info.initByPlayer(playerVestigeData.rank, role, true);
info.initByPlayer(playerVestigeData.rank, role, playerVestigeData.leagueCode, true);
info.setPlayerHeroes(heroes, lineup);
return info;
}
}
export async function generateAttackInfo(roleId: string, rank: number) {
export async function generateAttackInfo(roleId: string, leagueCode: string, 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, false);
info.initByPlayer(rank, role, leagueCode, false);
return info;
}
@@ -262,7 +263,7 @@ export async function updateMyVestigeRank(isChange: boolean, atkData: GVGVestige
update.hasDefense = true;
needUpdate = true;
}
if(atkData && atkData.rank > historyRank) { // 更新历史最高排名
if(atkData && (historyRank == 0 || atkData.rank < historyRank)) { // 更新历史最高排名
update.historyRank = atkData.rank;
needUpdate = true;
}
@@ -285,22 +286,87 @@ export function calBreakGoods(vestige: number, historyRank: number, rank: number
for(let i = historyRank + 1; i <= rank; i++) {
let dicRank = dicRankMap.get(i);
if(!dicRank) continue;
for(let { id, count } of dicRank.onceReward) {
let obj = rewards.find(obj => obj.id == id);
if(!obj) {
rewards.push({ id, count });
} else {
obj.count += count;
}
}
for(let { id, count } of dicRank.onceLeagueReward) {
let obj = leagueRewards.find(obj => obj.id == id);
if(!obj) {
leagueRewards.push({ id, count });
} else {
obj.count += count;
}
}
combinePushItem(rewards, dicRank.onceReward);
combinePushItem(leagueRewards, dicRank.onceLeagueReward);
}
return { rewards, leagueRewards }
}
// 玩家当天的驻扎记录,没有的话就创建一个
export async function getMyVestigeRank(configId: number, groupId: number, serverType: number, 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
}
myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupId, serverType, role, myLeague.leagueCode, oppRanks );
}
return myVestigeRank;
}
// 保存排行榜
export async function saveScoreToRank(rec: GVGVestigeRecType) {
await savePlayerRank(rec.configId, rec.groupId, rec.serverType, rec.vestigeId, rec.attackInfo);
await savePlayerRank(rec.configId, rec.groupId, rec.serverType, rec.vestigeId, rec.defenseInfo);
}
export function getDayKeyInfo() {
return moment().format('YYMMDD');
}
async function savePlayerRank(configId: number, groupId: number, serverType: number, vestigeId: number, playerInfo: 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 myScore = await GVGVestigeSumRankModel.incScore(playerInfo.roleId, groupId, serverType, newRank - oldRank);
let r1 = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { serverType, groupId, day: getDayKeyInfo() });
await r1.setRankWithRoleInfo(playerInfo.roleId, myScore.score, myScore.updatedAt.getTime());
let leagueScore = await GVGVestigeLeagueRankModel.incScore(configId, playerInfo.leagueCode, groupId, serverType, newRank - oldRank);
let r2 = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { serverType, groupId, day: getDayKeyInfo() });
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 && isSimple && obj instanceof RoleRankInfo) {
return { rank: obj.rank, name: obj.roleName, 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, 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 }
}
export async function saveVestigeRankSchedule() {
let day = getDayKeyInfo();
let keys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_LEAGUE}:${day}:`);
for(let key of keys) {
let [,, _groupId, _serverType] = key.split(':');
let groupId = parseInt(_groupId);
let serverType = parseInt(_serverType);
let r = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupId, serverType, day});
let ranks = await r.getRankByRangeRaw();
await GVGVestigeLeagueRankModel.saveRank(groupId, serverType, ranks);
}
}

View File

@@ -82,4 +82,15 @@ export function getProduceCoinCnt(items: RewardInter[]) {
}
}
return produceCoinCnt;
}
export function combinePushItem(targetItems: RewardInter[], dicItems: RewardInter[]) {
for(let { id, count } of dicItems) {
let obj = targetItems.find(obj => obj.id == id);
if(!obj) {
targetItems.push({ id, count });
} else {
obj.count += count;
}
}
}

View File

@@ -1,4 +1,4 @@
import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo, RoleAndGuildRankInfo } from "../domain/rank";
import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo, RoleAndGuildRankInfo, LeagueRankParam, LeagueRankInfo } from "../domain/rank";
import { getInfoKeyByRedisKey, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD, getRedisKeyByRankType, COUNTER, RANK_TYPE, PUSH_ROUTE } from "../consts";
import { redisClient, delKeys, saveLadderDefCeByData } from "./redisService";
import { RoleType, RoleModel } from "../db/Role";
@@ -16,7 +16,10 @@ import { ActivityTimeLimitRankModel } from "../db/ActivityTimeLimitRank";
import { sendMessageToServerWithSuc } from "./pushService";
import { LadderMatchModel } from "../db/LadderMatch";
import { completeRanks } from "./ladderService";
import { GVGVestigeRankModel } from "../db/GVGVestigeRank";
import { GVGVestigeSumRankModel } from "../db/GVGVestigeSumRank";
import { GVGLeagueModel, GVGLeagueType } from "../db/GVGLeague";
import { GVGVestigeLeagueRankModel } from "../db/GVGVestigeLeagueRank";
import { getDayKeyInfo } from "./gvg/gvgFightService";
/**
@@ -111,7 +114,7 @@ export class Rank {
* 返回字段修改
* @param obj
*/
private async generFields(obj: GuildRankInfo | RoleRankInfo) {
private async generFields(obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) {
return obj;
}
@@ -119,7 +122,7 @@ export class Rank {
* 从外部设置返回字段
* @param cb
*/
public setGenerFieldsFun(cb: (obj: GuildRankInfo | RoleRankInfo) => any) {
public setGenerFieldsFun(cb: (obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) => any) {
this.generFields = cb;
}
@@ -189,6 +192,22 @@ export class Rank {
return newScore;
}
public async setRankWithLeagueInfo(leagueCode: string, score: number, timestamp: number, league?: GVGLeagueType, isInc = false) {
return await this.setRankWithLeagueInfoArrParam(leagueCode, [score, timestamp], league, isInc);
}
public async setRankWithLeagueInfoArrParam(leagueCode: string, scores: number[], league?: GVGLeagueType, isInc = false) {
for (let infoKey of [this.infoKey, ...this.extraKeys]) {
const hasCurUser = await redisClient().hexistsAsync(infoKey, leagueCode);
if (!hasCurUser) {
await this.generParamAndSet(infoKey, { leagueCode }, { league });
}
}
let newScore = await this.setRank({ leagueCode }, scores, isInc);
return newScore;
}
/**
* 根据武将表设置更新排行榜&玩家信息
* @param roleId 玩家id
@@ -211,7 +230,7 @@ export class Rank {
/**
* 将玩家信息按顺序组成 如roleId:hid
* @param {{ string }} key redis key
* @param {{ roleId?: string; guildCode?: string; hid?: number }} param 玩家信息
* @param {{ roleId?: string; guildCode?: string; hid?: number; leagueCode?: string }} param 玩家信息
*/
private composeFields(key: REDIS_KEY, param: myIdInter) {
let type = KEY_TO_COMPOSE_FIELD.get(key);
@@ -222,6 +241,8 @@ export class Rank {
return param.guildCode;
} else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) {
return `${param.roleId}:${param.hid}`;
} else if (type == COMPOSE_FIELD_TYPE.LEAGUE) {
return `${param.leagueCode}`;
} else {
return '';
}
@@ -243,6 +264,8 @@ export class Rank {
return { guildCode: arr[0] };
} else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) {
return { roleId: arr[0], hid: parseInt(arr[1]) };
} else if (type == COMPOSE_FIELD_TYPE.LEAGUE) {
return { leagueCode: arr[0] };
} else {
return {};
}
@@ -254,9 +277,9 @@ export class Rank {
* @param fields 玩家id
* @param db 数据库内的数据
*/
public async generParamAndSet(infoKey: string, fields: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroUpdate }) {
let { roleId, guildCode, hid } = fields;
let { role, guild, hero } = db;
public async generParamAndSet(infoKey: string, fields: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroUpdate, league?: GVGLeagueType }) {
let { roleId, guildCode, hid, leagueCode } = fields;
let { role, guild, hero, league } = db;
if (infoKey == REDIS_KEY.USER_INFO) {
if (!role) {
@@ -272,6 +295,13 @@ export class Rank {
}
let param = new GuildRankParam(guild);
await this.setUserInfo(infoKey, { guildCode }, param);
} else if (infoKey == REDIS_KEY.LEAGUE_INFO) {
if (!league) {
league = await GVGLeagueModel.findByCode(leagueCode);
if(!league) return;
}
let param = new LeagueRankParam(league);
await this.setUserInfo(infoKey, { leagueCode }, param);
} else if (infoKey == REDIS_KEY.TOP_LINEUP_INFO) {
if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
@@ -345,7 +375,7 @@ export class Rank {
* @param myId
* @param param
*/
private async setUserInfo(infoKey: REDIS_KEY, myId: myIdInter, param: RankParam | GuildRankParam | LineupParam[]) {
private async setUserInfo(infoKey: REDIS_KEY, myId: myIdInter, param: RankParam | GuildRankParam | LineupParam[] | LeagueRankParam) {
let field = this.composeFields(infoKey, myId);
let value = JSON.stringify(param);
return await redisClient().hsetAsync(infoKey, field, value);
@@ -532,6 +562,29 @@ export class Rank {
return await this.generFields(param);
}
public async generMyRankWithLeague(leagueCode: string, score: number, time: number, league?: GVGLeagueType) {
// 如果没有信息,更新玩家信息
let param: LeagueRankInfo;
let hasCurUser = await redisClient().hexistsAsync(this.infoKey, leagueCode);
if (!hasCurUser) {
if (!league) {
league = await GVGLeagueModel.findByCode(leagueCode);
if(!league) return null
}
param = new LeagueRankInfo(league);
param.setInfo(0, { leagueCode }, score, time);
} else {
const info = await redisClient().hgetAsync(this.infoKey, leagueCode);
if(!info) return null
const leagueInfo = JSON.parse(info);
param = new LeagueRankInfo(leagueInfo);
param.setInfo(0, { leagueCode }, score, time);
}
return await this.generFields(param);
}
public async generMyRankWithHero(roleId: string, hid: number, score: number, time: number, hero?: HeroType, role?: RoleType) {
// 如果没有信息,更新玩家信息
let param: RoleRankInfo;
@@ -558,7 +611,7 @@ export class Rank {
return await this.generFields(param);
}
private async setExInfoToParam(extraKey: string, param: RoleRankInfo | GuildRankInfo, myId: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) {
private async setExInfoToParam(extraKey: string, param: RoleRankInfo | GuildRankInfo | LeagueRankInfo, myId: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) {
let { role, guild, hero } = db;
if (extraKey == REDIS_KEY.TOP_LINEUP_INFO) {
@@ -668,7 +721,6 @@ export class Rank {
public async getRankListWithMyRank(myId: myIdInter, isReverse = true) {
let ranks = await this.getRankByRange('+inf', '-inf', isReverse);
console.log('#### ranks', ranks);
let newRanks = [], newMyRank: any;
let myRank = ranks.find(cur => {
return cur.isMyInfo(myId);
@@ -738,7 +790,7 @@ export class Rank {
public async getRankByRange(max: number | string = '+inf', min: number | string = '-inf', isReverse = true) {
let raws = await this.getRankByRangeRaw(max, min, isReverse);
let ranks = new Array<RoleRankInfo | GuildRankInfo>();
let ranks = new Array<RoleRankInfo | GuildRankInfo | LeagueRankInfo>();
let l = 1;
for (let { field, scores } of raws) {
let param = await this.getParam(l, field, scores);
@@ -756,7 +808,7 @@ export class Rank {
const userInfo = JSON.parse(info);
if(!userInfo) return null;
let param: RoleRankInfo | GuildRankInfo;
let param: RoleRankInfo | GuildRankInfo | LeagueRankInfo;
if (this.infoKey == REDIS_KEY.USER_INFO) {
if (this.key != REDIS_KEY.LADDER && this.key != REDIS_KEY.GVG_VESTIGE_MEMBER && nowSeconds() - userInfo.updatedAt > 2 * 30 * 24 * 60 * 60) {
return null;
@@ -771,6 +823,10 @@ export class Rank {
param = new GuildRankInfo(userInfo);
param.setInfo(rank, myId, scores[0], scores[1]);
}
} else if (this.infoKey == REDIS_KEY.LEAGUE_INFO) {
param = new LeagueRankInfo(userInfo);
param.setInfo(rank, myId, scores[0], scores[1]);
}
for (let extraKey of this.extraKeys) {
@@ -781,7 +837,7 @@ export class Rank {
public async getRankByRank(start: number, end: number) {
let ranks = new Array<RoleRankInfo | GuildRankInfo>();
let ranks = new Array<RoleRankInfo | GuildRankInfo | LeagueRankInfo>();
let key = this.keyName.getName();
if (this.isUnion) {
key = await this.generateUnionRank();
@@ -1125,6 +1181,32 @@ export async function setRankRedisFromDb(type: string, args?: { serverId?: numbe
await r.setRankWithRoleInfo(rank.roleId, rank.rank, 0, role);
await saveLadderDefCeByData(rank.roleId, rank);
}
} else if (type == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) {
let ranks = await GVGVestigeSumRankModel.findRank();
for(let { _id: { groupId, serverType }, arr, roleIds } of ranks) {
let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.RANK);
let r = new Rank(type, { groupId, serverType, day: getDayKeyInfo() });
r.setIsInit(true);
for(let { roleId, score, updatedAt } of arr) {
let role = roles.find(cur => cur.roleId == roleId);
if(role) {
await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role);
}
}
}
} else if (type == REDIS_KEY.GVG_VESTIGE_LEAGUE) {
let ranks = await GVGVestigeLeagueRankModel.findRank();
for(let { _id: { groupId, serverType }, arr, leagueCodes } of ranks) {
let leagues = await GVGLeagueModel.findByCodes(leagueCodes);
let r = new Rank(type, { groupId, serverType, day: getDayKeyInfo() });
r.setIsInit(true);
for(let { leagueCode, score, updatedAt } of arr) {
let league = leagues.find(cur => cur.leagueCode == leagueCode);
if(league) {
await r.setRankWithLeagueInfo(leagueCode, score, updatedAt.getTime(), league);
}
}
}
}
}

View File

@@ -16,8 +16,6 @@ import { RoleModel, RoleType } from '../db/Role';
import { GuildType } from '../db/Guild';
import { ActivityGroupModel } from '../db/ActivityGroup';
import { LadderMatchModel, LadderMatchType } from '../db/LadderMatch';
import { GVGServerGroupModel } from '../db/GVGServerGroup';
import { nowSeconds } from '../pubUtils/timeUtil';
/**
* 在服务重新启动时将信息存入redis
@@ -50,9 +48,14 @@ export async function initAllRank() {
await delKeys(REDIS_KEY.SUM_CE_SNAPSHOT);
await delKeys(REDIS_KEY.TOP_LINE_SNAPSHOT);
await delKeys(REDIS_KEY.LADDER);
await delKeys(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL);
await delKeys(REDIS_KEY.GVG_VESTIGE_LEAGUE);
await delKeys(REDIS_KEY.LEAGUE_INFO);
await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {});
await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, {});
await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_LEAGUE, {});
for(let {id} of serverList) {
await initRankByServerId(id);
await initActivitiesRank(id)
@@ -163,6 +166,11 @@ export async function updateUserInfo(key: string, roleId: string, arr: Array<{fi
}
}
export async function findKeys(key: string) {
let keys = await redisClient().keysAsync(`${key}*`);
return keys
}
/********排行榜结束 */

View File

@@ -44,6 +44,7 @@ import { HiddenDataModel, HiddenDataModelType } from '../db/HiddenData';
import { setHiddenData, setHiddenDataToMemory } from './dataService';
import { GVGConfigModel } from '../db/GVGConfig';
import { createNewGVGConfig, initLeaguePrepare } from './gvg/gvgService';
import { saveVestigeRankSchedule } from './gvg/gvgFightService';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -905,11 +906,12 @@ export async function initGVGConfigSchedule() {
scheduleJob(`gvgConfig`, config.scheduleTime * 1000, createNewGVGConfig);
console.log('##### initGVGConfigSchedule', nowSeconds(), config.prepareTime)
if(nowSeconds() > config.prepareTime) {
initLeaguePrepare();
} else {
scheduleJob(`gvgPrepare`, config.prepareTime * 1000, initLeaguePrepare);
}
scheduleJob('gvgFightSchedule', '0 0 22 * * ?', saveVestigeRankSchedule);
}
// —————————————— gvg end —————————————— //