From 34e02dea896a3bf11ba150cac3d1ebb420d44fe7 Mon Sep 17 00:00:00 2001 From: luying Date: Tue, 6 Apr 2021 19:52:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E8=A1=8C=E6=A6=9C=EF=BC=9A=E6=97=A7?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../servers/battle/handler/guildHandler.ts | 37 +- .../app/servers/battle/handler/pvpHandler.ts | 40 +- .../battle/handler/towerBattleHandler.ts | 29 +- .../guild/handler/cityActivityHandler.ts | 30 +- .../guild/handler/gateActivityHandler.ts | 57 +- .../guild/handler/raceActivityHandler.ts | 5 +- .../app/servers/role/handler/friendHandler.ts | 6 +- .../app/servers/role/handler/rankHandler.ts | 15 +- game-server/app/services/battleService.ts | 8 +- .../app/services/guildActivityObjService.ts | 5 +- .../app/services/guildActivityService.ts | 169 +++--- game-server/app/services/guildService.ts | 12 +- .../app/services/normalBattleService.ts | 4 +- game-server/app/services/pvpService.ts | 30 +- game-server/app/services/rankService.ts | 305 +++++++++++ game-server/app/services/redisService.ts | 510 +++--------------- game-server/app/services/timeTaskService.ts | 30 +- game-server/config/redis.ts | 2 + shared/consts/constModules/selectConst.ts | 8 +- shared/db/Role.ts | 2 +- shared/domain/rank.ts | 97 +++- .../resource/jsons/dic_zyz_rankingReward.json | 266 +++++++++ .../resource/jsons/dic_zyz_rankingType.json | 65 +++ 23 files changed, 1014 insertions(+), 718 deletions(-) create mode 100644 game-server/app/services/rankService.ts create mode 100644 shared/resource/jsons/dic_zyz_rankingReward.json create mode 100644 shared/resource/jsons/dic_zyz_rankingType.json diff --git a/game-server/app/servers/battle/handler/guildHandler.ts b/game-server/app/servers/battle/handler/guildHandler.ts index 1e9a0e8a6..046e4ae6b 100644 --- a/game-server/app/servers/battle/handler/guildHandler.ts +++ b/game-server/app/servers/battle/handler/guildHandler.ts @@ -15,13 +15,14 @@ import { UserGuildApplyModel } from '../../../db/UserGuildApply'; import { hasStructureConsume, getStructureConsume, gameData } from '../../../pubUtils/data'; import { GuildRecModel } from '../../../db/GuildRec'; import { sendMail } from '../../../services/mailService'; -import { existsRank, initSingleRankWithServer, getRank, setRank, redisUserInfoUpdate, removeFromRank, getMyRank, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService'; +import { updateUserInfo, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService'; import { openGuildRefine } from '../../../services/guildRefineService'; import { unlockTrain } from '../../../services/guildTrainService'; import { removeBossRank } from '../../../services/guildBossService'; import { removeTrainRank } from '../../../services/guildTrainService'; import { pushGuildNoticeUpdateMsg, pushGuildUpStructureMsg, addRoleToGuildChannel, getGuildChannelSid } from '../../../services/chatService'; +import { Rank } from '../../../services/rankService'; export default function (app: Application) { return new GuildHandler(app); } @@ -71,10 +72,9 @@ export class GuildHandler { await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 // 加入排行 - let params = new GuildRankParam(guild.icon, guild.name, guild.lv, guild.leader, guild.memberCnt); - await setRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code, 0, Date.now(), params); - - let rank = await getMyRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); + await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild); + let rank = await r.getMyRank(guild.code); // 加入channel session.set('guildCode', guild.code); @@ -134,7 +134,7 @@ export class GuildHandler { let chatSid = await getGuildChannelSid(code); this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { name, notice, introduce, ceLimit, isAuto }); - await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]); if (notice) { pushGuildNoticeUpdateMsg(roleId, roleName, guild); } @@ -216,7 +216,7 @@ export class GuildHandler { if(auth == GUILD_AUTH.LEADER) { // 转让团长 updateObject['leader'] = role._id; await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}); // 自己降权限 - await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(role) } ]); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(role) } ]); } guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader @@ -279,7 +279,8 @@ export class GuildHandler { } // 获取排行榜 - const rank = await getMyRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + const rank = await r.getMyRank(guild.code); // 返回 const result = { hasGuild: true, ...guild, leader: { ...leader, isOnline: leaderIsOnline }, rank, myInfo: {...userGuild }}; @@ -604,7 +605,8 @@ export class GuildHandler { let chatSid = await getGuildChannelSid(code); this.app.rpc.chat.guildRemote.dismiss.toServer(chatSid,code); - await removeFromRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); + await r.removeFromRank(code); return resResult(STATUS.SUCCESS, { code, status: guild.status }); } @@ -742,7 +744,7 @@ export class GuildHandler { await sendMail(MAIL_TYPE.GUILD_BE_IMPEACH, leaderRoleId, roleName, [guild.name]); await sendMail(MAIL_TYPE.GUILD_BE_SET_LEADER, topUser.roleId, roleName, [guild.name]); - await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(topUser) } ]); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(topUser) } ]); let isOnline = await isRoleOnline(topUser.roleId); const leader = { ...topUser, ce: topUser.ce, isOnline } @@ -793,7 +795,7 @@ export class GuildHandler { // 修改信息 let chatSid = await getGuildChannelSid(code); this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid,code, { ...result }); - await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, code, [{field: 'lv', value: result.lv } ]); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'lv', value: result.lv } ]); // 添加动态 const structureName = GUILD_STRUCTURE_NAME.get(id); @@ -915,17 +917,12 @@ export class GuildHandler { // 检查权限 const checkResult = await checkAuth(GUILD_OPERATE.GET_ACTIVE_RANK, roleId); if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - const hasRank = await existsRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - if(!hasRank) await initSingleRankWithServer(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - - let {ranks, myRank} = await getRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, myUserGuild.guildCode); + + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + let { ranks, myRank } = await r.getRankListWithMyRank(myUserGuild.guildCode); if(!myRank) { let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly'); - let {icon, name, lv, leader, activeWeekly, memberCnt} = guild; - let _leader = leader; - let param = new GuildRankParam(icon, name, lv, _leader, memberCnt); - myRank = {...param, num: activeWeekly, rank: 0}; + myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); } return resResult(STATUS.SUCCESS, { ranks, myRank }); diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index ac20126e1..877a1ae6c 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -8,7 +8,6 @@ import { resResult, genCode } from '../../../pubUtils/util'; import { PvpDefenseModel, OppPlayers } from '../../../db/PvpDefense'; import { pvpEndParamInter } from '../../../pubUtils/interface'; -import { RankParam } from '../../../domain/rank'; import { PlayerDetail, PlayerDetailHero } from '../../../domain/battleField/guild'; import { PVP_HERO_POS, PVP_HERO_ORDER, REDIS_KEY, LINEUP_NUM } from '../../../consts'; import { PVP } from '../../../pubUtils/dicParam'; @@ -17,13 +16,13 @@ import { HeroModel } from '../../../db/Hero'; import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { PvpRecordModel } from '../../../db/PvpRecord'; -import { existsRank, getRank, setRank, getMyRank, initSingleRankWithServer } from '../../../services/redisService'; import { handleCost } from '../../../services/rewardService'; -import { nowSeconds } from '../../../pubUtils/timeUtil'; +import { nowSeconds, getSeconds } from '../../../pubUtils/timeUtil'; import { setPvpSeasonResult, resetPvpWarId, resetPvpSeasonTime } from '../../../services/timeTaskService'; import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult'; import { PvpHistoryOppModel, PvpHistoryOppType } from '../../../db/PvpHistoryOpp'; import { SystemConfigModel } from '../../../db/SystemConfig'; +import { Rank } from '../../../services/rankService'; export default function(app: Application) { return new PvpHandler(app); @@ -62,8 +61,8 @@ export class PvpHandler { const role = await RoleModel.findByRoleId(roleId); // 加入排行榜 - let params = new RankParam(roleName, role.lv, role.vLv, role.head, role.frame, role.spine, role.title); - await setRank(REDIS_KEY.PVP_RANK, 0, roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params); + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); return resResult(STATUS.SUCCESS, {score, hisScore, heroScores}); } @@ -118,7 +117,8 @@ export class PvpHandler { } } - let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId);//去redis中获取排名 + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + let myRank = await r.getMyRank(roleId);//去redis中获取排名 let data:any = {warId, seasonNum, seasonEndTime, myRank, oppPlayers, heroes: heroes.map(cur => { let {actorId, dataId, order} = cur; @@ -284,9 +284,9 @@ export class PvpHandler { let result = await getEnemies(pvpDefense.oppPlayers, pvpDefense.winStreakNum); // 加入排行榜 - let params = new RankParam(roleName, role.lv, role.vLv, role.head, role.frame, role.spine,role.title); - await setRank(REDIS_KEY.PVP_RANK, 0, roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params); - let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId); + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); + let myRank = await r.getMyRank(roleId); return resResult(STATUS.SUCCESS, { battleCode, isSuccess, @@ -387,24 +387,17 @@ export class PvpHandler { async getRank(msg: {}, session: BackendSession) { let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId') - const hasRank = await existsRank(REDIS_KEY.PVP_RANK, serverId); - if(!hasRank) await initSingleRankWithServer(REDIS_KEY.PVP_RANK, serverId); - - let {ranks, myRank} = await getRank(REDIS_KEY.PVP_RANK, 0, roleId); + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + let {ranks, myRank} = await r.getRankListWithMyRank(roleId); + if(!myRank) { let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - let role = await RoleModel.findByRoleId(roleId); - let { lv, vLv, head, frame, spine, title} = role; - let rankRank = new RankParam(roleName, lv, vLv, head, frame, spine, title); - myRank = { - rank: 0, roleId, ...rankRank, num: pvpDefense.score, str: '' - } + + myRank = await r.generMyRankWithRole(roleId, pvpDefense.score, getSeconds(pvpDefense.refOppTime)); } - return resResult(STATUS.SUCCESS, { ranks: ranks.slice(0, 100), myRank }); + return resResult(STATUS.SUCCESS, { ranks, myRank }); } async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { @@ -448,7 +441,8 @@ export class PvpHandler { }); } heroes.sort((a, b) => b.score - a.score); - let rank = await getMyRank(REDIS_KEY.PVP_RANK, 0, oppoRoleId);//去redis中获取排名 + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + let rank = await r.getMyRank(oppoRoleId);//去redis中获取排名 result = new PlayerDetail({...role, ...pvpDefense, heroes, rank}); } diff --git a/game-server/app/servers/battle/handler/towerBattleHandler.ts b/game-server/app/servers/battle/handler/towerBattleHandler.ts index 4c4a0db49..eaba107df 100644 --- a/game-server/app/servers/battle/handler/towerBattleHandler.ts +++ b/game-server/app/servers/battle/handler/towerBattleHandler.ts @@ -11,9 +11,8 @@ import { decodeArrayStr, resResult, shouldRefresh, calculateNum, getRefTime, gen import { calcuHangUpReward, checkTaskConditions, checkHangUpSpdUpCnt, createCurTasks, treatTask, getRemainTime, getTasksReward, getTaskStatus, getDoingOrWaitingTasks } from '../../../services/battleService'; import { handleFixedReward, addItems, handleCost } from '../../../services/rewardService'; import { checkBattleHeroes } from '../../../services/normalBattleService'; -import { getRank, setRank, existsRank, initSingleRankWithServer } from '../../../services/redisService'; -import { RankParam } from '../../../domain/rank'; import { getGoldObject } from '../../../pubUtils/itemUtils'; +import { Rank } from '../../../services/rankService'; export default function(app: Application) { return new TowerBattleHandler(app); @@ -35,10 +34,8 @@ export class TowerBattleHandler { towerLv = 1; let role = await RoleModel.towerLvUp(roleId); // 更新redis - let { roleName, towerUpTime, lv, vLv, head, frame, spine, title } = role; - let rankRank = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await setRank(REDIS_KEY.TOWER_RANK, serverId, roleId, towerLv, towerUpTime.getTime(), rankRank); - + let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, towerLv, role.towerUpTime.getTime(), role); } let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv); if (!towerRec) { @@ -310,24 +307,4 @@ export class TowerBattleHandler { let costGold = TOWER_TASK_CONST.COST_GOLD; return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold }); } - - async getTowerRank(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId') - - const hasTowerRank = await existsRank(REDIS_KEY.TOWER_RANK, serverId); - if(!hasTowerRank) await initSingleRankWithServer(REDIS_KEY.TOWER_RANK, serverId); - - let {ranks, myRank} = await getRank(REDIS_KEY.TOWER_RANK, serverId, roleId); - if(!myRank) { - let role = await RoleModel.findByRoleId(roleId); - let {towerLv, lv, vLv, head, frame, spine } = role; - myRank = { - rank: 0, roleId, roleName, lv, vLv,guildName: "", head, frame, spine, num: towerLv, str: '' - } - } - - return resResult(STATUS.SUCCESS, { ranks, myRank }); - } } diff --git a/game-server/app/servers/guild/handler/cityActivityHandler.ts b/game-server/app/servers/guild/handler/cityActivityHandler.ts index 4f3d7bf13..1f0f31a7d 100644 --- a/game-server/app/servers/guild/handler/cityActivityHandler.ts +++ b/game-server/app/servers/guild/handler/cityActivityHandler.ts @@ -12,11 +12,8 @@ import { nowSeconds, getBeforeSeconds } from "../../../pubUtils/timeUtil"; import { getGoldObject } from "../../../pubUtils/itemUtils"; import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; import { handleCost } from "../../../services/rewardService"; -import { getRankScore, getCityKeyName, getGuildKeyName, setUserGuildActivityRank, setRank } from "../../../services/redisService"; -import { RoleModel, RoleType } from "../../../db/Role"; -import { RankParam, GuildRankParam } from "../../../domain/rank"; -import { GuildModel } from "../../../db/Guild"; import { addActive } from "../../../services/guildService"; +import { Rank } from "../../../services/rankService"; export default function (app: Application) { return new CityActivityHandler(app); @@ -188,8 +185,9 @@ export class CityActivityHandler { // 更新公会参与的玩家 obj.pushMembers(guildCode, roleId, userGuild.job); - // // 返回当前军团总军功 - let guildScore = await getRankScore(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, guildCode); + // 返回当前军团总军功 + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true); + let guildScore = await r.getMyScore(guildCode); const dbCities = await GuildActivityCityModel.getAllCities(serverId); let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity, dbCities); @@ -234,16 +232,12 @@ export class CityActivityHandler { if(!pushResult) return resResult(STATUS.WRONG_PARMS); // 更新redis数据 - let role = await RoleModel.findByRoleId(roleId); - let { lv, vLv, head, frame, spine, title } = role; - let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); - let myScore = await setUserGuildActivityRank(REDIS_KEY.USER_CITY_ACTIVITY, guildCode, serverId, roleId, damage, Date.now(), userParam); + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }); + let myScore = await myR.setRankWithRoleInfo(roleId, damage, Date.now(), null, false, true); + + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true ); + let guildScore = await r.setRankWithGuildInfo(guildCode, damage, Date.now(), null, true); - let guild = await GuildModel.findByCode(guildCode, serverId); - let leader = guild.leader; - let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader, guild.memberCnt); - let guildScore = await setRank(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, guild.code, damage, Date.now(), params, true); - gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp, -1 * damage); if(gateHp <= 0) { // 推送 停止活动并结算奖励 @@ -286,8 +280,10 @@ export class CityActivityHandler { // 发放活跃 await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 // 返回当前军团总军功 - let guildScore = await getRankScore(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, guildCode); - let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode), serverId, roleId, true); + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }); + let myScore = await myR.getMyScore(roleId); + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true); + let guildScore = await r.getMyScore(guildCode); let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); return resResult(STATUS.SUCCESS, { diff --git a/game-server/app/servers/guild/handler/gateActivityHandler.ts b/game-server/app/servers/guild/handler/gateActivityHandler.ts index 1fbe0a593..e672d6e90 100644 --- a/game-server/app/servers/guild/handler/gateActivityHandler.ts +++ b/game-server/app/servers/guild/handler/gateActivityHandler.ts @@ -5,16 +5,14 @@ import { STATUS, GUILD_ACTIVITY_TYPE, GUILD_POINT_WAYS, ENEMIES_TYPE, GET_POINT_ import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; -import { RoleModel, RoleType } from "../../../db/Role"; -import { GuildModel } from "../../../db/Guild"; -import { RankParam, GuildRankParam } from "../../../domain/rank"; -import { setRank, getGuildKeyName, getRankScore, setUserGuildActivityRank, delGuildActivityRank } from "../../../services/redisService"; +import { delGuildActivityRank } from "../../../services/redisService"; import { REDIS_KEY } from "../../../consts"; import { addActive } from "../../../services/guildService"; import { gameData } from "../../../pubUtils/data"; import { getGuildChannelSid } from "../../../services/chatService"; import { UserGuildModel } from "../../../db/UserGuild"; import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; +import { Rank } from "../../../services/rankService"; export default function (app: Application) { return new GateActivityHandler(app); @@ -96,7 +94,8 @@ export class GateActivityHandler { obj.pushMembers(guildCode, serverId, roleId, userGuild.job); // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + let guildScore = await r.getMyScore(guildCode); // 前一天中位数战力 let medianCe = await getMedianCe(serverId); @@ -138,16 +137,12 @@ export class GateActivityHandler { obj.setMemberRecord(code, newMemberRecord); // 更新redis数据 - let role = await RoleModel.findByRoleId(roleId); - let { lv, vLv, head, frame, spine, title } = role; - let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); - let myScore = await setUserGuildActivityRank(REDIS_KEY.USER_GATE_ACTIVITY, guildCode, serverId, roleId, score, Date.now(), userParam); + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }, false); + let myScore = await myR.setRankWithRoleInfo(roleId, score, Date.now(), null, false, true); + + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + let guildScore = await r.setRankWithGuildInfo(guildCode, score, Date.now(), null, true); - let guild = await GuildModel.findByCode(guildCode, serverId); - let leader = guild.leader; - let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader, guild.memberCnt); - let guildScore = await setRank(REDIS_KEY.GATE_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); - // 更新数据库 let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords, round); @@ -186,8 +181,10 @@ export class GateActivityHandler { pinus.app.rpc.chat.guildRemote.pushGateHp.toServer(chatSid, guildCode, gateHp); // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); - let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId, true); + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); + let myScore = await myR.getMyScore(roleId); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + let guildScore = await r.getMyScore(guildCode); return resResult(STATUS.SUCCESS, { code, @@ -228,25 +225,21 @@ export class GateActivityHandler { } } + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); if(isSuccess) { let score = gameData.gateActivityPoint.get(GET_POINT_WAYS.DEFENSE_SUCCESS); // 更新redis数据 - let role = await RoleModel.findByRoleId(roleId); - let { lv, vLv, head, frame, spine, title } = role; - let userParam = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await setUserGuildActivityRank(REDIS_KEY.USER_GATE_ACTIVITY, guildCode, serverId, roleId, score, Date.now(), userParam); + await myR.setRank(roleId, score, Date.now(), true); - let guild = await GuildModel.findByCode(guildCode, serverId); - let leader = guild.leader; - let params = new GuildRankParam(guild.icon, guild.name, guild.lv, leader, guild.memberCnt); - await setRank(REDIS_KEY.GATE_ACTIVITY, serverId, guild.code, score, Date.now(), params, true); + await r.setRank(guildCode, score, Date.now(), true); } // 发放活跃 await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 // 返回当前军团总军功 - let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); - let myScore = await getRankScore(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, roleId, true); + let guildScore = await r.getMyScore(guildCode); + let myScore = await r.getMyScore(roleId); let gateHp = obj.getGateHpAndInc(guildCode); obj.delMemberRecord(code); @@ -353,17 +346,7 @@ export class GateActivityHandler { async debugDelRedis(msg: { aid: number }, session: BackendSession) { let { aid } = msg; - - let map = new Map(); - let guilds = await GuildModel.findAllGuild('serverId code'); - for(let { serverId, code } of guilds) { - if(map.has(serverId)) { - map.get(serverId).push(code); - } else { - map.set(serverId, [code]); - } - } - await delGuildActivityRank(aid, map); + await delGuildActivityRank(aid); } // ! 测试接口 将自己添加进活动roleId里 diff --git a/game-server/app/servers/guild/handler/raceActivityHandler.ts b/game-server/app/servers/guild/handler/raceActivityHandler.ts index b0db6d4a3..0762eaf41 100644 --- a/game-server/app/servers/guild/handler/raceActivityHandler.ts +++ b/game-server/app/servers/guild/handler/raceActivityHandler.ts @@ -6,7 +6,7 @@ import { UserGuildModel } from "../../../db/UserGuild"; import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; import { addActive } from "../../../services/guildService"; -import { getMyUnionRank } from "../../../services/redisService"; +import { Rank } from "../../../services/rankService"; export default function (app: Application) { return new RaceActivityHandler(app); @@ -170,7 +170,8 @@ export class RaceActivityHandler { // 发放活跃 await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 // 返回当前军团总军功 - let myGuildRank = await getMyUnionRank(REDIS_KEY.RACE_ACTIVITY, serverId, guildCode); + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }); + let myGuildRank = await r.getMyRank(guildCode); return resResult(STATUS.SUCCESS, { timestamp: Date.now(), diff --git a/game-server/app/servers/role/handler/friendHandler.ts b/game-server/app/servers/role/handler/friendHandler.ts index 1649fd098..a2d9cbcee 100644 --- a/game-server/app/servers/role/handler/friendHandler.ts +++ b/game-server/app/servers/role/handler/friendHandler.ts @@ -7,7 +7,7 @@ import { FriendApplyModel } from "../../../db/FriendApply"; import { FriendApplyParams, FriendListParam, FriendRecommendParams, BlackListParam, FriendValueListParam } from "../../../domain/roleField/friend"; import { FriendShipModel, FriendShipType } from "../../../db/FriendShip"; import { FriendRelationModel, Relation } from "../../../db/FriendRelation"; -import { isRoleOnline, getServerName, getMyRank, getRoleOnlineInfo } from "../../../services/redisService"; +import { isRoleOnline, getServerName, getRoleOnlineInfo } from "../../../services/redisService"; import { increaseFrdCnt, getRecommendType, sortByBeSentHeart } from "../../../services/friendService"; import { FriendPointModel } from "../../../db/FriendPoint"; import { gameData } from "../../../pubUtils/data"; @@ -21,6 +21,7 @@ import { getPlayerMainAttribute } from "../../../services/pvpService"; import { FRIEND } from "../../../pubUtils/dicParam"; import { PlayerDetail, PlayerDetailHero } from "../../../domain/battleField/guild"; import { createPrivateMsg, pushMsgToRole, pushPresent } from "../../../services/chatService"; +import { Rank } from "../../../services/rankService"; export default function (app: Application) { @@ -686,7 +687,8 @@ export class FriendHandler { } } - let rank = await getMyRank(REDIS_KEY.PVP_RANK, 0, oppoRoleId);//去redis中获取排名 + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + let rank = await r.getMyRank(oppoRoleId);//去redis中获取排名 result = new PlayerDetail({...role, defCe: topLineupCe, heroes}); result.setWarStar(role.warStar, rank, towerLv); diff --git a/game-server/app/servers/role/handler/rankHandler.ts b/game-server/app/servers/role/handler/rankHandler.ts index 6da1d4880..812ea7d46 100644 --- a/game-server/app/servers/role/handler/rankHandler.ts +++ b/game-server/app/servers/role/handler/rankHandler.ts @@ -3,11 +3,12 @@ import { resResult, aesEncryptcfb } from "../../../pubUtils/util"; import { STATUS, REDIS_KEY, ENCRYPT_KEY, ENCRYPT_IV } from "../../../consts"; import { RoleModel, RoleType } from "../../../db/Role"; import { UserGuildModel } from "../../../db/UserGuild"; -import { existsRank, initSingleRankWithServer, getRank } from "../../../services/redisService"; import { GuildModel } from "../../../db/Guild"; import { GuildRankParam } from "../../../domain/rank"; import { HeroModel } from "../../../db/Hero"; import { UserModel } from "../../../db/User"; +import { Rank } from "../../../services/rankService"; +import { redisClient } from "../../../services/redisService"; export default function (app: Application) { return new RoleHandler(app); @@ -89,16 +90,11 @@ export class RoleHandler { const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode'); if (!myUserGuild) return resResult(STATUS.GUILD_NOT_FOUND); - const hasRank = await existsRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - if (!hasRank) await initSingleRankWithServer(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - - let { ranks, myRank } = await getRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, myUserGuild.guildCode); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + let { ranks, myRank } = await r.getRankListWithMyRank(myUserGuild.guildCode,); if (!myRank) { let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly memberCnt'); - let { icon, name, lv, leader, activeWeekly, memberCnt } = guild; - let _leader = leader; - let param = new GuildRankParam(icon, name, lv, _leader, memberCnt); - myRank = { ...param, num: activeWeekly, rank: 0 }; + myRank = await r.generMyRankWithGuild(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); } return resResult(STATUS.SUCCESS, { type, ranks, myRank }); @@ -144,4 +140,5 @@ export class RoleHandler { goods: [] }) } + } \ No newline at end of file diff --git a/game-server/app/services/battleService.ts b/game-server/app/services/battleService.ts index 39c0e9d4a..567f03282 100644 --- a/game-server/app/services/battleService.ts +++ b/game-server/app/services/battleService.ts @@ -10,9 +10,8 @@ import { decodeArrayStr, shouldRefresh, resResult, decodeStr, cal, getRandomWith import { STATUS } from '../consts/statusCode'; import { HangUpSpdUpRecModel } from '../db/HangUpSpdUpRec'; import { TowerTaskRecModel } from '../db/TowerTaskRec'; -import { setRank } from './redisService'; -import { RankParam } from '../domain/rank'; import { cloneDeep } from 'lodash'; +import { Rank } from './rankService'; export async function checkTowerWar(roleId: string, battleId: number, heroes: Array) { const battleIdStr = `${battleId}`; @@ -73,9 +72,8 @@ export async function towerBattleEnd(sid: string, roleId: string, serverId: numb if (inc === 1) { let role = await RoleModel.towerLvUp(roleId); // 更新redis - let { roleName, towerLv, towerUpTime, lv, vLv, head, frame, spine, title } = role; - let rankRank = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await setRank(REDIS_KEY.TOWER_RANK, serverId, roleId, towerLv, towerUpTime.getTime(), rankRank); + let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, towerLv, role.towerUpTime.getTime(), role); const nextTowerInfo = getTowerDataByLv(towerLv + 1); if (nextTowerInfo) { diff --git a/game-server/app/services/guildActivityObjService.ts b/game-server/app/services/guildActivityObjService.ts index 3055218d3..b34c24013 100644 --- a/game-server/app/services/guildActivityObjService.ts +++ b/game-server/app/services/guildActivityObjService.ts @@ -6,12 +6,12 @@ import { GUILDACTIVITY } from "../pubUtils/dicParam"; import { RewardInter } from "../pubUtils/interface"; import { getRaceEventItems, gameData } from "../pubUtils/data"; import { GuildModel } from "../db/Guild"; -import { setRankWithoutUserInfo } from "./redisService"; import { sendSingleRaceActEndMsg } from "./guildActivityService"; import { REDIS_KEY, RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, RACE_EVENT, STATUS } from "../consts"; import { getGuildChannelSid } from "./chatService"; import { pinus } from "pinus"; import { getRandEelm, sortArrRandom, resResult } from "../pubUtils/util"; +import { Rank } from "./rankService"; export class GateActivityObject { private gateHp: Map = new Map(); // 城门血条,每个军团有一条血条 guildCode => hp @@ -265,7 +265,8 @@ export class RaceActivityObject { let events = this.events.get(guildCode)||[]; let needSendEnd = woodenHorse.calCurWoodenHorse(events); if(woodenHorse.status == 1 || woodenHorse.status == 2) { // 更新距离 // TODO 写进const表 - await setRankWithoutUserInfo(REDIS_KEY.RACE_ACTIVITY, serverId, guildCode, Math.floor(woodenHorse.distance * 1000), woodenHorse.time - woodenHorse.startTime, true, false, 6); + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6, 5); + await r.setRank(guildCode, Math.floor(woodenHorse.distance * 1000), woodenHorse.time - woodenHorse.startTime, false); if (needSendEnd) { // 抵达后发送奖励,发送消息,结算 await sendSingleRaceActEndMsg(guildCode, woodenHorse); } diff --git a/game-server/app/services/guildActivityService.ts b/game-server/app/services/guildActivityService.ts index 4deae3927..06cae7b65 100644 --- a/game-server/app/services/guildActivityService.ts +++ b/game-server/app/services/guildActivityService.ts @@ -8,9 +8,8 @@ import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, import { Record, UserGuildActivityRecModel } from "../db/UserGuildActivityRec"; import { GateMembersRec, CityParam, Member, WoodenHorse } from "../domain/battleField/guildActivity"; import { DicGuildActivity } from "../pubUtils/dictionary/DicGuildActivity"; -import { getUnionRank, getRank, getGuildKeyName, getMyUnionRank, getRankScore, getCityKeyName, getAllServers, getUnionRankRange } from "./redisService"; -import { GuildModel } from "../db/Guild"; -import { SimpleGuildRankParam, SimpleRoleRankParam, SimpleGuildRankWithTimeParam } from "../domain/rank"; +import { getAllServers } from "./redisService"; +import { SimpleGuildRankParam, SimpleRoleRankParam, SimpleGuildRankWithTimeParam, GuildRankInfo, RoleRankInfo } from "../domain/rank"; import { getGuildChannelSid, getWorldChannelSid, getCityChannelSid } from "./chatChannelService"; import { pinus } from "pinus"; import { GuildActivityRecordModel } from "../db/GuildActivityRec"; @@ -20,6 +19,7 @@ import { getHonourObject } from '../pubUtils/itemUtils'; import { GuildActivityCityType, GuildActivityCityModel } from "../db/GuildActivityCity"; import { DicCityActivity } from "../pubUtils/dictionary/DicCityActivity"; import { GateActivityObject, CityActivityObject, RaceActivityObject } from "./guildActivityObjService"; +import { Rank } from "./rankService"; let gateActivityObj: GateActivityObject; let cityActivityObj: CityActivityObject; @@ -153,37 +153,59 @@ export function getRecordScore(aid: number, round: number, record: { round: numb } export async function getGateActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { - let guildKey = REDIS_KEY.GATE_ACTIVITY; - let memberKey = getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode); - let rec = await getGuildActivityRank(guildKey, memberKey, guildCode, serverId, roleId, roleName); - return rec; + + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + r.setGenerFieldsFun(generGuildActivityRankField); + let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank(guildCode); + if(!myGuildRank) { + myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); + } + + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); + myR.setGenerFieldsFun(generGuildActivityMemberRankField); + let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank(roleId); + if(roleName && !myMemberRank) { + myMemberRank = await r.generMyRankWithRole(roleId, 0, 0); + } + + return { guildRank, myGuildRank, memberRank, myMemberRank } } export async function getCityActivityRank(guildCode: string, serverId: number, cityId: number, roleId?: string, roleName?: string) { - let guildKey = getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId); - let memberKey = getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode); - let rec = await getGuildActivityRank(guildKey, memberKey, guildCode, serverId, roleId, roleName); - return rec; + + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true); + r.setGenerFieldsFun(generGuildActivityRankField); + let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank(guildCode); + if(!myGuildRank) { + myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); + } + + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }); + myR.setGenerFieldsFun(generGuildActivityMemberRankField); + let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank(roleId); + if(roleName && !myMemberRank) { + myMemberRank = await r.generMyRankWithRole(roleId, 0, 0); + } + + return { guildRank, myGuildRank, memberRank, myMemberRank } } export async function getRaceActivityRank(guildCode: string, serverId: number) { - let guildKey = REDIS_KEY.RACE_ACTIVITY; + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6); + r.setGenerFieldsFun(generField); + let { myRank, ranks } = await r.getRankListWithMyRank(guildCode); + if(!myRank) { + myRank = await r.generMyRankWithGuild(guildCode, 0, 0); + } - let guildRankResult = await getUnionRank(guildKey, serverId, guildCode, 6); - let guildRank = new Array(); - for(let { rank, code, name, num, time } of guildRankResult.ranks) { - let param = new SimpleGuildRankWithTimeParam(rank, code, name, { distance: num/1000, time: time * 1000, startTime: 0, durability: 0 }); - guildRank.push(param); - } - let myGuildRank: SimpleGuildRankWithTimeParam; - if(guildRankResult.myRank) { - let { rank, code, name, num, time } = guildRankResult.myRank; - myGuildRank = new SimpleGuildRankWithTimeParam(rank, code, name, { distance: num/1000, time: time * 1000, startTime: 0, durability: 0 }); - } else { - let guild = await GuildModel.findByCode(guildCode, serverId, 'name'); - myGuildRank = new SimpleGuildRankWithTimeParam(0, guildCode, guild?.name, { distance: 0, time: 0, startTime: 0, durability: 0 }); - } - return { guildRank, myGuildRank } + return { guildRank: ranks, myGuildRank: myRank } +} + + +function generField(params: GuildRankInfo) { + let { rank, code, name, num, time } = params; + let param = new SimpleGuildRankWithTimeParam(rank, code, name, { distance: num/1000, time: time * 1000, startTime: 0, durability: 0 }); + return param; } /** @@ -192,12 +214,13 @@ export async function getRaceActivityRank(guildCode: string, serverId: number) { * @param serverId */ export async function getWoodenHorseList(guildCode: string, serverId: number) { - let guildKey = REDIS_KEY.RACE_ACTIVITY; let obj = getRaceActivityObj(); - let myRank = await getMyUnionRank(guildKey, serverId, guildCode); + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, {serverId}, true, 6, 5); + + let myRank = await r.getMyRank(guildCode); let startRank = myRank - 2 > 0? myRank - 2: 1; let endRank = startRank + 4; - let range = await getUnionRankRange(guildKey, serverId, startRank, endRank); + let range = await r.getRankByRange(startRank, endRank); let woodenHorseList = new Array(); for(let { code } of range) { let woodenHorse = await obj.getWoodenHorse(code, serverId); @@ -208,48 +231,14 @@ export async function getWoodenHorseList(guildCode: string, serverId: number) { return woodenHorseList; } +function generGuildActivityRankField(param: GuildRankInfo) { + let { rank, code, name, num } = param; + return new SimpleGuildRankParam(rank, code, name, num); +} -/** - * 获得军团活动排行榜 - * @param guildCode - * @param serverId - * @param roleId - * @param roleName - */ -export async function getGuildActivityRank(guildKey: string, memberKey: string, guildCode: string, serverId: number, roleId?: string, roleName?: string) { - - let guildRankResult = await getUnionRank(guildKey, serverId, guildCode); - let guildRank = new Array(); - for(let { rank, code, name, num } of guildRankResult.ranks) { - let param = new SimpleGuildRankParam(rank, code, name, num); - guildRank.push(param); - } - let myGuildRank: SimpleGuildRankParam; - if(guildRankResult.myRank) { - let { rank, code, name, num } = guildRankResult.myRank; - myGuildRank = new SimpleGuildRankParam(rank, code, name, num); - } else { - let guild = await GuildModel.findByCode(guildCode, serverId, 'name'); - myGuildRank = new SimpleGuildRankParam(0, guildCode, guild?.name, 0); - } - - let memberRankResult = await getRank(memberKey, serverId, roleId); - let memberRank = new Array(); - for(let { rank, roleId, roleName, num } of memberRankResult.ranks) { - let param = new SimpleRoleRankParam(rank, roleId, roleName, num); - memberRank.push(param) - } - let myMemberRank: SimpleRoleRankParam; - if(roleName) { - if(memberRankResult.myRank) { - let { rank, roleId, roleName, num } = memberRankResult.myRank; - myMemberRank = new SimpleRoleRankParam(rank, roleId, roleName, num); - } else { - myMemberRank = new SimpleRoleRankParam(0, roleId, roleName, 0); - } - } - - return { guildRank, myGuildRank, memberRank, myMemberRank } +function generGuildActivityMemberRankField(param: RoleRankInfo) { + let { rank, roleId, roleName, num } = param; + return new SimpleRoleRankParam(rank, roleId, roleName, num); } /** @@ -372,8 +361,9 @@ export async function gateActivitySettleReward(guildCode: string, serverId: numb let obj = getGateActivityObj(); let { gateHp, members } = obj.getObj(guildCode, serverId); - let rank = await getMyUnionRank(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); - let guildScore = await getRankScore(REDIS_KEY.GATE_ACTIVITY, serverId, guildCode); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + let rank = await r.getMyRank(guildCode); + let guildScore = await r.getMyScore(guildCode); let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank); @@ -387,8 +377,11 @@ export async function gateActivitySettleReward(guildCode: string, serverId: numb }); // 结算功勋等奖励 let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, ''); - for(let { rank, roleId, num: myScore } of memberRankResult.ranks) { + + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); + + let ranks = await myR.getRankByRange(); + for(let { rank, roleId, num: myScore } of ranks) { let honour = dic.honour + myScore * GUILDACTIVITY.GATEACTIVITY_HONOUR_RATIO; await updateUserRecAndSendHonour(honour, myScore, rank, roleId, members); } @@ -425,8 +418,9 @@ export async function cityActivitySettleReward(cityId: number, serverId: number) let gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp); let isSuccess = gateHp <= 0; // 血条未击破则没有占领军团 - let guildRankRsult = await getUnionRank(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, ''); - for(let { rank: guildRank, code: guildCode, name, num } of guildRankRsult.ranks) { + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true); + let ranks = await r.getRankByRange(); + for(let { rank: guildRank, code: guildCode, name, num } of ranks) { if(guildRank == 1) { if(isSuccess) { await GuildActivityCityModel.guard(serverId, cityId, guildCode, name); // 占领 @@ -449,9 +443,10 @@ export async function cityActivitySettleReward(cityId: number, serverId: number) await genAuction(guildCode, AUCTION_SOURCE.GATE, rec.code, serverId, rewards); let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let memberRankResult = await getRank(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId, ''); + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); + let ranks = await myR.getRankByRange(); let userRank = 0; - for(let { rank, roleId, num: myScore } of memberRankResult.ranks) { + for(let { rank, roleId, num: myScore } of ranks) { let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, rank); await updateUserRecAndSendHonour(honour, myScore, rank, roleId, members); userRank = rank; @@ -577,7 +572,14 @@ export async function calWoodenHorseAndSend(serverId: number) { console.log('calWoodenHorseAndSend'); let guildKey = REDIS_KEY.RACE_ACTIVITY; let obj = getRaceActivityObj(); - let { ranks } = await getUnionRank(guildKey, serverId, '', 6); + let fun = async function (param: GuildRankInfo) { + let { rank, code, name } = param; + let _obj = await obj.getWoodenHorse(code, serverId); + return new SimpleGuildRankWithTimeParam(rank, code, name, _obj); + } + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6); + r.setGenerFieldsFun(fun); + let ranks = await r.getRankByRange(); let map = new Map(); let guildRank = new Array(); @@ -650,10 +652,9 @@ export async function raceActivitySettleReward(guildCode: string, woodenHorse: W let { serverId, durability, distance } = woodenHorse; let obj = getRaceActivityObj(); // 计算排名,计算耐久,发送奖励 - let rank = await getMyUnionRank(REDIS_KEY.RACE_ACTIVITY, serverId, guildCode); - + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true); let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团 - let myGuildRank = await getMyUnionRank(REDIS_KEY.RACE_ACTIVITY, serverId, guildCode); + let myGuildRank = await r.getMyRank(guildCode); let members = obj.getMembersOfGuild(guildCode); let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, myGuildRank); @@ -670,7 +671,7 @@ export async function raceActivitySettleReward(guildCode: string, woodenHorse: W let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); let honour = dic.honour + Math.floor(durability * GUILDACTIVITY.RACEACTIVITY_DURABILITY_REWARD); for(let { roleId } of members) { - await updateUserRecAndSendHonour(honour, 0, rank, roleId, members); + await updateUserRecAndSendHonour(honour, 0, myGuildRank, roleId, members); } } diff --git a/game-server/app/services/guildService.ts b/game-server/app/services/guildService.ts index 6c3793fe5..2743bf219 100644 --- a/game-server/app/services/guildService.ts +++ b/game-server/app/services/guildService.ts @@ -10,7 +10,7 @@ import { nowSeconds } from "../pubUtils/timeUtil"; import { pinus, BackendSession } from "pinus"; import { ARMY } from "../pubUtils/dicParam"; import { sendMail } from "./mailService"; -import { setRank, getMyRank, initSingleRank, getRoleOnlineInfo, redisUserInfoUpdate } from "./redisService"; +import { initSingleRank, getRoleOnlineInfo, updateUserInfo } from "./redisService"; import { GuildRankParam, GuildLeader } from "../domain/rank"; import { lockData, lockDataNoRetry } from '../services/redLockService'; import { ErrLogModel } from '../db/ErrLog'; @@ -19,6 +19,7 @@ import { pushMail } from '../pubUtils/interface'; import { getMailContent } from '../services/mailService'; import { DATA_NAME } from '../consts/dataName'; import { addRoleToGuildChannel } from "./chatService"; +import { Rank } from "./rankService"; /** * @description 检查该玩家是否有权限做操作 @@ -71,7 +72,7 @@ export async function joinGuild(code: string, guildName: string, lv: number, rol res.releaseCallback();//解锁 return { status: -1, resResult: resResult(STATUS.GUILD_MEMBER_MAX) }; } else { - await redisUserInfoUpdate(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) } const role = await RoleModel.findByRoleId(roleId); @@ -175,8 +176,8 @@ export async function addActive(roleId: string, serverId: number, id: number, ty // 排行榜更新 let leader = await RoleModel.findById(guild.leader); - let guildRankParam = new GuildRankParam(guild.icon, guild.name, guild.lv, new GuildLeader(leader), guild.memberCnt); - await setRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, guild.code, guild.activeWeekly, guild.activeUpdateTime * 1000, guildRankParam); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime * 1000, guild); pinus.app.rpc.chat.guildRemote.updateInfo.toServer(CHAT_SERVER, guildCode, { activeDaily: guild.activeDaily, activeWeekly: guild.activeWeekly }); return { status: 1, guild, userGuild }; } @@ -265,7 +266,8 @@ export async function settleGuildWeekly() { } // 转换周活跃奖励 - let rank = await getMyRank(REDIS_KEY.GUILD_ACTIVE_RANK, serverId, code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + let rank = await r.getMyRank(code); let allWeeklyReward = getGuildActiveWeekReward(rank); for(let [roleId, job] of members) { let jobActiveRatio = gameData.guildPosition.get(job).activeRatio; diff --git a/game-server/app/services/normalBattleService.ts b/game-server/app/services/normalBattleService.ts index 6a90a7581..51f5f693f 100644 --- a/game-server/app/services/normalBattleService.ts +++ b/game-server/app/services/normalBattleService.ts @@ -2,7 +2,7 @@ import { HeroModel } from '../db/Hero'; import Role, { RoleModel } from '../db/Role' import { getLvByExp, getExpByLv, gameData } from '../pubUtils/data'; -import { redisUserInfoUpdate } from './redisService'; +import { updateUserInfo } from './redisService'; import { switchOnFunc } from './funcSwitchService'; import { FUNC_OPT_TYPE } from '../consts'; import { BackendSession } from 'pinus'; @@ -24,7 +24,7 @@ export async function roleLevelup(roleId: string, kingExp: number, session: Back role = await RoleModel.levelup(roleId, newLv, newExp); if(newLv > lv) { // 升级 await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session); - await redisUserInfoUpdate(REDIS_KEY.USER_INFO, roleId, [{field: 'lv', value: newLv}]) + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{field: 'lv', value: newLv}]) } let actordata = []; for(let i = lv; i <= newLv; i++) { diff --git a/game-server/app/services/pvpService.ts b/game-server/app/services/pvpService.ts index 9a251103a..d00c16934 100644 --- a/game-server/app/services/pvpService.ts +++ b/game-server/app/services/pvpService.ts @@ -1,25 +1,24 @@ import { PvpDefenseModel, Heroes, OppPlayers, PvpDefenseType, HeroScores, pvpUpdateInter } from '../db/PvpDefense'; -import { RoleType, RoleModel } from '../db/Role'; -import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY, PVP_CONST, HERO_CE_RATIO } from '../consts'; +import { RoleType } from '../db/Role'; +import { PVP_HERO_POS, REDIS_KEY, PVP_CONST } from '../consts'; import { setPvpDefResult } from '../services/timeTaskService'; import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; -import { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh, reduceCe, getChineseName } from '../pubUtils/util'; +import { getRandomIndexByLen, genCode, shouldRefresh, reduceCe, getChineseName } from '../pubUtils/util'; import { oppPlayersInter, pvpEndParamInter } from '../pubUtils/interface'; -import { RankParam } from '../domain/rank'; import { gameData, getPLvByScore } from "../pubUtils/data"; import { PVP } from '../pubUtils/dicParam'; import { SystemConfigModel } from '../db/SystemConfig' -import { setRank, getMyRank, getFieldByRank } from './redisService'; import { nowSeconds, checkTodayTime } from '../pubUtils/timeUtil'; import { HeroesRecord } from '../db/PvpRecord'; -import { HeroModel, HeroType } from '../db/Hero'; +import { HeroModel } from '../db/Hero'; import { MainAttrNumber, Attribute, CeAttrData, CeAttrDataRole } from '../domain/roleField/attribute'; import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral'; import { DicWarJson } from '../pubUtils/dictionary/DicWarJson'; import { findWhere, findIndex } from 'underscore'; import { pinus } from 'pinus'; import { PvpHistoryOppModel, PvpHistoryOppType } from '../db/PvpHistoryOpp'; +import { Rank } from './rankService'; export async function initPvpInfo(role: RoleType) { let heroes: Array = []; @@ -44,9 +43,8 @@ export async function initPvpInfo(role: RoleType) { let result = await PvpDefenseModel.createPvpDefense({ roleId: role.roleId, roleName: role.roleName, role: role._id, heroes, oppPlayers, defCe, seasonNum, challengeCnt }); //加入排行榜 - let { roleId, roleName, lv, vLv, head, frame,spine, title } = role; - let params = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await setRank(REDIS_KEY.PVP_RANK, 0, roleId, result.score, result.updatedAt.getTime(), params); + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + await r.setRankWithRoleInfo(REDIS_KEY.PVP_RANK, result.score, result.updatedAt.getTime(), role, false); return result; } @@ -114,13 +112,16 @@ export async function refreshEnemies(role: RoleType, score: number, pLv: number) export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayers[], mapWarJson: DicWarJson[], roleId: string, pos: number) { console.log('matchPlayerByRank', JSON.stringify(oppPlayers)) + let r = new Rank(REDIS_KEY.PVP_RANK, {}); let ridRanks = new Array(); // 已经被使用了的排名 for(let { roleId: curRoleId } of oppPlayers) { - let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, robotIdComBack(curRoleId)); + let rankLv = await r.getMyRank(robotIdComBack(curRoleId)); ridRanks.push(rankLv); } - console.log('ridRanks', pos, JSON.stringify(ridRanks)); - let myRank = await getMyRank(REDIS_KEY.PVP_RANK, 0, roleId); + + let myRank = await r.getMyRank(roleId); + ridRanks.push(myRank); + let oppRoleId = ''; let oppRank = 0; if(myRank == 1) { // 第一名 @@ -153,7 +154,7 @@ export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer } } } - let result = await getFieldByRank(REDIS_KEY.PVP_RANK, 0, oppRank); + let result = await r.getUserByRank(oppRank); if(result.length <= 0) return false; oppRoleId = result[0]; @@ -211,7 +212,8 @@ async function matchPlayer(seasonNum: number, oppPlayers: OppPlayers[], mapWarJs async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJson[], roleId: string, pos: number) { let { heroScores, heroes: defenseHeroes } = pvpdefense; let role = pvpdefense.role; - let rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, role.roleId); + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + let rankLv = await r.getMyRank(role.roleId); let dbHeroes = await HeroModel.findByRole(role.roleId, [{field: 'ce', sortBy: -1}]); let heroes = new Array(); let otherHeroes = new Array(); // 阵容外的所有武将信息 diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts new file mode 100644 index 000000000..e71adaaad --- /dev/null +++ b/game-server/app/services/rankService.ts @@ -0,0 +1,305 @@ +import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, GuildRankInfo, GuildLeader } from "../domain/rank"; +import { REDIS_RANK_TO_INFO, ROLE_SELECT, GUILD_SELECT, REDIS_KEY } from "../consts"; +import { redisClient, setUserInfo } from "./redisService"; +import { RoleType, RoleModel } from "../db/Role"; +import { GuildType, GuildModel } from "../db/Guild"; + +/** + * @description 排行榜相关操作 + * @export + * @class Rank + */ +export class Rank { + key: string; // 排行榜原始key + keyName: KeyName; // 拼接之后的key + infoKey: string; // 玩家数据key + isUnion: boolean; // 是否使用多个zset联合计算 + limit: number = 200; // 排行榜长度 + timelen: number = 10; // 给时间位留的长度 + unionRankLife: number = 10; + + constructor(key: string, keyParam: KeyNameParam, isUnion = false, timelen = 10, limit = 200) { + this.key = key; + this.keyName = new KeyName(key, keyParam); + this.infoKey = REDIS_RANK_TO_INFO.get(key); + this.isUnion = isUnion; + this.timelen = timelen; + this.limit = limit; + } + + private async generFields(obj: GuildRankInfo|RoleRankInfo) { + return obj; + } + + public setGenerFieldsFun(cb: (obj: GuildRankInfo|RoleRankInfo) => any) { + this.generFields = cb; + } + + // 合成的排行榜的生命时长 单位s + public setUnionRankLife(unionRankLife: number) { + this.unionRankLife = unionRankLife; + } + + public async existsRank() { + const result = await redisClient().existsAsync(this.keyName.getName()); + return result; + } + + public async setRankWithRoleInfo(roleId: string, score: number, timestamp: number, role?: RoleType, needReduceCe = false, isInc = true ) { + // 如果没有信息,更新玩家信息 + const hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); + if(!hasCurUser) { + if(!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + needReduceCe = true; + } + let param = new RankParam(role, needReduceCe); + await setUserInfo(this.infoKey, roleId, param); + } + let newScore = await this.setRank(roleId, score, timestamp, isInc); + + return newScore; + } + + public async setRankWithGuildInfo(guildCode: string, score: number, timestamp: number, guild?: GuildType, isInc = true) { + const hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); + if(!hasCurUser) { + if(!guild) { + guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK) + } + let param = new GuildRankParam(guild); + await setUserInfo(this.infoKey, guildCode, param); + } + let newScore = await this.setRank(guildCode, score, timestamp, isInc); + + return newScore; + } + + public async setRank(myId: string, score: number, timestamp: number, isInc = false) { + + // 更新分数 + let newScore = score; + if(this.isUnion) { + newScore = await this.updateRankScoreAtom(myId, score, timestamp, isInc); + } else { + newScore = await this.updateRankScoreEncode(myId, score, timestamp, isInc) + } + return newScore; + } + + /** + * @description 使用将score和time合成一个字段更新分数 + * @param myId + * @param score + * @param timestamp + */ + private async updateRankScoreEncode(myId: string, score: number, timestamp: number, isInc = false) { + let newScore = score; + let key = this.keyName.getName(); + if(isInc) { + let oldScore = await this.getMyScore(myId); + newScore = oldScore + score; + } + + let scoreStr = this.encodeScore(newScore, timestamp); + await redisClient().zaddAsync(key, scoreStr, myId); + return score + } + + /** + * @description 使用分两个zset更新redis中某field的值 + * @param myId + * @param score + * @param timestamp + * @param isInc + * @class Rank + */ + private async updateRankScoreAtom(myId: string, score: number, timestamp: number, isInc = false) { + let key = this.keyName.getName(); + let timeKey = this.keyName.getTimeName(); + + let pow = Math.pow(10, this.timelen + 1); + let newScore = 0; + // 分数zset + if(isInc) { + newScore = await redisClient().zincrbyAsync(key, score, myId); + } else { + newScore = await redisClient().zaddAsync(key, score, myId); + } + // 时间zset + await redisClient().zaddAsync(timeKey, pow - 1 - Math.floor(timestamp/1000), myId); + + return parseInt(newScore.toString()); + } + + /** + * @description 设置到期时间 + * @param time 到期时间,10位时间戳 + * @class Rank + */ + public async setExpire(time: number) { + let key = this.keyName.getName(); + let timeKey = this.keyName.getTimeName(); + + await redisClient().expireatAsync(key, time); + await redisClient().expireatAsync(timeKey, time); + } + + public async generMyRankWithRole(roleId: string, score: number, time: number, role?: RoleType, needReduceCe = false) { + // 如果没有信息,更新玩家信息 + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); + if(!hasCurUser) { + if(!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + needReduceCe = true; + } + let param = new RoleRankInfo(role, needReduceCe); + param.setInfo(0, roleId, score, time); + return await this.generFields(param); + } else { + const info = await redisClient().hgetAsync(this.infoKey, roleId); + const userInfo = JSON.parse(info); + + let param = new RoleRankInfo(userInfo); + param.setInfo(0, roleId, score, time); + return await this.generFields(param); + } + } + + public async generMyRankWithGuild(guildCode: string, score: number, time: number, guild?: GuildType) { + // 如果没有信息,更新玩家信息 + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); + if(!hasCurUser) { + if(!guild) { + guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); + } + let param = new GuildRankInfo(guild); + param.setInfo(0, guildCode, score, time); + return await this.generFields(param); + } else { + const info = await redisClient().hgetAsync(this.infoKey, guildCode); + const guildInfo = JSON.parse(info); + let param = new GuildRankInfo(guildInfo); + param.setInfo(0, guildCode, score, time); + return await this.generFields(param); + } + } + + public async getRankListWithMyRank(myId: string) { + let ranks = await this.getRankByRange(); + let newRanks = [], newMyRank; + let myRank = ranks.find(cur => { + return cur.isMyInfo(myId); + }); + if(this.generFields) { + for(let rank of ranks) { + let n = await this.generFields(rank); + newRanks.push(n); + } + if(myRank) { + newMyRank = await this.generFields(myRank); + } + } + + return { myRank: newMyRank, ranks: newRanks } + } + + public async getRankByRange(from: number|string = '+inf', to: number|string = '-inf') { + + let ranks = new Array(); + let key = this.keyName.getName(); + if(this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES", "LIMIT", 0, this.limit); + + for(let ii = 0; ii < rankFromDb.length; ii+=2) { + const myId = rankFromDb[ii]; + const { score, time } = this.decodeScore(rankFromDb[ii + 1]); + const info = await redisClient().hgetAsync(this.infoKey, myId); + const userInfo = JSON.parse(info); + + if(this.infoKey == REDIS_KEY.USER_INFO) { + let param = new RoleRankInfo(userInfo); + param.setInfo(Math.floor(ii/2)+1, myId, score, time); + ranks.push(param); + } else if(this.infoKey == REDIS_KEY.GUILD_INFO) { + let param = new GuildRankInfo(userInfo); + param.setInfo(Math.floor(ii/2)+1, myId, score, time); + ranks.push(param); + } + } + return ranks + } + + + // 获取我的排名 + public async getMyRank(myId: string) { + let key = this.keyName.getName(); + if(this.isUnion) { + key = await this.generateUnionRank(); + } + let myRank = await redisClient().zrevrankAsync(key, myId); + return myRank + 1; + } + + // 获取排名第几名的信息 + public async getUserByRank(rank: number) { + let key = this.keyName.getName(); + let myRank = await redisClient().zrevrangeAsync(key, rank - 1, rank - 1); + return myRank; + } + + + // 获取排名第几名的信息 + public async getMyScore(myId: string) { + let key = this.keyName.getName(); + let score = await redisClient().zscoreAsync(key, myId); + if(!score) score = 0; + if(!this.isUnion) { + let result = this.decodeScore(score.toString()); + score = result.score; + } + return parseInt(score.toString()); + } + + // 从排行榜中移除 + public async removeFromRank(myId: string) { + let key = this.keyName.getName(); + await redisClient().zremAsync(key, myId); + + return true; + } + + private async generateUnionRank() { + let unionKey = this.keyName.getUnionName(); // 联合的key + let existsKey = await redisClient().existsAsync(unionKey); + if(!existsKey) { + let originKey = this.keyName.getName(); + let timeKey = this.keyName.getTimeName(); + + let pow = Math.pow(10, this.timelen + 1); + await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1); + await redisClient().expireAsync(unionKey, this.unionRankLife); // 10秒更新一次 + } + return unionKey; + } + + // 有序排行综合时间和得分排序 + private encodeScore(score: number, timestamp: number) { + let timelen = this.timelen; + let pow = Math.pow(10, timelen + 1); + return score * pow + pow - 1 - Math.floor(timestamp/1000) + } + + private decodeScore(num: string) { + let timelen = this.timelen; + let pow = Math.pow(10, timelen + 1); + let _num = parseInt(num); + return { + time: pow - _num % pow, + score: Math.floor(_num/pow) + }; + } +} \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index e2455b567..19dea752d 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -10,22 +10,19 @@ import { SystemConfigModel } from '../db/SystemConfig'; import { GuildRankParam, GuildLeader, RankParam } from '../domain/rank'; import { GuildModel } from '../db/Guild'; import { comBtlRanges } from '../pubUtils/gamedata'; -import { getNextHourPoint } from '../pubUtils/timeUtil'; -import { gameData } from '../pubUtils/data'; +import { Rank } from './rankService'; /** * 在服务重新启动时,将信息存入redis */ export async function initAllRank() { - const client: Redis.RedisClient = redisClient(); const serverList = await GameModel.getAllServerList(); - await client.delAsync(REDIS_KEY.ONLINE_USERS); - await client.delAsync(REDIS_KEY.USER_INFO); - - await client.delAsync(REDIS_KEY.GUILD_INFO); - await client.delAsync(REDIS_KEY.PVP_RANK); + await delKeys(REDIS_KEY.ONLINE_USERS); + await delKeys(REDIS_KEY.USER_INFO); + await delKeys(REDIS_KEY.GUILD_INFO); + await delKeys(REDIS_KEY.PVP_RANK); + await delKeys(REDIS_KEY.TOWER_RANK); + await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK); for(let {id} of serverList) { - await client.delAsync(getKeyName(REDIS_KEY.TOWER_RANK, id)); - await client.delAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, id)); await initRank(id); } } @@ -37,14 +34,8 @@ export async function initAllRank() { */ export async function initRank(serverId: number) { // console.log('*****', 'initRank') - const client: Redis.RedisClient = redisClient(); - await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, serverId); - await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); - await client.expireAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), 30 * 24 * 60 * 60); - await client.expireAsync(REDIS_KEY.PVP_RANK, 30 * 24 * 60 * 60); - await client.expireAsync(REDIS_KEY.USER_INFO, 30 * 24 * 60 * 60); - await client.expireAsync(REDIS_KEY.GUILD_INFO, 30 * 24 * 60 * 60); - await client.expireAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), 30 * 24 * 60 * 60); + await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, {serverId}); + await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); } @@ -54,80 +45,48 @@ export async function initRank(serverId: number) { */ export async function initSingleRank(key: string) { - const serverList = await GameModel.getAllServerList(); - for(let {id} of serverList) { - await initSingleRankWithServer(key, id); - } -} + await delKeys(key); -/** - * 初始化某一服内的某一种排行榜 - * @param key redis key - */ -export async function initSingleRankWithServer(key: string, serverId: number) { - - await redisClient().delAsync(getKeyName(key, serverId)); - await setRankRedisFromDb(key, serverId); - await redisClient().expireAsync(key, 30 * 24 * 60 * 60); -} - -/** - * 从数据库内获取排行榜存入redis - * @param type 排行榜类型 - * @param serverId 分服 - */ -async function setRankRedisFromDb(type: string, serverId: number) { - if(type == REDIS_KEY.TOWER_RANK) { - let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv', 'head', 'frame', 'spine','title', 'updatedAt']); - for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime, head, frame, spine, title} of ranks) { - // console.log(roleId); - await redisClient().zaddAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId); - let rankPram = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); - } - } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { - let ranks = await GuildModel.getRank(serverId); - for(let { code, icon, name, lv, leader, activeWeekly = 0, activeUpdateTime = 0, memberCnt } of ranks) { - let _leader = leader; - let { roleName, title, head, frame, spine, lv: leaderLv } = _leader; - await redisClient().zaddAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), encodeScoreWithTime(activeWeekly, activeUpdateTime * 1000 ), code); - let rankParam = new GuildRankParam(icon, name, lv, { roleName, title, head, frame, spine, lv: leaderLv }, memberCnt); - await redisUserInfoAdd(REDIS_KEY.GUILD_INFO, code, rankParam); - } - } - -} - -// 排行榜是否存在 -export async function existsRank(key: string, serverId: number) { - const result = await redisClient().existsAsync(getKeyName(key, serverId)); - return result; -} - - -/** - * 获得redis key的名字 - * @param key REDIS_KEY中配置的key - * @param serverId 服务器id - * @param plus 后面再加 - */ -function getKeyName(key: string, serverId?: number, plus: string = '') { - let newKey = ''; - if(serverId) { - newKey = `${key}:${serverId}`; + if(key == REDIS_KEY.PVP_RANK) { + await setRankRedisFromDb(key, {}); } else { - newKey = key; + const serverList = await GameModel.getAllServerList(); + for(let { id } of serverList) { + await setRankRedisFromDb(key, { serverId: id }); + } } - - if(plus) { - newKey += `:${plus}`; - } - return newKey; } +/** + * debug接口使用,直接删除排行榜数据 + * @param params serverId => guildCodes + */ +export async function delGuildActivityRank(aid: number) { + if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + await delKeys(REDIS_KEY.USER_GATE_ACTIVITY); + await delKeys(REDIS_KEY.GATE_ACTIVITY); + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + await delKeys(REDIS_KEY.USER_CITY_ACTIVITY); + await delKeys(REDIS_KEY.CITY_ACTIVITY); + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + await delKeys(REDIS_KEY.RACE_ACTIVITY); + } +} -// 更新玩家信息 -export async function redisUserInfoUpdate(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader)}>) { +async function delKeys(key: string) { + let keys = await redisClient().keysAsync(`${key}*`); + for(let key of keys) { + await redisClient().delAsync(key); + } + return keys +} + +export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam) { + let value = JSON.stringify(params); + return await redisClient().hsetAsync(key, roleId, value); +} + +export async function updateUserInfo(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader)}>) { let params = await redisClient().hgetAsync(key, roleId); if(params) { let obj = JSON.parse(params); @@ -138,142 +97,43 @@ export async function redisUserInfoUpdate(key: string, roleId: string, arr: Arra } } -// 添加玩家信息缓存 -export async function redisUserInfoAdd(key: string, roleId: string, params: RankParam|GuildRankParam) { - let value = JSON.stringify(params); - return await redisClient().hsetAsync(key, roleId, value); -} +/********排行榜结束 */ /** - * 更新排行榜 - * @param key 配置在REDIS_KEY中的key - * @param serverId 区服id 如pvp这样跨服的,serverId传0 - * @param myId 玩家roleId或军团code - * @param score 得分 - * @param timestamp 时间 13位时间戳 - * @param params 玩家数据 - * @param isAtom 是否是原子性的更新 - * @param limit + * 从数据库内获取排行榜存入redis + * @param type 排行榜类型 + * @param serverId 分服 */ -export async function setRank(key: string, serverId: number, myId: string, score: number, timestamp: number, params: RankParam|GuildRankParam, isAtom = false, timelen = 10, limit = 100) { - - // 更新分数 - let newScore = score; - if(isAtom) { - newScore = await updateRankAtom(key, serverId, myId, score, timestamp, true, timelen); - } else { - const _score = encodeScoreWithTime(score, timestamp); - await redisClient().zaddAsync(getKeyName(key, serverId), _score, myId); - // 移除100名以外 - await redisClient().zremrangebyrankAsync(getKeyName(key, serverId), limit, 10000); - } +async function setRankRedisFromDb(type: string, args?: {serverId?: number}) { - let infoKey = REDIS_RANK_TO_INFO.get(key)||REDIS_KEY.USER_INFO; - // 如果没有信息,更新玩家信息 - const hasCurUser = await redisClient().hexistsAsync(infoKey, myId); - if(!hasCurUser) { - await redisUserInfoAdd(infoKey, myId, params); - } - return parseInt(newScore.toString()); -} - -export async function setRankWithoutUserInfo(key: string, serverId: number, myId: string, score: number, timestamp: number, isAtom = false, isInc = true, timelen=10, limit = 100) { - - let infoKey = REDIS_RANK_TO_INFO.get(key)||REDIS_KEY.USER_INFO; - // 如果没有信息,更新玩家信息 - const hasCurUser = await redisClient().hexistsAsync(infoKey, myId); - if(!hasCurUser) { - let guild = await GuildModel.findByCode(myId, serverId); - - let leader = guild.leader; - let guildRankParam = new GuildRankParam(guild.icon, guild.name, guild.lv, leader, guild.memberCnt); - await redisUserInfoAdd(infoKey, myId, guildRankParam); - } - - // 更新分数 - let newScore = score; - if(isAtom) { - newScore = await updateRankAtom(key, serverId, myId, score, timestamp, isInc, timelen); - } else { - const _score = encodeScoreWithTime(score, timestamp); - await redisClient().zaddAsync(getKeyName(key, serverId), _score, myId); - // 移除100名以外 - await redisClient().zremrangebyrankAsync(getKeyName(key, serverId), limit, 10000); - } - - return parseInt(newScore.toString()); -} - -// 获取排行榜 -export async function getRank(key: string, serverId: number, roleId: string, limit = 100) { - - let ranks = [], myRank = null; - const rankFromDb = await redisClient().zrevrangebyscoreAsync(getKeyName(key, serverId), '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); - - let _key = key.split(':')[0]; - let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; - - for(let ii = 0; ii < rankFromDb.length; ii+=2) { - const _roleId = rankFromDb[ii]; - const _score = decodeScoreWithTime(rankFromDb[ii + 1]); - const info = await redisClient().hgetAsync(infoKey, _roleId); - const _userInfo = JSON.parse(info); - const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; - if(infoKey == REDIS_KEY.USER_INFO) { - tmp["roleId"] = _roleId; - } else if(infoKey == REDIS_KEY.GUILD_INFO) { - tmp["code"] = _roleId; + if(type == REDIS_KEY.TOWER_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv', 'head', 'frame', 'spine','title', 'updatedAt']); + let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); + for(let role of ranks) { + // console.log(roleId); + await r.setRankWithRoleInfo(role.roleId, role.towerLv, role.towerUpTime?role.towerUpTime.getTime():0, role); + } + } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { + let serverId = args.serverId; + let ranks = await GuildModel.getRank(serverId); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + for(let guild of ranks) { + await r.setRankWithGuildInfo(guild.code, guild.activeWeekly, guild.activeUpdateTime * 1000, guild); + } + } else if ( type == REDIS_KEY.PVP_RANK) { + let { seasonNum } = await SystemConfigModel.findSystemConfig(); + console.log('execute season resetPvpRanks seasonNum = ' + seasonNum); + let ranks = await PvpDefenseModel.getRank(seasonNum);//获得全服前1000名的排名,加入到redis中 + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + for(let {roleId, role: _role, score, updatedAt } of ranks) { + let role = _role; + if (!role) { + continue; + } + await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role); } - ranks.push(tmp); - if(roleId == _roleId) myRank = tmp; } - return {ranks, myRank} -} - -// 获取我的排名 -export async function getMyRank(key: string, serverId: number, roleId: string) { - let myRank = await redisClient().zrevrankAsync(getKeyName(key, serverId), roleId); - - if(!myRank && myRank != 0) { - return 0 - } else { - return myRank + 1; - } -} - -// 获取排名第几名的信息 -export async function getFieldByRank(key: string, serverId: number, rank: number) { - let myRank = await redisClient().zrevrangeAsync(getKeyName(key, serverId), rank - 1, rank - 1); - return myRank; -} - -// 有序排行综合时间和得分排序 -function encodeScoreWithTime(score: number, timestamp: number): number { - // value = score * Math.power(10, 14) + max_time - timestamp - let timelen = 10; - let pow = Math.pow(10, timelen + 1); - return score * pow + pow - 1 - Math.floor(timestamp/1000) -} - -function decodeScoreWithTime(num: string, timelen: number = 10): number { - let pow = Math.pow(10, timelen + 1); - let _num = parseInt(num); - return Math.floor(_num/pow); -} - -function decodeTime(num: string, timelen: number = 10): number { - let pow = Math.pow(10, timelen + 1); - let _num = parseInt(num); - let time = _num % pow; - console.log(pow, time, _num); - return pow - time; -} - -// 从排行榜中移除 -export async function removeFromRank(key: string, serverId: number, myId: string) { - await redisClient().zremAsync(getKeyName(key, serverId), myId); - - return true; } /**************** 寻宝相关 start */ @@ -504,26 +364,6 @@ export async function getAllOnlineRoles() { return result; } -export async function resetPvpRanks() { - await redisClient().delAsync(REDIS_KEY.PVP_RANK); - let { seasonNum } = await SystemConfigModel.findSystemConfig(); - console.log('execute season resetPvpRanks seasonNum = ' + seasonNum); - let pvpRank = await PvpDefenseModel.getRank(seasonNum);//获得全服前1000名的排名,加入到redis中 - for(let {roleId, role: _role, score, updatedAt } of pvpRank) { - let role = _role; - if (!role) { - continue; - } - let { roleName, head, frame, spine, title, lv, vLv } = role; - await redisClient().zaddAsync(getKeyName(REDIS_KEY.PVP_RANK), encodeScoreWithTime(score, updatedAt?updatedAt.getTime():0), roleId); - - const hasCurUser = await redisClient().hexistsAsync(REDIS_KEY.USER_INFO, roleId); - if(!hasCurUser) { - let rankPram = new RankParam(roleName, lv, vLv, head, frame, spine, title); - await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); - } - } -} // 排行榜是否存在 export async function smembersAsync(key: string) { @@ -585,205 +425,9 @@ export async function getServerName(serverType: string, serverId: number) { return name } -function redisClient() { +export function redisClient() { const client: Redis.RedisClient = pinus.app.get('redis'); return client; } /**************** 数据库表end */ - -/**************** 军团活动排行 */ - -/** - * 更新排行榜(将得分和时间拆分开) - * @param key 配置在REDIS_KEY中的key - * @param serverId 区服id - * @param field 玩家id/军团id - * @param score 得分 - * @param time 事件 - */ -async function updateRankAtom(key: string, serverId: number, field: string, score: number, timestamp: number, isInc = true, timelen = 10) { - let originKey = getKeyName(key, serverId); - let timeKey = getKeyName(key, serverId, 'time'); - - let pow = Math.pow(10, timelen + 1); - let newScore = 0; - console.log('********', isInc, field, score, pow - 1 - Math.floor(timestamp/1000)); - if(isInc) { - newScore = await redisClient().zincrbyAsync(originKey, score, field); - } else { - newScore = await redisClient().zaddAsync(originKey, score, field); - } - await redisClient().zaddAsync(timeKey, pow - 1 - Math.floor(timestamp/1000), field); - - await redisClient().expireatAsync(originKey, getNextHourPoint(5)); - await redisClient().expireatAsync(timeKey, getNextHourPoint(5)); - - return newScore; -} - -async function generateUnionRank(key: string, serverId: number, timelen = 10) { - let unionKey = getKeyName(key, serverId, 'union'); // 联合的key - let existsKey = await redisClient().existsAsync(unionKey); - if(!existsKey) { - let originKey = getKeyName(key, serverId); - let timeKey = getKeyName(key, serverId, 'time'); - - let pow = Math.pow(10, timelen + 1); - await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1); - if(originKey.indexOf(REDIS_KEY.RACE_ACTIVITY) == -1) { - await redisClient().expireAsync(unionKey, 10); // 10秒更新一次 - } else { - await redisClient().expireAsync(unionKey, 1); // 1秒更新一次 - } - } - return unionKey; -} - -/** - * 使用updateRankAtom更新的排行榜,使用这个方法获取列表 - * @param key 配置在REDIS_KEY中的key - * @param serverId 区服id - * @param roleId 自己的id - */ -export async function getUnionRank(key: string, serverId: number, roleId: string, timelen = 10, limit = 100) { - - let ranks = [], myRank = null; - let unionKey = await generateUnionRank(key, serverId, timelen); - const rankFromDb = await redisClient().zrevrangebyscoreAsync(unionKey, '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); - - let _key = key.split(':')[0]; - console.log(_key) - let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; - - for(let ii = 0; ii < rankFromDb.length; ii+=2) { - const _roleId = rankFromDb[ii]; - const _score = decodeScoreWithTime(rankFromDb[ii + 1], timelen); - const _time = decodeTime(rankFromDb[ii + 1], timelen); - const info = await redisClient().hgetAsync(infoKey, _roleId); - const _userInfo = JSON.parse(info); - const tmp = {..._userInfo, num: _score, time: _time, rank: Math.floor(ii/2)+1}; - if(infoKey == REDIS_KEY.USER_INFO) { - tmp["roleId"] = _roleId; - } else if(infoKey == REDIS_KEY.GUILD_INFO) { - tmp["code"] = _roleId; - } - ranks.push(tmp); - if(roleId == _roleId) myRank = tmp; - } - return {ranks, myRank} -} - -/** - * 获取(分两个zset的)排行的一段排名内的数据 - * @param key 配置在REDIS_KEY中的key - * @param serverId 区服id - * @param startRank 开始排名 - * @param endRank 结束排名 - */ -export async function getUnionRankRange(key: string, serverId: number, startRank: number, endRank: number) { - let ranks = []; - - let unionKey = await generateUnionRank(key, serverId); - const rankFromDb = await redisClient().zrevrangeAsync(unionKey, startRank - 1, endRank - 1, "WITHSCORES"); - - let _key = key.split(':')[0]; - let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; - - for(let ii = 0; ii < rankFromDb.length; ii+=2) { - const _roleId = rankFromDb[ii]; - const _score = decodeScoreWithTime(rankFromDb[ii + 1]); - const info = await redisClient().hgetAsync(infoKey, _roleId); - const _userInfo = JSON.parse(info); - const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; - if(infoKey == REDIS_KEY.USER_INFO) { - tmp["roleId"] = _roleId; - } else if(infoKey == REDIS_KEY.GUILD_INFO) { - tmp["code"] = _roleId; - } - ranks.push(tmp); - } - return ranks -} - -// 获取我的排名 -export async function getMyUnionRank(key: string, serverId: number, roleId: string) { - let unionKey = await generateUnionRank(key, serverId); - let myRank = await redisClient().zrevrankAsync(unionKey, roleId); - return myRank + 1; -} - -/** - * 获取拼接得分的排行榜的某一个人的得分 - * @param key REDIS_KEY中配置的 - * @param serverId 分服 - * @param field 查询的人 - */ -export async function getRankScore(key: string, serverId: number, field: string, needDecode = false) { - let score = await redisClient().zscoreAsync(getKeyName(key, serverId), field); - if(!score) score = 0; - if(needDecode) { - score = decodeScoreWithTime(score.toString()); - } - return parseInt(score.toString()); -} - -export async function setUserGuildActivityRank(key: string, guildCode: string, serverId: number, roleId: string, score: number, time: number, userParam: RankParam) { - let nkey = getGuildKeyName(key, guildCode); - let oldScore = await getRankScore(nkey, serverId, roleId, true); - let nScore = await setRank(nkey, serverId, roleId, oldScore + score, time, userParam); - await redisClient().expireatAsync(getKeyName(nkey, serverId), getNextHourPoint(5)) - return nScore -} - -/** - * 按军团名拼接key - * @param key - * @param guildCode 军团编号 - */ -export function getGuildKeyName(key: string, guildCode: string) { - return `${key}:${guildCode}`; -} - -export function getCityKeyName(key: string, cityId: number) { - return `${key}:${cityId}`; -} - -/** - * debug接口使用,直接删除排行榜数据 - * @param params serverId => guildCodes - */ -export async function delGuildActivityRank(aid: number, params: Map) { - if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - for(let [serverId, guildCodes] of params) { - await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId)); - await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'time')); - await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'union')); - - for(let guildCode of guildCodes) { - await redisClient().delAsync(getKeyName(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId)); - } - } - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - let dicCity = gameData.cityActivity; - for(let [cityId] of dicCity) { - for(let [serverId, guildCodes] of params) { - await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId) , serverId)); - await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, 'time')); - await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, 'union')); - - for(let guildCode of guildCodes) { - await redisClient().delAsync(getKeyName(getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode), serverId)); - } - } - } - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - for(let [serverId] of params) { - await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId)); - await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId, 'time')); - await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId, 'union')); - } - } -} - -/**************** 军团活动排行end */ \ No newline at end of file diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index c381666b4..83f3a1056 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -7,9 +7,8 @@ import { nowSeconds, getTodayZeroPoint, getAge } from '../pubUtils/timeUtil'; import { getPvpGkWarIds, getPvpRankRewards, getPvpHeroRewards, getResultMaxRank, getTodayGuildActivity } from '../pubUtils/data'; import { deepCopy, getRandomArr, resResult } from '../pubUtils/util'; import { getLvByScore } from './pvpService'; -import { getMyRank, setRank, resetPvpRanks, getAllOnlineRoles, delGuildActivityRank, getAllServers } from './redisService'; +import { getAllOnlineRoles, getAllServers, initSingleRank, delGuildActivityRank } from './redisService'; import { MAIL_TYPE, REDIS_KEY, ADULT_AGE, GUEST_MAX_TIME, ADDICTION_PREVENTION_CODE, GUILD_ACTIVITY_STATUS, GUILD_ACTIVITY_TYPE } from '../consts'; -import { RankParam } from '../domain/rank'; import { RoleModel } from '../db/Role'; import { MailModel, MailType } from '../db/Mail'; import { pinus } from 'pinus'; @@ -25,6 +24,7 @@ import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity'; import { GuildModel } from '../db/Guild'; import { dispatch } from '../util/dispatcher'; +import { Rank } from './rankService'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -145,7 +145,8 @@ export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number, let pvpRankRewards = getPvpRankRewards(); let pvpHeroRewards = getPvpHeroRewards(); if (!rankLv) { - rankLv = await getMyRank(REDIS_KEY.PVP_RANK, 0, pvpDefense.roleId);// 获得排行榜排名 + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + rankLv = await r.getMyRank(pvpDefense.roleId);// 获得排行榜排名 } let oldPLv = getLvByScore(pvpDefense.heroScores);//结算前玩家的pvp等级 let { challengeCnt, challengeRefTime } = pvpDefense; @@ -202,9 +203,9 @@ export async function setPvpDefResult(pvpDefense: PvpDefenseType, seasonNum: num let rankLv = resultMaxRank.min; //最大排名挡位结算 let {score, pLv, heroScores, challengeCnt, challengeRefTime, rankGoods, heroGoods } = await checkResult(pvpDefense, seasonNum, oldSeasonEndTime, rankLv); pvpDefense = await PvpDefenseModel.updateInfoAndInclude(pvpDefense.roleId, {score, pLv, heroScores, seasonNum, challengeCnt, challengeRefTime}); - let { roleName, lv, vLv, head, frame, spine, title, roleId } = role; - let params = new RankParam(roleName, lv, vLv, head, frame, spine, title); - setRank(REDIS_KEY.PVP_RANK, 0, roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), params); + let { roleId } = role; + let r = new Rank(REDIS_KEY.PVP_RANK, {}); + r.setRankWithRoleInfo(pvpDefense.roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role, true); //下发邮件 if (!!rankGoods.length) await sendMail(MAIL_TYPE.PVP_RANK_REWARD, roleId, '系统', [JSON.stringify(seasonNum), '999+'], rankGoods, oldSeasonEndTime); @@ -285,6 +286,10 @@ export async function resetPvpSeasonTime(hour: number) { } +async function resetPvpRanks() { + await initSingleRank(REDIS_KEY.PVP_RANK); +} + export async function reportOnlineSchedule() { let allRoles = await getAllOnlineRoles(); console.log('reportOnlineSchedule all roles count: ', allRoles.length) @@ -345,17 +350,8 @@ export async function reportOneOnline(roleId: string, userCode: string, sid: str async function guildActivitySchedule() { /***********guildActivitySchedule***********/ - let dicGuildActivity = getTodayGuildActivity(); - let map = new Map(); - let guilds = await GuildModel.findAllGuild('serverId code'); - for(let { serverId, code } of guilds) { - if(map.has(serverId)) { - map.get(serverId).push(code); - } else { - map.set(serverId, [code]); - } - } - await delGuildActivityRank(dicGuildActivity.id, map); + let dicGuildActivity = getTodayGuildActivity(); + await delGuildActivityRank(dicGuildActivity.id); scheduleJob('guildActivityStart', `${dicGuildActivity.startSeconds} ${dicGuildActivity.startMinute} ${dicGuildActivity.startTime} * * ?`, guildActivityStartSchedule); diff --git a/game-server/config/redis.ts b/game-server/config/redis.ts index ef4c1b427..8b5d2de0a 100644 --- a/game-server/config/redis.ts +++ b/game-server/config/redis.ts @@ -8,6 +8,8 @@ declare module 'redis' { existsAsync(key: string): Promise; // 在 key 存在时删除 key。 delAsync(key: string): Promise; + // 在 key 存在时删除 key。 + keysAsync(pattern: string): Promise; // 设置过期时间 expireAsync(key: string, time: number): Promise; // 按时间戳设置过期时间 diff --git a/shared/consts/constModules/selectConst.ts b/shared/consts/constModules/selectConst.ts index 6fcca3252..0dbd7dc5d 100644 --- a/shared/consts/constModules/selectConst.ts +++ b/shared/consts/constModules/selectConst.ts @@ -12,7 +12,9 @@ export enum ROLE_SELECT { GET_ROLE_ID = 'roleId', GET_MY_SERVER = 'lv serverId userInfo.serverType', COM_BATTLE = 'lv head frame spine topLineupCe', - GET_HEADS = 'heads head frames frame spines spine' + GET_HEADS = 'heads head frames frame spines spine', + // 排行榜基础数据 + RANK = 'roleId roleName lv vLv head frame spine title guildName ce' }; export enum HERO_SELECT { @@ -36,7 +38,9 @@ export enum GUILD_SELECT { // 初始登录 ENTRY = 'guildCode lv memberCnt', // 获得邀请列表 - INVITED_MEMBER = '_id code isMemberMax +invitedMembers +inviteTime' + INVITED_MEMBER = '_id code isMemberMax +invitedMembers +inviteTime', + // 排行榜字段 + RANK = 'code name icon lv memberCnt leader' } export enum FRIEND_SHIP_SELECT { diff --git a/shared/db/Role.ts b/shared/db/Role.ts index 85e3af906..ac084de54 100644 --- a/shared/db/Role.ts +++ b/shared/db/Role.ts @@ -315,7 +315,7 @@ export default class Role extends BaseModel { } public static async towerLvUp(roleId: string) { - let role: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$inc: {towerLv: 1}, towerUpTime: new Date()}, {new: true}).lean({ virtuals: true }); + let role: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$inc: {towerLv: 1}, towerUpTime: new Date()}, {new: true}).lean({ getters: true, virtuals: true }); return role; } diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index 9b159c26f..bb191c803 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -1,5 +1,9 @@ import { EXTERIOR } from "../pubUtils/dicParam"; import { WoodenHorse } from "./battleField/guildActivity"; +import { RoleUpdate, RoleType } from "../db/Role"; +import { reduceCe } from "../pubUtils/util"; +import { GuildUpdateParam } from "../db/Guild"; +import { currentId } from "async_hooks"; // 排行榜返回玩家值 export class RankParam { @@ -11,15 +15,40 @@ export class RankParam { frame: number = EXTERIOR.EXTERIOR_FACECASE; spine: number = EXTERIOR.EXTERIOR_APPEARANCE; title: number; + ce: number; - constructor(roleName: string, lv: number, vLv: number, head: number, frame: number, spine: number, title: number) { - this.roleName = roleName; - this.lv = lv; - this.vLv = vLv; - this.head = head; - this.frame = frame; - this.spine = spine; - this.title = title; + constructor(role: RoleUpdate, needReduceCe = false) { + this.roleName = role.roleName; + this.lv = role.lv; + this.vLv = role.vLv; + this.head = role.head; + this.frame = role.frame; + this.spine = role.spine; + this.title = role.title; + this.guildName = role.guildName; + if(needReduceCe) { + this.ce = reduceCe(role.ce); + } else { + this.ce = role.ce; + } + } +} + +export class RoleRankInfo extends RankParam { + rank: number; + roleId: string; + num: number; + time: number; + + setInfo(rank: number, roleId: string, num: number, time: number) { + this.rank = rank; + this.roleId = roleId; + this.num = num; + this.time = time; + } + + isMyInfo(myId: string) { + return this.roleId == myId; } } @@ -39,13 +68,32 @@ export class GuildRankParam { } - constructor(icon: number, name: string, lv: number, leader: {roleName: string, title: number, lv: number, head: number, frame: number, spine: number}, memberCnt: number) { - this.icon = icon; - this.name = name; - this.lv = lv; + constructor(guild: GuildUpdateParam) { + this.icon = guild.icon; + this.name = guild.name; + this.lv = guild.lv; + let leader = guild.leader; let _leader = new GuildLeader(leader); this.leader = _leader; - this.memberCnt = memberCnt; + this.memberCnt = guild.memberCnt; + } +} + +export class GuildRankInfo extends GuildRankParam { + rank: number; + code: string; + num: number; + time: number; + + setInfo(rank: number, code: string, num: number, time: number) { + this.rank = rank; + this.code = code; + this.num = num; + this.time = time; + } + + isMyInfo(myId: string) { + return this.code == myId; } } @@ -114,23 +162,38 @@ export class KeyName { key: string; serverId?: number; guildCode?: string; + cityId?: number; - constructor(key: string) { + constructor(key: string, param: KeyNameParam) { this.key = key; + if(param.serverId) this.serverId = param.serverId; + if(param.guildCode) this.guildCode = param.guildCode; + if(param.cityId) this.cityId = param.cityId; } - getName() { + public getName() { let res = this.key; if(this.serverId) res += `:${this.serverId}`; if(this.guildCode) res += `:${this.guildCode}`; + if(this.cityId) res += `:${this.cityId}`; return res; } - getNameWithPlus(...plus: string[]) { + public getNameWithPlus(...plus: string[]) { let res = this.getName(); for(let p of plus) { res += `:${p}`; } return res; } -} \ No newline at end of file + + public getTimeName() { + return this.getNameWithPlus('time'); + } + + public getUnionName() { + return this.getNameWithPlus('union'); + } +} + +export type KeyNameParam = Partial; \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_rankingReward.json b/shared/resource/jsons/dic_zyz_rankingReward.json new file mode 100644 index 000000000..2b17a942d --- /dev/null +++ b/shared/resource/jsons/dic_zyz_rankingReward.json @@ -0,0 +1,266 @@ +[ + { + "id": 1, + "rankId": 1, + "condition": 1000, + "reward": "1&1&0|31002&50&0|31002&100&1" + }, + { + "id": 2, + "rankId": 1, + "condition": 5000, + "reward": "2&1&0|6004&1&0|31002&50&0|31002&100&1" + }, + { + "id": 3, + "rankId": 1, + "condition": 10000, + "reward": "3&1&0|6002&1&0|31002&50&0|31002&100&1" + }, + { + "id": 4, + "rankId": 1, + "condition": 13600, + "reward": "4&1&0|6003&1&0|31002&50&0|31002&100&1" + }, + { + "id": 5, + "rankId": 1, + "condition": 18550, + "reward": "5&1&0|31002&50&0|31002&100&1" + }, + { + "id": 6, + "rankId": 2, + "condition": 1000, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 7, + "rankId": 2, + "condition": 2000, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 8, + "rankId": 2, + "condition": 3000, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 9, + "rankId": 2, + "condition": 4000, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 10, + "rankId": 3, + "condition": 10, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 11, + "rankId": 3, + "condition": 20, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 12, + "rankId": 3, + "condition": 30, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 13, + "rankId": 3, + "condition": 40, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 14, + "rankId": 3, + "condition": 50, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 15, + "rankId": 4, + "condition": 10, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 16, + "rankId": 4, + "condition": 20, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 17, + "rankId": 4, + "condition": 30, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 18, + "rankId": 4, + "condition": 40, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 19, + "rankId": 4, + "condition": 50, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 20, + "rankId": 5, + "condition": 11111, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 21, + "rankId": 5, + "condition": 22222, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 22, + "rankId": 5, + "condition": 33333, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 23, + "rankId": 5, + "condition": 44444, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 24, + "rankId": 5, + "condition": 55555, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 25, + "rankId": 6, + "condition": 10, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 26, + "rankId": 6, + "condition": 20, + "reward": "1&1&0|31002&50&0|31002&100&1" + }, + { + "id": 27, + "rankId": 6, + "condition": 30, + "reward": "2&1&0|6004&1&0|31002&50&0|31002&100&1" + }, + { + "id": 28, + "rankId": 6, + "condition": 40, + "reward": "3&1&0|6002&1&0|31002&50&0|31002&100&1" + }, + { + "id": 29, + "rankId": 6, + "condition": 50, + "reward": "4&1&0|6003&1&0|31002&50&0|31002&100&1" + }, + { + "id": 30, + "rankId": 7, + "condition": 5001, + "reward": "5&1&0|31002&50&0|31002&100&1" + }, + { + "id": 31, + "rankId": 7, + "condition": 5010, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 32, + "rankId": 7, + "condition": 5020, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 33, + "rankId": 7, + "condition": 5030, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 34, + "rankId": 7, + "condition": 5040, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 35, + "rankId": 8, + "condition": 104, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 36, + "rankId": 8, + "condition": 105, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 37, + "rankId": 8, + "condition": 106, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 38, + "rankId": 8, + "condition": 107, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 39, + "rankId": 8, + "condition": 108, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 40, + "rankId": 9, + "condition": 9001, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 41, + "rankId": 9, + "condition": 9002, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 42, + "rankId": 9, + "condition": 9003, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 43, + "rankId": 9, + "condition": 9004, + "reward": "17040&1&0|31002&50&0|31002&100&1" + }, + { + "id": 44, + "rankId": 9, + "condition": 9005, + "reward": "17040&1&0|31002&50&0|31002&100&1" + } +] \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_rankingType.json b/shared/resource/jsons/dic_zyz_rankingType.json new file mode 100644 index 000000000..964a3dabd --- /dev/null +++ b/shared/resource/jsons/dic_zyz_rankingType.json @@ -0,0 +1,65 @@ +[ + { + "id": 1, + "name": "最强阵容 ", + "group": 1, + "groupName": "玩家", + "general": 1 + }, + { + "id": 2, + "name": "最强武将", + "group": 1, + "groupName": "玩家", + "general": 1 + }, + { + "id": 3, + "name": "武将数量 ", + "group": 1, + "groupName": "玩家", + "general": 1 + }, + { + "id": 4, + "name": "主公等级", + "group": 1, + "groupName": "玩家", + "general": 1 + }, + { + "id": 5, + "name": "总战力", + "group": 1, + "groupName": "玩家", + "general": 2 + }, + { + "id": 6, + "name": "镇念塔 ", + "group": 1, + "groupName": "玩家", + "general": 2 + }, + { + "id": 7, + "name": "秘境", + "group": 1, + "groupName": "玩家", + "general": 2 + }, + { + "id": 8, + "name": "主线推进 ", + "group": 1, + "groupName": "玩家", + "general": 2 + }, + { + "id": 9, + "name": "精英主线", + "group": 1, + "groupName": "玩家", + "general": 2 + } +] \ No newline at end of file