排行榜: 获取排行榜

This commit is contained in:
luying
2021-04-07 21:00:07 +08:00
parent 34e02dea89
commit 5dca7b304d
32 changed files with 1077 additions and 290 deletions

View File

@@ -22,7 +22,7 @@ import * as redLockService from './app/services/redLockService';
import _pinus = require('pinus'); import _pinus = require('pinus');
import { updateTeamStatus } from './app/services/comBattleService'; import { updateTeamStatus } from './app/services/comBattleService';
import { init } from './app/pubUtils/gmData/gmDataUtil'; import { init } from './app/pubUtils/gmData/gmDataUtil';
import { addActive } from './app/services/guildService'; import { gameData } from './app/pubUtils/data';
const filePath = (_pinus as any).FILEPATH; const filePath = (_pinus as any).FILEPATH;
filePath.MASTER = '/config/master'; filePath.MASTER = '/config/master';
filePath.SERVER = '/config/servers'; filePath.SERVER = '/config/servers';

View File

@@ -74,7 +74,7 @@ export class GuildHandler {
// 加入排行 // 加入排行
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId});
await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild); await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild);
let rank = await r.getMyRank(guild.code); let rank = await r.getMyRank({ guildCode: guild.code });
// 加入channel // 加入channel
session.set('guildCode', guild.code); session.set('guildCode', guild.code);
@@ -280,7 +280,7 @@ export class GuildHandler {
// 获取排行榜 // 获取排行榜
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
const rank = await r.getMyRank(guild.code); const rank = await r.getMyRank({ guildCode: guild.code });
// 返回 // 返回
const result = { hasGuild: true, ...guild, leader: { ...leader, isOnline: leaderIsOnline }, rank, myInfo: {...userGuild }}; const result = { hasGuild: true, ...guild, leader: { ...leader, isOnline: leaderIsOnline }, rank, myInfo: {...userGuild }};
@@ -606,7 +606,7 @@ export class GuildHandler {
this.app.rpc.chat.guildRemote.dismiss.toServer(chatSid,code); this.app.rpc.chat.guildRemote.dismiss.toServer(chatSid,code);
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId});
await r.removeFromRank(code); await r.removeFromRank({ guildCode: code });
return resResult(STATUS.SUCCESS, { code, status: guild.status }); return resResult(STATUS.SUCCESS, { code, status: guild.status });
} }
@@ -790,6 +790,11 @@ export class GuildHandler {
if(!result) { if(!result) {
return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); return resResult(STATUS.GUILD_FUND_NOT_ENOUGH);
} }
if(id == GUILD_STRUCTURE.ARMY_CENTER) {
let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId });
await r.setRankWithGuildInfo(code, guild.lv, guild.lvUpdateTime, guild);
}
const resultStructure = result.structure.find(cur => cur.id == id); const resultStructure = result.structure.find(cur => cur.id == id);
// 修改信息 // 修改信息
@@ -919,7 +924,7 @@ export class GuildHandler {
if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
let { ranks, myRank } = await r.getRankListWithMyRank(myUserGuild.guildCode); let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild.guildCode });
if(!myRank) { if(!myRank) {
let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly'); let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly');
myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild);

View File

@@ -3,7 +3,7 @@ import { BattleRecordModel } from '../../../db/BattleRecord';
import { BattleSweepRecordModel } from '../../../db/BattleSweepRecord'; import { BattleSweepRecordModel } from '../../../db/BattleSweepRecord';
import { getWarById, } from '../../../pubUtils/gamedata'; import { getWarById, } from '../../../pubUtils/gamedata';
import { genCode } from '../../../pubUtils/util'; import { genCode } from '../../../pubUtils/util';
import { WAR_TYPE, EVENT_STATUS, FUNC_OPT_TYPE, MSG_SOURCE } from '../../../consts'; import { WAR_TYPE, EVENT_STATUS, FUNC_OPT_TYPE, MSG_SOURCE, REDIS_KEY } from '../../../consts';
import { checkDaily, checkDailyAndIncrease } from '../../../services/dailyBattleService'; import { checkDaily, checkDailyAndIncrease } from '../../../services/dailyBattleService';
import { checkTowerWar, towerBattleEnd } from '../../../services/battleService'; import { checkTowerWar, towerBattleEnd } from '../../../services/battleService';
import { WarReward } from '../../../services/warRewardService'; import { WarReward } from '../../../services/warRewardService';
@@ -18,6 +18,8 @@ import { checkDungeonNum, checkDungeonAndIncrease } from '../../../services/dung
import { switchOnFunc } from '../../../services/funcSwitchService'; import { switchOnFunc } from '../../../services/funcSwitchService';
import { gameData } from '../../../pubUtils/data'; import { gameData } from '../../../pubUtils/data';
import { pushMysteryFirstMsg, pushTowerMsg, pushVestigeFirstMsg } from '../../../services/chatService'; import { pushMysteryFirstMsg, pushTowerMsg, pushVestigeFirstMsg } from '../../../services/chatService';
import { nowSeconds } from '../../../pubUtils/timeUtil';
import { Rank } from '../../../services/rankService';
export default function(app: Application) { export default function(app: Application) {
return new NormalBattleHandler(app); return new NormalBattleHandler(app);
@@ -215,11 +217,22 @@ export class NormalBattleHandler {
} }
} else if (warInfo.warType == WAR_TYPE.MYSTERY || warInfo.warType == WAR_TYPE.MYSTERY_ELITE) { } else if (warInfo.warType == WAR_TYPE.MYSTERY || warInfo.warType == WAR_TYPE.MYSTERY_ELITE) {
let checkResult = await checkDungeonAndIncrease(roleId, 1, false); let checkResult = await checkDungeonAndIncrease(roleId, 1, false);
await RoleModel.saveDungeonHero(roleId, battleId, heroes, isSuccess); let role = await RoleModel.saveDungeonHero(roleId, battleId, heroes, isSuccess);
let r = new Rank(REDIS_KEY.DUNGEON_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.dungeonWarId, role.dungeonUpdatedAt, role);
if(checkResult.status == -1) { if(checkResult.status == -1) {
return checkResult.resResult; return checkResult.resResult;
} }
dungeonNum = Object.assign(dungeonNum, checkResult.data) dungeonNum = Object.assign(dungeonNum, checkResult.data)
} else if (warInfo.warType == WAR_TYPE.NORMAL) {
let role = await RoleModel.updateMainWarId(roleId, battleId, nowSeconds());
let r = new Rank(REDIS_KEY.MAIN_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.mainWarId, role.mainUpdatedAt, role);
} else if (warInfo.warType == WAR_TYPE.MAIN_ELITE) {
let role = await RoleModel.updateMainEliteWarId(roleId, battleId, nowSeconds());
let r = new Rank(REDIS_KEY.MAIN_ELITE_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role);
} }
if(isSuccess) { // 挑战胜利 if(isSuccess) { // 挑战胜利

View File

@@ -442,7 +442,7 @@ export class PvpHandler {
} }
heroes.sort((a, b) => b.score - a.score); heroes.sort((a, b) => b.score - a.score);
let r = new Rank(REDIS_KEY.PVP_RANK, {}); let r = new Rank(REDIS_KEY.PVP_RANK, {});
let rank = await r.getMyRank(oppoRoleId);//去redis中获取排名 let rank = await r.getMyRank({ roleId: oppoRoleId });//去redis中获取排名
result = new PlayerDetail({...role, ...pvpDefense, heroes, rank}); result = new PlayerDetail({...role, ...pvpDefense, heroes, rank});
} }

View File

@@ -7,7 +7,7 @@ import { Application } from 'pinus';
import {FrontendSession} from 'pinus'; import {FrontendSession} from 'pinus';
import { HeroModel } from './../../../db/Hero'; import { HeroModel } from './../../../db/Hero';
import { resResult } from '../../../pubUtils/util'; import { resResult } from '../../../pubUtils/util';
import { COM_BTL_QUALITY, ROLE_SELECT, HERO_SELECT, GUILD_SELECT, USER_GUILD_SELECT, DEBUG_MAGIC_WORD } from '../../../consts'; import { COM_BTL_QUALITY, ROLE_SELECT, HERO_SELECT, GUILD_SELECT, USER_GUILD_SELECT, DEBUG_MAGIC_WORD, REDIS_KEY } from '../../../consts';
import { getAp } from '../../../services/actionPointService'; import { getAp } from '../../../services/actionPointService';
import { ItemModel } from '../../../db/Item'; import { ItemModel } from '../../../db/Item';
import { chackFunOpenWhenLogin } from '../../../services/funcSwitchService'; import { chackFunOpenWhenLogin } from '../../../services/funcSwitchService';
@@ -21,6 +21,7 @@ import { gameData } from '../../../pubUtils/data';
import { getMails } from '../../../services/mailService'; import { getMails } from '../../../services/mailService';
import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildChannel, leaveSysChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService'; import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildChannel, leaveSysChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService';
import { reportOneOnline } from '../../../services/timeTaskService'; import { reportOneOnline } from '../../../services/timeTaskService';
import { Rank } from '../../../services/rankService';
export default function (app: Application) { export default function (app: Application) {
return new EntryHandler(app); return new EntryHandler(app);
} }
@@ -104,6 +105,11 @@ export class EntryHandler {
await loginRefresh(role.roleId); await loginRefresh(role.roleId);
reportOneOnline(role.roleId, user.userCode, self.app.get('serverId'), user.pkgName); reportOneOnline(role.roleId, user.userCode, self.app.get('serverId'), user.pkgName);
let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId });
r.setRankWithRoleInfo(role.roleId, role.heroNum, role.heroNumUpdatedAt, role);
let r2 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId });
r2.setRankWithRoleInfo(role.roleId, role.lv, role.updatedAt.getTime(), role);
role['heros'] = heros; role['heros'] = heros;
role['equips'] = equips; role['equips'] = equips;
role['consumeGoods'] = items; role['consumeGoods'] = items;

View File

@@ -8,7 +8,7 @@ import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec";
import { leaveCityChannel, addRoleToCityChannel, getCityChannelSid } from "../../../services/chatService"; import { leaveCityChannel, addRoleToCityChannel, getCityChannelSid } from "../../../services/chatService";
import { UserGuildModel } from "../../../db/UserGuild"; import { UserGuildModel } from "../../../db/UserGuild";
import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; import { GuildActivityRecordModel } from "../../../db/GuildActivityRec";
import { nowSeconds, getBeforeSeconds } from "../../../pubUtils/timeUtil"; import { nowSeconds, getBeforeSeconds, getNextHourPoint } from "../../../pubUtils/timeUtil";
import { getGoldObject } from "../../../pubUtils/itemUtils"; import { getGoldObject } from "../../../pubUtils/itemUtils";
import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; import { GUILDACTIVITY } from "../../../pubUtils/dicParam";
import { handleCost } from "../../../services/rewardService"; import { handleCost } from "../../../services/rewardService";
@@ -233,10 +233,12 @@ export class CityActivityHandler {
// 更新redis数据 // 更新redis数据
let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }); let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode });
let myScore = await myR.setRankWithRoleInfo(roleId, damage, Date.now(), null, false, true); let myScore = await myR.setRankWithRoleInfo(roleId, damage, Date.now(), null, false);
await myR.setExpire(getNextHourPoint(5));
let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true ); let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true );
let guildScore = await r.setRankWithGuildInfo(guildCode, damage, Date.now(), null, true); let guildScore = await r.setRankWithGuildInfo(guildCode, damage, Date.now(), null, true);
await r.setExpire(getNextHourPoint(5));
gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp, -1 * damage); gateHp = obj.getGateHpAndInc(serverId, cityId, dicCity.hp, -1 * damage);
if(gateHp <= 0) { if(gateHp <= 0) {

View File

@@ -13,6 +13,7 @@ import { getGuildChannelSid } from "../../../services/chatService";
import { UserGuildModel } from "../../../db/UserGuild"; import { UserGuildModel } from "../../../db/UserGuild";
import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; import { GuildActivityCityModel } from "../../../db/GuildActivityCity";
import { Rank } from "../../../services/rankService"; import { Rank } from "../../../services/rankService";
import { getNextHourPoint } from "../../../pubUtils/timeUtil";
export default function (app: Application) { export default function (app: Application) {
return new GateActivityHandler(app); return new GateActivityHandler(app);
@@ -138,10 +139,12 @@ export class GateActivityHandler {
// 更新redis数据 // 更新redis数据
let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }, false); 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 myScore = await myR.setRankWithRoleInfo(roleId, score, Date.now(), null, false);
await myR.setExpire(getNextHourPoint(5));
let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true);
let guildScore = await r.setRankWithGuildInfo(guildCode, score, Date.now(), null, true); let guildScore = await r.setRankWithGuildInfo(guildCode, score, Date.now(), null, true);
await r.setExpire(getNextHourPoint(5));
// 更新数据库 // 更新数据库
let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords, round); let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords, round);

View File

@@ -688,7 +688,7 @@ export class FriendHandler {
} }
let r = new Rank(REDIS_KEY.PVP_RANK, {}); let r = new Rank(REDIS_KEY.PVP_RANK, {});
let rank = await r.getMyRank(oppoRoleId);//去redis中获取排名 let rank = await r.getMyRank({ roleId: oppoRoleId });//去redis中获取排名
result = new PlayerDetail({...role, defCe: topLineupCe, heroes}); result = new PlayerDetail({...role, defCe: topLineupCe, heroes});
result.setWarStar(role.warStar, rank, towerLv); result.setWarStar(role.warStar, rank, towerLv);

View File

@@ -4,7 +4,7 @@ import { calPlayerCeAndSave, calAllHeroCe } from '../../../services/playerCeServ
import { resResult, returnHeroCeRatio, deepCopy } from '../../../pubUtils/util'; import { resResult, returnHeroCeRatio, deepCopy } from '../../../pubUtils/util';
import { STATUS } from '../../../consts/statusCode'; import { STATUS } from '../../../consts/statusCode';
import { HeroModel, Connect } from '../../../db/Hero'; import { HeroModel, Connect } from '../../../db/Hero';
import {CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ABI_STAGE, DEBUG_MAGIC_WORD, HERO_INITIAL_QUALITY} from '../../../consts'; import {CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ABI_STAGE, DEBUG_MAGIC_WORD, HERO_INITIAL_QUALITY, REDIS_KEY} from '../../../consts';
import { RoleModel } from '../../../db/Role'; import { RoleModel } from '../../../db/Role';
import { ItemModel } from '../../../db/Item'; import { ItemModel } from '../../../db/Item';
import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, getHeroLvByExp, getMaxGradeByjobClass, getJobByGradeAndClass, getFriendShipById, getFavourLvByExp } from '../../../pubUtils/data'; import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, getHeroLvByExp, getMaxGradeByjobClass, getJobByGradeAndClass, getFriendShipById, getFavourLvByExp } from '../../../pubUtils/data';
@@ -14,6 +14,8 @@ import { pushComposeOrangeHero, pushHeroQualityUpMsg, pushHeroStarMax, pushHeroW
import { calculatetopLineup } from '../../../pubUtils/playerCe'; import { calculatetopLineup } from '../../../pubUtils/playerCe';
import { PvpDefenseModel } from '../../../db/PvpDefense'; import { PvpDefenseModel } from '../../../db/PvpDefense';
import { Attribute } from '../../../domain/roleField/attribute'; import { Attribute } from '../../../domain/roleField/attribute';
import { nowSeconds } from '../../../pubUtils/timeUtil';
import { Rank } from '../../../services/rankService';
export default function(app: Application) { export default function(app: Application) {
return new HeroHandler(app); return new HeroHandler(app);
@@ -139,6 +141,10 @@ export class HeroHandler {
let curHero = await HeroModel.createHero({ let curHero = await HeroModel.createHero({
roleId, serverId, roleName, hid, hName, star, quality, job, skins:[{id: initialSkin, enable: true}] roleId, serverId, roleName, hid, hName, star, quality, job, skins:[{id: initialSkin, enable: true}]
}); });
let role = await RoleModel.incRoleInfo(roleId, { heroNum: 1 }, { heroNumUpdatedAt: nowSeconds() });
let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role);
await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid }]); // 解锁头像 await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid }]); // 解锁头像
let hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, sid, roleId, curHero, {}); let hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, sid, roleId, curHero, {});
await calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, [initialSkin]) await calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, [initialSkin])

View File

@@ -1,14 +1,13 @@
import { Application, BackendSession } from "pinus"; import { Application, BackendSession } from "pinus";
import { resResult, aesEncryptcfb } from "../../../pubUtils/util"; import { resResult } from "../../../pubUtils/util";
import { STATUS, REDIS_KEY, ENCRYPT_KEY, ENCRYPT_IV } from "../../../consts"; import { STATUS, REDIS_KEY, RANK_TYPE_TO_KEY, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SELECT } from "../../../consts";
import { RoleModel, RoleType } from "../../../db/Role"; import { RoleModel } from "../../../db/Role";
import { UserGuildModel } from "../../../db/UserGuild"; import { UserGuildModel } from "../../../db/UserGuild";
import { GuildModel } from "../../../db/Guild"; import { GuildModel } from "../../../db/Guild";
import { GuildRankParam } from "../../../domain/rank";
import { HeroModel } from "../../../db/Hero"; import { HeroModel } from "../../../db/Hero";
import { UserModel } from "../../../db/User"; import { UserModel } from "../../../db/User";
import { Rank } from "../../../services/rankService"; import { Rank } from "../../../services/rankService";
import { redisClient } from "../../../services/redisService"; import { nowSeconds } from "../../../pubUtils/timeUtil";
export default function (app: Application) { export default function (app: Application) {
return new RoleHandler(app); return new RoleHandler(app);
@@ -23,7 +22,7 @@ export class RoleHandler {
let roleName = session.get('roleName'); let roleName = session.get('roleName');
let serverId = session.get('serverId'); let serverId = session.get('serverId');
return resResult(STATUS.SUCCESS, { return resResult(STATUS.SUCCESS, {
role: [ role: [
{ type: 1, roleId: "8l6HPZAbdS", roleName: "东方月初", head: 11219, frame: 11301, spine: 11419, lv: 40, vLv: 0, guildName: "军团A", ce: 464262, num: 464262, received: [], }, { type: 1, roleId: "8l6HPZAbdS", roleName: "东方月初", head: 11219, frame: 11301, spine: 11419, lv: 40, vLv: 0, guildName: "军团A", ce: 464262, num: 464262, received: [], },
@@ -43,40 +42,47 @@ export class RoleHandler {
async getRank(msg: { type: number }, session: BackendSession) { async getRank(msg: { type: number }, session: BackendSession) {
let roleId = session.get('roleId'); let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId'); let serverId = session.get('serverId');
let { type } = msg; let { type } = msg;
let redisKey = RANK_TYPE_TO_KEY.get(type);
if(!redisKey) return resResult(STATUS.WRONG_PARMS);
let role = await RoleModel.findByRoleId(roleId, null, true); let r: Rank;
let { lv, vLv, head, frame, spine, guildName, ce } = role; switch(type) {
case RANK_TYPE.TOP_LINTUP:
let lineup = [ case RANK_TYPE.TOP_HERO:
{ hid: 27, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 }, case RANK_TYPE.SUM_CE:
{ hid: 32, star: 6, colorStar: 6, lv: 96, quality: 3, job: 1 }, r = new Rank(redisKey, { serverId }, false, 0); break;
{ hid: 19, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 }, default:
{ hid: 11, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 }, r = new Rank(redisKey, { serverId }); break;
{ hid: 12, star: 6, colorStar: 6, lv: 96, quality: 3, job: 16 }, }
{ hid: 8, star: 6, colorStar: 6, lv: 96, quality: 3, job: 1 } let { ranks, myRank } = await r.getRankListWithMyRank(roleId);
]; if(!myRank) {
if(type == 2) { let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
lineup = [{ hid: 27, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 }] if(type == RANK_TYPE.TOP_LINTUP) {
myRank = await r.generMyRankWithRole(roleId, role.topLineupCe, 0, role);
} else if (type == RANK_TYPE.TOP_HERO) {
let hero = await HeroModel.getMyTopHero(roleId, HERO_SELECT.RANK_LINEUP);
myRank = await r.generMyRankWithHero(roleId, hero.hid, hero.ce, 0, hero, role);
} else if (type == RANK_TYPE.HERO_NUM) {
myRank = await r.generMyRankWithRole(roleId, role.heroNum, role.heroNumUpdatedAt, role);
} else if (type == RANK_TYPE.USER_LV) {
myRank = await r.generMyRankWithRole(roleId, role.lv, role.updatedAt.getTime(), role);
} else if (type == RANK_TYPE.SUM_CE) {
myRank = await r.generMyRankWithRole(roleId, role.ce, role.updatedAt.getTime(), role);
} else if (type == RANK_TYPE.TOWER) {
myRank = await r.generMyRankWithRole(roleId, role.towerLv, role.towerUpTime?.getTime()||0, role);
} else if (type == RANK_TYPE.DUNGEON) {
myRank = await r.generMyRankWithRole(roleId, role.dungeonWarId, role.dungeonUpdatedAt, role);
} else if (type == RANK_TYPE.MAIN) {
myRank = await r.generMyRankWithRole(roleId, role.mainWarId, role.mainUpdatedAt, role);
} else if (type == RANK_TYPE.MAIN_ELITE) {
myRank = await r.generMyRankWithRole(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role);
}
} }
let ranks = await RoleModel.getRank('tower', serverId, ["lv", "roleName", "vLv", "head", "frame", "spine", "guildName", "ce"], 1, 10); return resResult(STATUS.SUCCESS, { type, ranks, myRank });
return resResult(STATUS.SUCCESS, {
type,
ranks: ranks.map((cur, i) => {
let { roleId, roleName, head, frame, spine, lv, vLv, ce } = cur;
return {
rank: i + 1, num: 323 - i, roleId, roleName, head, frame, spine, lv, vLv, guildName: `军团${i + 1}`, ce, lineup
}
}),
myRank: {
rank: 0, num: 104, roleId, roleName, head, frame, spine, lv, vLv, guildName, ce, lineup
}
});
} }
// 查看活跃排行榜 // 查看活跃排行榜
@@ -87,47 +93,38 @@ export class RoleHandler {
let { type } = msg; let { type } = msg;
const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode'); let redisKey = RANK_TYPE_TO_KEY.get(type);
if (!myUserGuild) return resResult(STATUS.GUILD_NOT_FOUND); if(!redisKey) return resResult(STATUS.WRONG_PARMS);
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let r = new Rank(redisKey, { serverId });
let { ranks, myRank } = await r.getRankListWithMyRank(myUserGuild.guildCode,); const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode');
let { ranks, myRank } = await r.getRankListWithMyRank({guildCode: myUserGuild?.guildCode||''});
if (!myRank) { if (!myRank) {
let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly memberCnt'); let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, GUILD_SELECT.RANK);
myRank = await r.generMyRankWithGuild(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); if(type == RANK_TYPE.GUILD_LV) {
myRank = await r.generMyRankWithGuild(guild.code, guild.lv, guild.lvUpdateTime, guild);
} else if(type == RANK_TYPE.GUILD_ACTIVE) {
myRank = await r.generMyRankWithGuild(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild);
}
} }
return resResult(STATUS.SUCCESS, { type, ranks, myRank }); return resResult(STATUS.SUCCESS, { type, ranks, myRank });
} }
// 查看活跃排行榜 // 查看单个武将排行榜
async getHeroRank(msg: { type: number, hid: number }, session: BackendSession) { async getHeroRank(msg: { type: number, hid: number }, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId') let serverId = session.get('serverId')
let { type, hid } = msg; let { type, hid } = msg;
let redisKey = RANK_TYPE_TO_KEY.get(type);
if(!redisKey) return resResult(STATUS.WRONG_PARMS);
let lineup = [ let r = new Rank(redisKey, { serverId, hid }, false, 0);
{ hid: 27, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 }, let ranks = await r.getRankByRange();
{ hid: 32, star: 6, colorStar: 6, lv: 96, quality: 3, job: 1 },
{ hid: 19, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 },
{ hid: 11, star: 6, colorStar: 6, lv: 96, quality: 3, job: 11 },
{ hid: 12, star: 6, colorStar: 6, lv: 96, quality: 3, job: 16 },
{ hid: 8, star: 6, colorStar: 6, lv: 96, quality: 3, job: 1 }
]
let ranks = await HeroModel.getRank(hid, serverId, null, 10);
return resResult(STATUS.SUCCESS, { return resResult(STATUS.SUCCESS, {
type, hid, ranks: ranks.map((cur, i) => { type, hid, ranks
let { ce, roleId, roleName, hid, star, colorStar, lv, quality } = cur;
return {
rank: i + 1, num: ce, roleId, roleName, head: 11219, frame: 11301, spine: 11419, lv: 40, vLv: 0, guildName: "军团A", ce: 464262,
hero: [{ hid, star, colorStar, lv, quality }],
lineup
}
})
}); });
} }
@@ -141,4 +138,11 @@ export class RoleHandler {
}) })
} }
async test(msg: { }, session: BackendSession) {
let roles = await RoleModel.find({}).lean();
for(let role of roles) {
let heroes = await HeroModel.find({ roleId: role.roleId }).lean();
await RoleModel.updateRoleInfo(role.roleId, { heroNum: heroes.length, heroNumUpdatedAt: nowSeconds() });
}
}
} }

View File

@@ -12,6 +12,7 @@ import { getGuildChannelSid } from "./chatService";
import { pinus } from "pinus"; import { pinus } from "pinus";
import { getRandEelm, sortArrRandom, resResult } from "../pubUtils/util"; import { getRandEelm, sortArrRandom, resResult } from "../pubUtils/util";
import { Rank } from "./rankService"; import { Rank } from "./rankService";
import { getNextHourPoint } from "../pubUtils/timeUtil";
export class GateActivityObject { export class GateActivityObject {
private gateHp: Map<string, number> = new Map(); // 城门血条,每个军团有一条血条 guildCode => hp private gateHp: Map<string, number> = new Map(); // 城门血条,每个军团有一条血条 guildCode => hp
@@ -266,7 +267,8 @@ export class RaceActivityObject {
let needSendEnd = woodenHorse.calCurWoodenHorse(events); let needSendEnd = woodenHorse.calCurWoodenHorse(events);
if(woodenHorse.status == 1 || woodenHorse.status == 2) { // 更新距离 // TODO 写进const表 if(woodenHorse.status == 1 || woodenHorse.status == 2) { // 更新距离 // TODO 写进const表
let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6, 5); 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); await r.setRank({guildCode}, Math.floor(woodenHorse.distance * 1000), woodenHorse.time - woodenHorse.startTime, false);
await r.setExpire(getNextHourPoint(5));
if (needSendEnd) { // 抵达后发送奖励,发送消息,结算 if (needSendEnd) { // 抵达后发送奖励,发送消息,结算
await sendSingleRaceActEndMsg(guildCode, woodenHorse); await sendSingleRaceActEndMsg(guildCode, woodenHorse);
} }

View File

@@ -156,14 +156,14 @@ export async function getGateActivityRank(guildCode: string, serverId: number, r
let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true);
r.setGenerFieldsFun(generGuildActivityRankField); r.setGenerFieldsFun(generGuildActivityRankField);
let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank(guildCode); let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({guildCode});
if(!myGuildRank) { if(!myGuildRank) {
myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0);
} }
let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode }); let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode });
myR.setGenerFieldsFun(generGuildActivityMemberRankField); myR.setGenerFieldsFun(generGuildActivityMemberRankField);
let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank(roleId); let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank({roleId});
if(roleName && !myMemberRank) { if(roleName && !myMemberRank) {
myMemberRank = await r.generMyRankWithRole(roleId, 0, 0); myMemberRank = await r.generMyRankWithRole(roleId, 0, 0);
} }
@@ -175,14 +175,14 @@ export async function getCityActivityRank(guildCode: string, serverId: number, c
let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true); let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId }, true);
r.setGenerFieldsFun(generGuildActivityRankField); r.setGenerFieldsFun(generGuildActivityRankField);
let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank(guildCode); let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({guildCode});
if(!myGuildRank) { if(!myGuildRank) {
myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0);
} }
let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode }); let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode });
myR.setGenerFieldsFun(generGuildActivityMemberRankField); myR.setGenerFieldsFun(generGuildActivityMemberRankField);
let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank(roleId); let { ranks: memberRank, myRank: myMemberRank } = await r.getRankListWithMyRank({roleId});
if(roleName && !myMemberRank) { if(roleName && !myMemberRank) {
myMemberRank = await r.generMyRankWithRole(roleId, 0, 0); myMemberRank = await r.generMyRankWithRole(roleId, 0, 0);
} }
@@ -193,7 +193,7 @@ export async function getCityActivityRank(guildCode: string, serverId: number, c
export async function getRaceActivityRank(guildCode: string, serverId: number) { export async function getRaceActivityRank(guildCode: string, serverId: number) {
let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6); let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true, 6);
r.setGenerFieldsFun(generField); r.setGenerFieldsFun(generField);
let { myRank, ranks } = await r.getRankListWithMyRank(guildCode); let { myRank, ranks } = await r.getRankListWithMyRank({guildCode});
if(!myRank) { if(!myRank) {
myRank = await r.generMyRankWithGuild(guildCode, 0, 0); myRank = await r.generMyRankWithGuild(guildCode, 0, 0);
} }
@@ -217,7 +217,7 @@ export async function getWoodenHorseList(guildCode: string, serverId: number) {
let obj = getRaceActivityObj(); let obj = getRaceActivityObj();
let r = new Rank(REDIS_KEY.RACE_ACTIVITY, {serverId}, true, 6, 5); let r = new Rank(REDIS_KEY.RACE_ACTIVITY, {serverId}, true, 6, 5);
let myRank = await r.getMyRank(guildCode); let myRank = await r.getMyRank({guildCode});
let startRank = myRank - 2 > 0? myRank - 2: 1; let startRank = myRank - 2 > 0? myRank - 2: 1;
let endRank = startRank + 4; let endRank = startRank + 4;
let range =<GuildRankInfo[]> await r.getRankByRange(startRank, endRank); let range =<GuildRankInfo[]> await r.getRankByRange(startRank, endRank);
@@ -362,8 +362,8 @@ export async function gateActivitySettleReward(guildCode: string, serverId: numb
let { gateHp, members } = obj.getObj(guildCode, serverId); let { gateHp, members } = obj.getObj(guildCode, serverId);
let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true);
let rank = await r.getMyRank(guildCode); let rank = await r.getMyRank({guildCode});
let guildScore = await r.getMyScore(guildCode); let guildScore = await r.getMyScore({guildCode});
let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank); let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank);
@@ -654,7 +654,7 @@ export async function raceActivitySettleReward(guildCode: string, woodenHorse: W
// 计算排名,计算耐久,发送奖励 // 计算排名,计算耐久,发送奖励
let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true); let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId }, true);
let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团 let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团
let myGuildRank = await r.getMyRank(guildCode); let myGuildRank = await r.getMyRank({guildCode});
let members = obj.getMembersOfGuild(guildCode); let members = obj.getMembersOfGuild(guildCode);
let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, myGuildRank); let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, myGuildRank);

View File

@@ -175,9 +175,8 @@ export async function addActive(roleId: string, serverId: number, id: number, ty
guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active });
// 排行榜更新 // 排行榜更新
let leader = await RoleModel.findById(guild.leader);
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime * 1000, guild); await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime, guild);
pinus.app.rpc.chat.guildRemote.updateInfo.toServer(CHAT_SERVER, guildCode, { activeDaily: guild.activeDaily, activeWeekly: guild.activeWeekly }); pinus.app.rpc.chat.guildRemote.updateInfo.toServer(CHAT_SERVER, guildCode, { activeDaily: guild.activeDaily, activeWeekly: guild.activeWeekly });
return { status: 1, guild, userGuild }; return { status: 1, guild, userGuild };
} }
@@ -267,7 +266,7 @@ export async function settleGuildWeekly() {
// 转换周活跃奖励 // 转换周活跃奖励
let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
let rank = await r.getMyRank(code); let rank = await r.getMyRank({guildCode: code});
let allWeeklyReward = getGuildActiveWeekReward(rank); let allWeeklyReward = getGuildActiveWeekReward(rank);
for(let [roleId, job] of members) { for(let [roleId, job] of members) {
let jobActiveRatio = gameData.guildPosition.get(job).activeRatio; let jobActiveRatio = gameData.guildPosition.get(job).activeRatio;

View File

@@ -6,7 +6,8 @@ import { updateUserInfo } from './redisService';
import { switchOnFunc } from './funcSwitchService'; import { switchOnFunc } from './funcSwitchService';
import { FUNC_OPT_TYPE } from '../consts'; import { FUNC_OPT_TYPE } from '../consts';
import { BackendSession } from 'pinus'; import { BackendSession } from 'pinus';
import { REDIS_KEY } from '../consts/consts'; import { REDIS_KEY } from '../consts';
import { Rank } from './rankService';
export async function roleLevelup(roleId: string, kingExp: number, session: BackendSession) { export async function roleLevelup(roleId: string, kingExp: number, session: BackendSession) {
let role = await RoleModel.findByRoleId(roleId); let role = await RoleModel.findByRoleId(roleId);
@@ -24,7 +25,10 @@ export async function roleLevelup(roleId: string, kingExp: number, session: Back
role = await RoleModel.levelup(roleId, newLv, newExp); role = await RoleModel.levelup(roleId, newLv, newExp);
if(newLv > lv) { // 升级 if(newLv > lv) { // 升级
await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session); await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session);
await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{field: 'lv', value: newLv}]) await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{field: 'lv', value: newLv}]);
let r = new Rank(REDIS_KEY.USER_LV, { serverId: role.serverId });
await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role);
} }
let actordata = []; let actordata = [];
for(let i = lv; i <= newLv; i++) { for(let i = lv; i <= newLv; i++) {

View File

@@ -10,12 +10,14 @@ import { calPlayerCeAndSave as pubCalPlayerCeAndSave, reCalAllHeroCe } from '..
import Hero, { HeroType, HeroUpdate } from '../db/Hero'; import Hero, { HeroType, HeroUpdate } from '../db/Hero';
import { defaultHeroes } from './pvpService'; import { defaultHeroes } from './pvpService';
import { RoleUpdate } from '../db/Role'; import { RoleUpdate } from '../db/Role';
import { redisUserInfoUpdate } from './redisService'; import { Rank, updateUserInfo } from './rankService';
import { REDIS_KEY } from '../consts'; import { REDIS_KEY } from '../consts';
//修改并下发战力 //修改并下发战力
export async function calPlayerCeAndSave(type: number, sid: string, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array<number>) { export async function calPlayerCeAndSave(type: number, sid: string, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array<number>) {
let {role, pushHeros, topLineupCe, hero, guild} = await pubCalPlayerCeAndSave(type, roleId, originHero, update, args); let {role, pushHeros, topLineupCe, hero, guild, serverId} = await pubCalPlayerCeAndSave(type, roleId, originHero, update, args);
console.log(JSON.stringify(pushHeros)) console.log(JSON.stringify(pushHeros))
//下发战力 //下发战力
let uids = [{ uid: roleId, sid }]; let uids = [{ uid: roleId, sid }];
@@ -23,21 +25,57 @@ export async function calPlayerCeAndSave(type: number, sid: string, roleId: stri
defaultHeroes(role); defaultHeroes(role);
if(guild) { if(guild) {
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 }]);
} }
// 最强阵容
let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId }, false, 0);
await r.setRankWithRoleInfo(roleId, reduceCe(topLineupCe), 0, role);
// 最强武将
for(let { hid, ce } of pushHeros) {
let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }, false, 0);
await r2.setRankWithHeroInfo(roleId, hid, ce, 0, hero);
let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }, false, 0);
await r4.setRankWithHeroInfo(roleId, hid, ce, 0, hero);
}
// 总战力
let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }, false, 0);
await r3.setRankWithRoleInfo(roleId, reduceCe(role.ce), 0, role);
return hero; return hero;
} }
export async function calAllHeroCe(type:number, sid: string, roleId: string, update: RoleUpdate, args?:Array<number>) { export async function calAllHeroCe(type:number, sid: string, roleId: string, update: RoleUpdate, args?:Array<number>) {
let {role, ce, pushHeros, topLineupCe, guild } = await reCalAllHeroCe(type, roleId, update, args); let {role, ce, pushHeros, topLineupCe, guild, serverId } = await reCalAllHeroCe(type, roleId, update, args);
if(pushHeros.length > 0) { if(pushHeros.length > 0) {
let uids = [{ uid: roleId, sid }]; let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(ce), heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids); pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(ce), heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids);
if(guild) { if(guild) {
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 }]);
} }
// 最强阵容
let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId }, false, 0);
await r.setRankWithRoleInfo(roleId, reduceCe(topLineupCe), 0, role);
// 最强武将
for(let { hid, ce } of pushHeros) {
let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }, false, 0);
await r2.setRankWithHeroInfo(roleId, hid, ce, 0);
let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }, false, 0);
await r4.setRankWithHeroInfo(roleId, hid, ce, 0);
}
// 总战力
let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }, false, 0);
await r3.setRankWithRoleInfo(roleId, reduceCe(role.ce), 0, role);
} }
return role; return role;
} }

View File

@@ -115,11 +115,11 @@ export async function matchPlayerByRank(seasonNum: number, oppPlayers: OppPlayer
let r = new Rank(REDIS_KEY.PVP_RANK, {}); let r = new Rank(REDIS_KEY.PVP_RANK, {});
let ridRanks = new Array<number>(); // 已经被使用了的排名 let ridRanks = new Array<number>(); // 已经被使用了的排名
for(let { roleId: curRoleId } of oppPlayers) { for(let { roleId: curRoleId } of oppPlayers) {
let rankLv = await r.getMyRank(robotIdComBack(curRoleId)); let rankLv = await r.getMyRank({ roleId: robotIdComBack(curRoleId)});
ridRanks.push(rankLv); ridRanks.push(rankLv);
} }
let myRank = await r.getMyRank(roleId); let myRank = await r.getMyRank({roleId});
ridRanks.push(myRank); ridRanks.push(myRank);
let oppRoleId = ''; let oppRoleId = '';
@@ -213,7 +213,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJ
let { heroScores, heroes: defenseHeroes } = pvpdefense; let { heroScores, heroes: defenseHeroes } = pvpdefense;
let role = <RoleType>pvpdefense.role; let role = <RoleType>pvpdefense.role;
let r = new Rank(REDIS_KEY.PVP_RANK, {}); let r = new Rank(REDIS_KEY.PVP_RANK, {});
let rankLv = await r.getMyRank(role.roleId); let rankLv = await r.getMyRank({ roleId: role.roleId });
let dbHeroes = await HeroModel.findByRole(role.roleId, [{field: 'ce', sortBy: -1}]); let dbHeroes = await HeroModel.findByRole(role.roleId, [{field: 'ce', sortBy: -1}]);
let heroes = new Array<PvpEnemies>(); let heroes = new Array<PvpEnemies>();
let otherHeroes = new Array<PvpOtherHeroes>(); // 阵容外的所有武将信息 let otherHeroes = new Array<PvpOtherHeroes>(); // 阵容外的所有武将信息

View File

@@ -1,8 +1,13 @@
import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, GuildRankInfo, GuildLeader } from "../domain/rank"; import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, GuildRankInfo, GuildLeader, LineupParam, myIdInter } from "../domain/rank";
import { REDIS_RANK_TO_INFO, ROLE_SELECT, GUILD_SELECT, REDIS_KEY } from "../consts"; import { REDIS_RANK_TO_INFO, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, REDIS_RANK_TO_EXTRA, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD } from "../consts";
import { redisClient, setUserInfo } from "./redisService"; import { redisClient, setUserInfo } from "./redisService";
import { RoleType, RoleModel } from "../db/Role"; import { RoleType, RoleModel } from "../db/Role";
import { GuildType, GuildModel } from "../db/Guild"; import { GuildType, GuildModel } from "../db/Guild";
import Hero, { HeroModel, HeroType } from "../db/Hero";
import { SystemConfigModel } from "../db/SystemConfig";
import { PvpDefenseModel } from "../db/PvpDefense";
import { gameData } from "../pubUtils/data";
/** /**
* @description 排行榜相关操作 * @description 排行榜相关操作
@@ -13,25 +18,27 @@ export class Rank {
key: string; // 排行榜原始key key: string; // 排行榜原始key
keyName: KeyName; // 拼接之后的key keyName: KeyName; // 拼接之后的key
infoKey: string; // 玩家数据key infoKey: string; // 玩家数据key
extraKeys: string[];
isUnion: boolean; // 是否使用多个zset联合计算 isUnion: boolean; // 是否使用多个zset联合计算
limit: number = 200; // 排行榜长度 limit: number = 200; // 排行榜长度
timelen: number = 10; // 给时间位留的长度 timelen: number = 10; // 给时间位留的长度
unionRankLife: number = 10; unionRankLife: number = 10;
constructor(key: string, keyParam: KeyNameParam, isUnion = false, timelen = 10, limit = 200) { constructor(key: string, keyParam: KeyNameParam, isUnion = false, timelen = 10, limit = 200) {
this.key = key; this.key = key;
this.keyName = new KeyName(key, keyParam); this.keyName = new KeyName(key, keyParam);
this.infoKey = REDIS_RANK_TO_INFO.get(key); this.infoKey = REDIS_RANK_TO_INFO.get(key);
this.extraKeys = REDIS_RANK_TO_EXTRA.get(key) || [];
this.isUnion = isUnion; this.isUnion = isUnion;
this.timelen = timelen; this.timelen = timelen;
this.limit = limit; this.limit = limit;
} }
private async generFields(obj: GuildRankInfo|RoleRankInfo) { private async generFields(obj: GuildRankInfo | RoleRankInfo) {
return obj; return obj;
} }
public setGenerFieldsFun(cb: (obj: GuildRankInfo|RoleRankInfo) => any) { public setGenerFieldsFun(cb: (obj: GuildRankInfo | RoleRankInfo) => any) {
this.generFields = cb; this.generFields = cb;
} }
@@ -45,41 +52,162 @@ export class Rank {
return result; return result;
} }
public async setRankWithRoleInfo(roleId: string, score: number, timestamp: number, role?: RoleType, needReduceCe = false, isInc = true ) { public async setRankWithRoleInfo(roleId: string, score: number, timestamp: number, role?: RoleType, isInc = true) {
// 如果没有信息,更新玩家信息 // 如果没有信息,更新玩家信息
const hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); for (let infoKey of [this.infoKey, ...this.extraKeys]) {
if(!hasCurUser) { const hasCurUser = await redisClient().hexistsAsync(infoKey, roleId);
if(!role) { if (!hasCurUser) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); await this.generParamAndSet(infoKey, { roleId }, { role });
needReduceCe = true;
} }
let param = new RankParam(role, needReduceCe);
await setUserInfo(this.infoKey, roleId, param);
} }
let newScore = await this.setRank(roleId, score, timestamp, isInc); let newScore = await this.setRank({ roleId }, score, timestamp, isInc);
return newScore; return newScore;
} }
public async setRankWithGuildInfo(guildCode: string, score: number, timestamp: number, guild?: GuildType, isInc = true) { public async setRankWithGuildInfo(guildCode: string, score: number, timestamp: number, guild?: GuildType, isInc = true) {
const hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); for (let infoKey of [this.infoKey, ...this.extraKeys]) {
if(!hasCurUser) { const hasCurUser = await redisClient().hexistsAsync(infoKey, guildCode);
if(!guild) { if (!hasCurUser) {
guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK) await this.generParamAndSet(infoKey, { guildCode }, { guild });
} }
let param = new GuildRankParam(guild);
await setUserInfo(this.infoKey, guildCode, param);
} }
let newScore = await this.setRank(guildCode, score, timestamp, isInc); let newScore = await this.setRank({ guildCode }, score, timestamp, isInc);
return newScore; return newScore;
} }
public async setRank(myId: string, score: number, timestamp: number, isInc = false) { public async setRankWithHeroInfo(roleId: string, hid: number, score: number, timestamp: number, hero?: HeroType, isInc = true) {
// 如果没有信息,更新玩家信息
for (let infoKey of [this.infoKey, ...this.extraKeys]) {
const hasCurUser = await redisClient().hexistsAsync(infoKey, roleId);
if (!hasCurUser) {
await this.generParamAndSet(infoKey, { roleId, hid }, { hero });
}
}
let newScore = await this.setRank({ roleId, hid }, score, timestamp, isInc);
return newScore;
}
private composeFields(key: string, param: myIdInter) {
let type = KEY_TO_COMPOSE_FIELD.get(key);
if (type == COMPOSE_FIELD_TYPE.ROLE) {
return param.roleId;
} else if (type == COMPOSE_FIELD_TYPE.GUILD) {
return param.guildCode;
} else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) {
return `${param.roleId}:${param.hid}`;
} else {
return '';
}
}
private decodeFields(key: string, field: string) {
let type = KEY_TO_COMPOSE_FIELD.get(key);
let arr = field.split(':');
if (type == COMPOSE_FIELD_TYPE.ROLE) {
return { roleId: arr[0] };
} else if (type == COMPOSE_FIELD_TYPE.GUILD) {
return { guildCode: arr[0] };
} else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) {
return { roleId: arr[0], hid: parseInt(arr[1]) };
} else {
return {};
}
}
private async generParamAndSet(infoKey: string, fields: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) {
let { roleId, guildCode, hid } = fields;
let { role, guild, hero } = db;
if (infoKey == REDIS_KEY.USER_INFO) {
if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
}
let param = new RankParam(role);
await this.setUserInfo(infoKey, { roleId }, param);
} else if (infoKey == REDIS_KEY.GUILD_INFO) {
if (!guild) {
guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK)
}
let param = new GuildRankParam(guild);
await this.setUserInfo(infoKey, { guildCode }, param);
} else if (infoKey == REDIS_KEY.TOP_LINEUP_INFO) {
if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
}
let { topLineup = [] } = role;
let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP);
let arr = new Array<LineupParam>();
for (let { hid } of topLineup) {
let curHero = heroes.find(cur => cur.hid == hid);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
await this.setUserInfo(infoKey, { roleId }, arr);
} else if (infoKey == REDIS_KEY.HERO_INFO) {
if (!hero) {
hero = await HeroModel.findByHidAndRole(hid, roleId, HERO_SELECT.RANK_LINEUP, true);
}
let arr = new Array<LineupParam>();
if (hero) {
let param = new LineupParam(hero);
arr.push(param);
await this.setUserInfo(infoKey, { roleId, hid }, arr);
}
} else if (infoKey == REDIS_KEY.DUNGEON_LINEUP) {
if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
}
let { dungeonWarId, dungeonHeroes } = role;
if(dungeonWarId > 0) {
let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId);
let lineup = cur?cur.heroes: [];
let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP);
let arr = new Array<LineupParam>();
for (let seqId of lineup) {
let curHero = heroes.find(cur => cur.seqId == seqId);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
await this.setUserInfo(infoKey, { roleId }, arr);
}
} else if (infoKey == REDIS_KEY.SHOW_LINEUP) {
if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
}
let { showLineup, topLineup = [] } = role;
let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP);
let arr = new Array<LineupParam>();
if(!showLineup) showLineup = topLineup.map(cur => cur.hid);
for (let hid of showLineup) {
let curHero = heroes.find(cur => cur.hid == hid);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
await this.setUserInfo(infoKey, { roleId }, arr);
}
}
private async setUserInfo(infoKey: string, myId: myIdInter, param: RankParam | GuildRankParam | LineupParam[]) {
let field = this.composeFields(infoKey, myId);
await setUserInfo(infoKey, field, param);
}
public async setRank(myId: myIdInter, score: number, timestamp: number, isInc = false) {
// 更新分数 // 更新分数
let newScore = score; let newScore = score;
if(this.isUnion) { if (this.isUnion) {
newScore = await this.updateRankScoreAtom(myId, score, timestamp, isInc); newScore = await this.updateRankScoreAtom(myId, score, timestamp, isInc);
} else { } else {
newScore = await this.updateRankScoreEncode(myId, score, timestamp, isInc) newScore = await this.updateRankScoreEncode(myId, score, timestamp, isInc)
@@ -93,16 +221,16 @@ export class Rank {
* @param score * @param score
* @param timestamp * @param timestamp
*/ */
private async updateRankScoreEncode(myId: string, score: number, timestamp: number, isInc = false) { private async updateRankScoreEncode(myId: myIdInter, score: number = 0, timestamp: number = 0, isInc = false) {
let newScore = score; let newScore = score;
let key = this.keyName.getName(); let key = this.keyName.getName();
if(isInc) { if (isInc) {
let oldScore = await this.getMyScore(myId); let oldScore = await this.getMyScore(myId);
newScore = oldScore + score; newScore = oldScore + score;
} }
let scoreStr = this.encodeScore(newScore, timestamp); let scoreStr = this.encodeScore(newScore, timestamp);
await redisClient().zaddAsync(key, scoreStr, myId); await redisClient().zaddAsync(key, scoreStr, this.composeFields(this.key, myId));
return score return score
} }
@@ -114,24 +242,25 @@ export class Rank {
* @param isInc * @param isInc
* @class Rank * @class Rank
*/ */
private async updateRankScoreAtom(myId: string, score: number, timestamp: number, isInc = false) { private async updateRankScoreAtom(myId: myIdInter, score: number = 0, timestamp: number = 0, isInc = false) {
let key = this.keyName.getName(); let key = this.keyName.getName();
let timeKey = this.keyName.getTimeName(); let timeKey = this.keyName.getTimeName();
let pow = Math.pow(10, this.timelen + 1); let pow = Math.pow(10, this.timelen + 1);
let newScore = 0; let newScore = 0;
// 分数zset // 分数zset
if(isInc) { if (isInc) {
newScore = await redisClient().zincrbyAsync(key, score, myId); newScore = await redisClient().zincrbyAsync(key, score, this.composeFields(this.key, myId));
} else { } else {
newScore = await redisClient().zaddAsync(key, score, myId); newScore = await redisClient().zaddAsync(key, score, this.composeFields(this.key, myId));
} }
// 时间zset // 时间zset
await redisClient().zaddAsync(timeKey, pow - 1 - Math.floor(timestamp/1000), myId); await redisClient().zaddAsync(timeKey, pow - 1 - this.handleTimestamp(timestamp), this.composeFields(this.key, myId));
return parseInt(newScore.toString()); return parseInt(newScore.toString());
} }
/** /**
* @description 设置到期时间 * @description 设置到期时间
* @param time 到期时间10位时间戳 * @param time 到期时间10位时间戳
@@ -145,58 +274,202 @@ export class Rank {
await redisClient().expireatAsync(timeKey, time); await redisClient().expireatAsync(timeKey, time);
} }
public async generMyRankWithRole(roleId: string, score: number, time: number, role?: RoleType, needReduceCe = false) { public async generMyRankWithRole(roleId: string, score: number, time: number, role?: RoleType) {
// 如果没有信息,更新玩家信息 // 如果没有信息,更新玩家信息
let param: RoleRankInfo;
let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId);
if(!hasCurUser) { if (!hasCurUser) {
if(!role) { if (!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
needReduceCe = true;
} }
let param = new RoleRankInfo(role, needReduceCe); param = new RoleRankInfo(role);
param.setInfo(0, roleId, score, time); param.setInfo(0, { roleId }, score, time);
return await this.generFields(param);
} else { } else {
const info = await redisClient().hgetAsync(this.infoKey, roleId); const info = await redisClient().hgetAsync(this.infoKey, roleId);
const userInfo = JSON.parse(info); const userInfo = JSON.parse(info);
let param = new RoleRankInfo(userInfo); param = new RoleRankInfo(userInfo);
param.setInfo(0, roleId, score, time); param.setInfo(0, { roleId }, score, time);
return await this.generFields(param);
} }
for (let extraKey of this.extraKeys) {
await this.setExInfoToParam(extraKey, param, { roleId }, {role});
}
return await this.generFields(param);
} }
public async generMyRankWithGuild(guildCode: string, score: number, time: number, guild?: GuildType) { public async generMyRankWithGuild(guildCode: string, score: number, time: number, guild?: GuildType) {
// 如果没有信息,更新玩家信息 // 如果没有信息,更新玩家信息
let param: GuildRankInfo;
let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode);
if(!hasCurUser) { if (!hasCurUser) {
if(!guild) { if (!guild) {
guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK);
} }
let param = new GuildRankInfo(guild); param = new GuildRankInfo(guild);
param.setInfo(0, guildCode, score, time); param.setInfo(0, { guildCode }, score, time);
return await this.generFields(param);
} else { } else {
const info = await redisClient().hgetAsync(this.infoKey, guildCode); const info = await redisClient().hgetAsync(this.infoKey, guildCode);
const guildInfo = JSON.parse(info); const guildInfo = JSON.parse(info);
let param = new GuildRankInfo(guildInfo); param = new GuildRankInfo(guildInfo);
param.setInfo(0, guildCode, score, time); param.setInfo(0, { guildCode }, score, time);
return await this.generFields(param); }
for (let extraKey of this.extraKeys) {
await this.setExInfoToParam(extraKey, param, { guildCode }, { guild } );
}
return await this.generFields(param);
}
public async generMyRankWithHero(roleId: string, hid: number, score: number, time: number, hero?: HeroType, role?: RoleType) {
// 如果没有信息,更新玩家信息
let param: RoleRankInfo;
let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId);
if (!hasCurUser) {
if(!role) {
role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true);
}
param = new RoleRankInfo(role);
param.setInfo(0, { roleId, hid }, score, time);
} else {
const info = await redisClient().hgetAsync(this.infoKey, roleId);
const userInfo = JSON.parse(info);
param = new RoleRankInfo(userInfo);
param.setInfo(0, { roleId, hid }, score, time);
}
for (let extraKey of this.extraKeys) {
await this.setExInfoToParam(extraKey, param, { roleId, hid }, { hero, role });
}
return await this.generFields(param);
}
private async setExInfoToParam(extraKey: string, param: RoleRankInfo | GuildRankInfo, myId: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) {
let { role, guild, hero } = db;
if (extraKey == REDIS_KEY.TOP_LINEUP_INFO) {
param = <RoleRankInfo>param;
let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId));
if (!hasCurUser) {
if (!role) {
role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true);
}
let { topLineup } = role;
let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL);
let arr = new Array<LineupParam>();
for (let { hid } of topLineup) {
let curHero = heroes.find(cur => cur.hid == hid);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
param.setTopLine(arr);
} else {
const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId));
const infoObj = JSON.parse(info);
param.setTopLine(infoObj);
}
} else if (extraKey == REDIS_KEY.HERO_INFO) {
param = <RoleRankInfo>param;
let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId));
if (!hasCurUser) {
if(!hero) {
hero = await HeroModel.findByHidAndRole(myId.hid, myId.roleId, HERO_SELECT.RANK_LINEUP);
}
let arr = new Array<LineupParam>();
let lineParam = new LineupParam(hero);
arr.push(lineParam);
if(this.key == REDIS_KEY.HERO_RANK) {
param.setSingleHero(arr);
} else {
param.setTopLine(arr);
}
} else {
const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId));
const infoObj = JSON.parse(info);
if(this.key == REDIS_KEY.HERO_RANK) {
param.setSingleHero(infoObj);
} else {
param.setTopLine(infoObj);
}
}
} else if (extraKey == REDIS_KEY.DUNGEON_LINEUP) {
param = <RoleRankInfo>param;
let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId));
if (!hasCurUser) {
if (!role) {
role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true);
}
let { dungeonWarId, dungeonHeroes } = role;
let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId);
let lineup = cur?cur.heroes: [];
let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.RANK_LINEUP);
let arr = new Array<LineupParam>();
for (let seqId of lineup) {
let curHero = heroes.find(cur => cur.seqId == seqId);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
param.setTopLine(arr);
} else {
const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId));
const infoObj = JSON.parse(info);
param.setTopLine(infoObj);
}
} else if (extraKey == REDIS_KEY.SHOW_LINEUP) {
param = <RoleRankInfo>param;
let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId));
if (!hasCurUser) {
if (!role) {
role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true);
}
let { showLineup, topLineup = [] } = role;
let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL);
let arr = new Array<LineupParam>();
if(!showLineup) showLineup = topLineup.map(cur => cur.hid);
for (let hid of showLineup) {
let curHero = heroes.find(cur => cur.hid == hid);
if (curHero) {
let param = new LineupParam(curHero);
arr.push(param);
}
}
param.setTopLine(arr);
} else {
const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId));
const infoObj = JSON.parse(info);
param.setTopLine(infoObj);
}
} }
} }
public async getRankListWithMyRank(myId: string) { public async getRankListWithMyRank(myId: myIdInter) {
let ranks = await this.getRankByRange(); let ranks = await this.getRankByRange();
let newRanks = [], newMyRank; let newRanks = [], newMyRank: RoleRankInfo | GuildRankInfo;
let myRank = ranks.find(cur => { let myRank = ranks.find(cur => {
return cur.isMyInfo(myId); return cur.isMyInfo(myId);
}); });
if(this.generFields) { if (this.generFields) {
for(let rank of ranks) { for (let rank of ranks) {
let n = await this.generFields(rank); let n = await this.generFields(rank);
newRanks.push(n); newRanks.push(n);
} }
if(myRank) { if (myRank) {
newMyRank = await this.generFields(myRank); newMyRank = await this.generFields(myRank);
} }
} }
@@ -204,44 +477,53 @@ export class Rank {
return { myRank: newMyRank, ranks: newRanks } return { myRank: newMyRank, ranks: newRanks }
} }
public async getRankByRange(from: number|string = '+inf', to: number|string = '-inf') { public async getRankByRange(from: number | string = '+inf', to: number | string = '-inf') {
let ranks = new Array<RoleRankInfo|GuildRankInfo>(); let ranks = new Array<RoleRankInfo | GuildRankInfo>();
let key = this.keyName.getName(); let key = this.keyName.getName();
if(this.isUnion) { if (this.isUnion) {
key = await this.generateUnionRank(); key = await this.generateUnionRank();
} }
const rankFromDb = await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES", "LIMIT", 0, this.limit); const rankFromDb = await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES", "LIMIT", 0, this.limit);
for(let ii = 0; ii < rankFromDb.length; ii+=2) { for (let ii = 0; ii < rankFromDb.length; ii += 2) {
const myId = rankFromDb[ii]; const field = rankFromDb[ii];
let myId = this.decodeFields(this.key, field);
const { score, time } = this.decodeScore(rankFromDb[ii + 1]); const { score, time } = this.decodeScore(rankFromDb[ii + 1]);
const info = await redisClient().hgetAsync(this.infoKey, myId); const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId));
const userInfo = JSON.parse(info); const userInfo = JSON.parse(info);
if(this.infoKey == REDIS_KEY.USER_INFO) { let param: RoleRankInfo | GuildRankInfo;
let param = new RoleRankInfo(userInfo); if (this.infoKey == REDIS_KEY.USER_INFO) {
param.setInfo(Math.floor(ii/2)+1, myId, score, time); param = new RoleRankInfo(userInfo);
ranks.push(param); param.setInfo(Math.floor(ii / 2) + 1, myId, score, time);
} else if(this.infoKey == REDIS_KEY.GUILD_INFO) { } else if (this.infoKey == REDIS_KEY.GUILD_INFO) {
let param = new GuildRankInfo(userInfo); param = new GuildRankInfo(userInfo);
param.setInfo(Math.floor(ii/2)+1, myId, score, time); param.setInfo(Math.floor(ii / 2) + 1, myId, score, time);
ranks.push(param);
} }
for (let extraKey of this.extraKeys) {
await this.setExInfoToParam(extraKey, param, myId, {});
}
ranks.push(param);
} }
return ranks return ranks
} }
// 获取我的排名 // 获取我的排名
public async getMyRank(myId: string) { public async getMyRank(myId: myIdInter) {
let key = this.keyName.getName(); let key = this.keyName.getName();
if(this.isUnion) { if (this.isUnion) {
key = await this.generateUnionRank(); key = await this.generateUnionRank();
} }
let myRank = await redisClient().zrevrankAsync(key, myId); let myRank = await redisClient().zrevrankAsync(key, this.composeFields(this.key, myId));
return myRank + 1; if(!myRank && myRank != 0) {
return 0;
} else {
return myRank + 1;
}
} }
// 获取排名第几名的信息 // 获取排名第几名的信息
@@ -253,11 +535,11 @@ export class Rank {
// 获取排名第几名的信息 // 获取排名第几名的信息
public async getMyScore(myId: string) { public async getMyScore(myId: myIdInter) {
let key = this.keyName.getName(); let key = this.keyName.getName();
let score = await redisClient().zscoreAsync(key, myId); let score = await redisClient().zscoreAsync(key, this.composeFields(this.key, myId));
if(!score) score = 0; if (!score) score = 0;
if(!this.isUnion) { if (!this.isUnion) {
let result = this.decodeScore(score.toString()); let result = this.decodeScore(score.toString());
score = result.score; score = result.score;
} }
@@ -265,9 +547,9 @@ export class Rank {
} }
// 从排行榜中移除 // 从排行榜中移除
public async removeFromRank(myId: string) { public async removeFromRank(myId: myIdInter) {
let key = this.keyName.getName(); let key = this.keyName.getName();
await redisClient().zremAsync(key, myId); await redisClient().zremAsync(key, this.composeFields(this.key, myId));
return true; return true;
} }
@@ -275,12 +557,12 @@ export class Rank {
private async generateUnionRank() { private async generateUnionRank() {
let unionKey = this.keyName.getUnionName(); // 联合的key let unionKey = this.keyName.getUnionName(); // 联合的key
let existsKey = await redisClient().existsAsync(unionKey); let existsKey = await redisClient().existsAsync(unionKey);
if(!existsKey) { if (!existsKey) {
let originKey = this.keyName.getName(); let originKey = this.keyName.getName();
let timeKey = this.keyName.getTimeName(); let timeKey = this.keyName.getTimeName();
let pow = Math.pow(10, this.timelen + 1); let pow = Math.pow(10, this.timelen + 1);
await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1); await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1);
await redisClient().expireAsync(unionKey, this.unionRankLife); // 10秒更新一次 await redisClient().expireAsync(unionKey, this.unionRankLife); // 10秒更新一次
} }
return unionKey; return unionKey;
@@ -290,7 +572,7 @@ export class Rank {
private encodeScore(score: number, timestamp: number) { private encodeScore(score: number, timestamp: number) {
let timelen = this.timelen; let timelen = this.timelen;
let pow = Math.pow(10, timelen + 1); let pow = Math.pow(10, timelen + 1);
return score * pow + pow - 1 - Math.floor(timestamp/1000) return score * pow + pow - 1 - this.handleTimestamp(timestamp)
} }
private decodeScore(num: string) { private decodeScore(num: string) {
@@ -299,7 +581,127 @@ export class Rank {
let _num = parseInt(num); let _num = parseInt(num);
return { return {
time: pow - _num % pow, time: pow - _num % pow,
score: Math.floor(_num/pow) score: Math.floor(_num / pow)
}; };
} }
private handleTimestamp(timestamp: number = 0) {
let l = timestamp.toString().length;
if(l > this.timelen) {
timestamp = Math.floor(timestamp / Math.pow(10, l - this.timelen));
}
return timestamp
}
}
/**
* 从数据库内获取排行榜存入redis
* @param type 排行榜类型
* @param serverId 分服
*/
export async function setRankRedisFromDb(type: string, args?: {serverId?: number}) {
if(type == REDIS_KEY.TOWER_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('tower', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { 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(type, serverId);
let r = new Rank(type, { serverId });
for(let guild of ranks) {
await r.setRankWithGuildInfo(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild);
}
} else if (type == REDIS_KEY.GUILD_LV_RANK) {
let serverId = args.serverId;
let ranks = await GuildModel.getRank(type, serverId);
let r = new Rank(type, { serverId });
for(let guild of ranks) {
await r.setRankWithGuildInfo(guild.code, guild.lv, guild.lvUpdateTime, 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(type, {});
for(let {roleId, role: _role, score, updatedAt } of ranks) {
let role = <RoleType>_role;
if (!role) {
continue;
}
await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role);
}
} else if (type == REDIS_KEY.TOP_LINEUP_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('topLineup', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId }, false, 0);
for(let role of ranks) {
// console.log(roleId);
await r.setRankWithRoleInfo(role.roleId, role.topLineupCe, role.updatedAt.getTime(), role);
}
} else if (type == REDIS_KEY.TOP_HERO_RANK) {
let serverId = args.serverId;
let ranks = await HeroModel.getAllRank(serverId, HERO_SELECT.RANK_LINEUP);
let r = new Rank(type, { serverId }, false, 0);
for(let hero of ranks) {
await r.setRankWithHeroInfo(hero.roleId, hero.hid, hero.ce, hero.updatedAt.getTime(), hero);
}
} else if (type == REDIS_KEY.HERO_NUM_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('heroNum', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId });
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.heroNum, role.heroNumUpdatedAt, role );
}
} else if (type == REDIS_KEY.USER_LV) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('lv', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId });
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.lv, role.updatedAt.getTime(), role);
}
} else if (type == REDIS_KEY.SUM_CE_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('ce', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId }, false, 0);
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.ce, role.updatedAt.getTime(), role);
}
} else if (type == REDIS_KEY.DUNGEON_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('dungeon', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId });
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.dungeonWarId, role.dungeonUpdatedAt, role);
}
} else if (type == REDIS_KEY.MAIN_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('main', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId });
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.mainWarId, role.mainUpdatedAt, role);
}
} else if (type == REDIS_KEY.MAIN_ELITE_RANK) {
let serverId = args.serverId;
let ranks = await RoleModel.getRank('mainElite', serverId, ROLE_SELECT.RANK);
let r = new Rank(type, { serverId });
for(let role of ranks) {
await r.setRankWithRoleInfo(role.roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role);
}
} else if (type == REDIS_KEY.HERO_RANK) {
let serverId = args.serverId;
for(let hid of gameData.dicMyHeroes) {
let ranks = await HeroModel.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP);
let r = new Rank(type, { serverId, hid }, false, 0);
for(let hero of ranks) {
await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero);
}
}
}
} }

View File

@@ -1,16 +1,12 @@
import { GOOD_QUALITY, REDIS_RANK_TO_INFO, COM_BTL_QUALITY, GUILD_ACTIVITY_TYPE, GUILD_ACTIVITY_STATUS } from './../consts'; import { COM_BTL_QUALITY, GUILD_ACTIVITY_TYPE } from './../consts';
import { RoleModel, RoleType } from "../db/Role";
import * as Redis from 'redis'; import * as Redis from 'redis';
import {REDIS_KEY} from '../consts' import {REDIS_KEY} from '../consts'
import { GameModel } from "../db/Game"; import { GameModel } from "../db/Game";
import { promisifyAll } from 'bluebird'; import { promisifyAll } from 'bluebird';
import { pinus } from 'pinus'; import { pinus } from 'pinus';
import { PvpDefenseModel } from '../db/PvpDefense'; import { GuildRankParam, GuildLeader, RankParam, LineupParam } from '../domain/rank';
import { SystemConfigModel } from '../db/SystemConfig';
import { GuildRankParam, GuildLeader, RankParam } from '../domain/rank';
import { GuildModel } from '../db/Guild';
import { comBtlRanges } from '../pubUtils/gamedata'; import { comBtlRanges } from '../pubUtils/gamedata';
import { Rank } from './rankService'; import { setRankRedisFromDb } from './rankService';
/** /**
* 在服务重新启动时将信息存入redis * 在服务重新启动时将信息存入redis
*/ */
@@ -19,9 +15,22 @@ export async function initAllRank() {
await delKeys(REDIS_KEY.ONLINE_USERS); await delKeys(REDIS_KEY.ONLINE_USERS);
await delKeys(REDIS_KEY.USER_INFO); await delKeys(REDIS_KEY.USER_INFO);
await delKeys(REDIS_KEY.GUILD_INFO); await delKeys(REDIS_KEY.GUILD_INFO);
await delKeys(REDIS_KEY.TOP_LINEUP_INFO);
await delKeys(REDIS_KEY.HERO_INFO);
await delKeys(REDIS_KEY.PVP_RANK); await delKeys(REDIS_KEY.PVP_RANK);
await delKeys(REDIS_KEY.TOWER_RANK); await delKeys(REDIS_KEY.TOWER_RANK);
await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK); await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK);
await delKeys(REDIS_KEY.TOP_LINEUP_RANK);
await delKeys(REDIS_KEY.TOP_HERO_RANK);
await delKeys(REDIS_KEY.HERO_NUM_RANK);
await delKeys(REDIS_KEY.USER_LV);
await delKeys(REDIS_KEY.SUM_CE_RANK);
await delKeys(REDIS_KEY.DUNGEON_RANK);
await delKeys(REDIS_KEY.DUNGEON_LINEUP);
await delKeys(REDIS_KEY.MAIN_RANK);
await delKeys(REDIS_KEY.MAIN_ELITE_RANK);
await delKeys(REDIS_KEY.HERO_RANK);
await delKeys(REDIS_KEY.SHOW_LINEUP);
for(let {id} of serverList) { for(let {id} of serverList) {
await initRank(id); await initRank(id);
} }
@@ -34,8 +43,18 @@ export async function initAllRank() {
*/ */
export async function initRank(serverId: number) { export async function initRank(serverId: number) {
// console.log('*****', 'initRank') // console.log('*****', 'initRank')
await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, {serverId}); await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId}); await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.GUILD_LV_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.TOP_LINEUP_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.TOP_HERO_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.HERO_NUM_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.USER_LV, { serverId });
await setRankRedisFromDb(REDIS_KEY.SUM_CE_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.DUNGEON_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.MAIN_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.MAIN_ELITE_RANK, { serverId });
await setRankRedisFromDb(REDIS_KEY.HERO_RANK, { serverId });
} }
@@ -81,7 +100,7 @@ async function delKeys(key: string) {
return keys return keys
} }
export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam) { export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam|LineupParam[]) {
let value = JSON.stringify(params); let value = JSON.stringify(params);
return await redisClient().hsetAsync(key, roleId, value); return await redisClient().hsetAsync(key, roleId, value);
} }
@@ -99,42 +118,6 @@ export async function updateUserInfo(key: string, roleId: string, arr: Array<{fi
/********排行榜结束 */ /********排行榜结束 */
/**
* 从数据库内获取排行榜存入redis
* @param type 排行榜类型
* @param serverId 分服
*/
async function setRankRedisFromDb(type: string, args?: {serverId?: number}) {
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 = <RoleType>_role;
if (!role) {
continue;
}
await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role);
}
}
}
/**************** 寻宝相关 start */ /**************** 寻宝相关 start */

View File

@@ -146,7 +146,7 @@ export async function checkResult(pvpDefense: PvpDefenseType, seasonNum: number,
let pvpHeroRewards = getPvpHeroRewards(); let pvpHeroRewards = getPvpHeroRewards();
if (!rankLv) { if (!rankLv) {
let r = new Rank(REDIS_KEY.PVP_RANK, {}); let r = new Rank(REDIS_KEY.PVP_RANK, {});
rankLv = await r.getMyRank(pvpDefense.roleId);// 获得排行榜排名 rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名
} }
let oldPLv = getLvByScore(pvpDefense.heroScores);//结算前玩家的pvp等级 let oldPLv = getLvByScore(pvpDefense.heroScores);//结算前玩家的pvp等级
let { challengeCnt, challengeRefTime } = pvpDefense; let { challengeCnt, challengeRefTime } = pvpDefense;

View File

@@ -0,0 +1,87 @@
import { Client } from './Client';
import 'mocha';
import { PinusWSClient } from 'pinus-robot-plugin';
import { expect } from 'chai';
import { checkSuccessResponse } from './CheckPatten';
import { BLOCK_OPEATE, RANK_TYPE } from '../app/consts';
describe('排行榜测试', function() {
let pinusClient: PinusWSClient;
let roleInfo;
beforeEach(function(done) {
const c = new Client();
const timer = setInterval(() => {
if (c.client) {
pinusClient = c.client;
roleInfo = c.roleInfo;
clearInterval(timer);
done();
}
}, 500);
});
afterEach(function(done) {
pinusClient.disconnect();
// disconnect 后等待 500ms供服务器清理环境、退出频道等
setTimeout(() => {
done();
}, 500);
});
it('获取玩家最强阵容排行榜', function(done) {
pinusClient.request('role.rankHandler.getRank', { type: RANK_TYPE.TOP_LINTUP } , (res) => {
checkParamWithLineup(res);
done();
});
});
it('获取玩家最强武将排行榜', function(done) {
pinusClient.request('role.rankHandler.getRank', { type: RANK_TYPE.TOP_HERO } , (res) => {
checkParamWithLineup(res);
done();
});
});
});
function checkParamWithLineup(res) {
checkSuccessResponse(res);
expect(res.data.type).to.be.a('number');
expect(res.data.ranks).to.be.a('array');
expect(res.data.myRank).to.be.an('object');
checkRankParamWithLineup(res.data.myRank);
res.data.ranks.forEach(cur => {
checkRankParamWithLineup(cur);
})
}
function checkRankParamWithLineup(data) {
checkBasicParam(data);
expect(data.lineup).to.be.a('array');
data.lineup.forEach(cur => {
checkLineup(cur);
})
}
function checkBasicParam(data) {
expect(data.rank).to.be.a('number');
expect(data.num).to.be.a('number');
expect(data.roleId).to.be.a('string');
expect(data.roleName).to.be.a('string');
expect(data.head).to.be.a('number');
expect(data.frame).to.be.a('number');
expect(data.spine).to.be.a('number');
expect(data.lv).to.be.a('number');
expect(data.guildName).to.be.a('string');
expect(data.ce).to.be.a('number');
}
function checkLineup(hero) {
expect(hero.hid).to.be.a('number');
expect(hero.star).to.be.a('number');
expect(hero.colorStar).to.be.a('number');
expect(hero.lv).to.be.a('number');
expect(hero.quality).to.be.a('number');
expect(hero.job).to.be.a('number');
}

View File

@@ -33,6 +33,7 @@ import { FriendShipModel } from '@db/FriendShip';
import { FriendApplyModel } from '@db/FriendApply'; import { FriendApplyModel } from '@db/FriendApply';
import { FriendRelationModel } from '@db/FriendRelation'; import { FriendRelationModel } from '@db/FriendRelation';
import { unlockFigure } from '@pubUtils/itemUtils'; import { unlockFigure } from '@pubUtils/itemUtils';
import { nowSeconds } from '@pubUtils/timeUtil';
/** /**
* Test Service * Test Service
@@ -268,6 +269,7 @@ export default class GMUsers extends Service {
try { try {
for(let heroInfo of heroInfos) { for(let heroInfo of heroInfos) {
let hero = await HeroModel.createHero(heroInfo); let hero = await HeroModel.createHero(heroInfo);
await RoleModel.incRoleInfo(heroInfo.roleId, { heroNum: 1 }, { heroNumUpdatedAt: nowSeconds() });
await unlockFigure(heroInfo.roleId, [{ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }]); // 解锁头像 await unlockFigure(heroInfo.roleId, [{ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: heroInfo.hid }]); // 解锁头像
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, heroInfo.roleId, hero, {}); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, heroInfo.roleId, hero, {});
} }

View File

@@ -1,7 +1,7 @@
export enum ROLE_SELECT { export enum ROLE_SELECT {
// 初始登录数据 // 初始登录数据
ENTRY = 'serverId userInfo.uid userInfo.tel userInfo.serverType ce topLineup topLineupCe teraphs roleId roleName tili lv exp gold coin vLv title hasGuild funcs eventStatus heads head frames frame spines spine guildCode frdCnt showLineup', ENTRY = 'serverId userInfo.uid userInfo.tel userInfo.serverType ce topLineup topLineupCe teraphs roleId roleName tili lv exp gold coin vLv title hasGuild funcs eventStatus heads head frames frame spines spine guildCode frdCnt showLineup updatedAt',
// 玩家列表显示基础数据 // 玩家列表显示基础数据
SHOW_SIMPLE = 'roleId roleName ce head frame spine lv title job quitTime loginTime vLv guildName serverId userInfo.serverType', SHOW_SIMPLE = 'roleId roleName ce head frame spine lv title job quitTime loginTime vLv guildName serverId userInfo.serverType',
// 显示申请需要的信息 // 显示申请需要的信息
@@ -14,12 +14,14 @@ export enum ROLE_SELECT {
COM_BATTLE = 'lv head frame spine topLineupCe', 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' RANK = 'roleId roleName lv vLv head frame spine title guildName ce isReducedCe topLineup towerLv towerUpTime topLineupCe heroNum updatedAt heroNumUpdatedAt dungeonWarId dungeonUpdatedAt dungeonHeroes mainWarId mainUpdatedAt mainEliteWarId mainEliteUpdatedAt showLineup',
}; };
export enum HERO_SELECT { export enum HERO_SELECT {
ENTRY = '-attr', ENTRY = '-attr',
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins attr' HERO_DETAIL = 'roleId roleName hid hName ce isReducedCe lv star colorStar quality job skins attr',
// 排行榜中lineup字段
RANK_LINEUP = 'seqId roleId hid star colorStar lv quality job ce isReducedCe updatedAt'
} }
export enum EQUIP_SELECT { export enum EQUIP_SELECT {
@@ -40,7 +42,7 @@ export enum GUILD_SELECT {
// 获得邀请列表 // 获得邀请列表
INVITED_MEMBER = '_id code isMemberMax +invitedMembers +inviteTime', INVITED_MEMBER = '_id code isMemberMax +invitedMembers +inviteTime',
// 排行榜字段 // 排行榜字段
RANK = 'code name icon lv memberCnt leader' RANK = 'code name icon lv memberCnt leader leader activeWeekly activeUpdateTime'
} }
export enum FRIEND_SHIP_SELECT { export enum FRIEND_SHIP_SELECT {

View File

@@ -226,20 +226,34 @@ export const DEFAULT_HERO_LV = 1;
export const FIX_SMS_CODE_TELS = ['18855953630', '13911134885', '15167549151', '15618654010', '15167549151', '18342915387', '15000250967']; export const FIX_SMS_CODE_TELS = ['18855953630', '13911134885', '15167549151', '15618654010', '15167549151', '18342915387', '15000250967'];
export const REDIS_KEY = { export const REDIS_KEY = {
USER_INFO: "userInfo", // 玩家缓存信息 USER_INFO: "userInfo", // 玩家缓存信息
TOWER_RANK: "towerRank", // 天梯排行榜 TOWER_RANK: "towerRank", // 天梯排行榜
COM_TEAM_SEARCH_PRE: 'comTeamSerQ', // 匹配中的玩家,按品质分 COM_TEAM_SEARCH_PRE: 'comTeamSerQ', // 匹配中的玩家,按品质分
PVP_RANK: "pvpRank", // pvp排行榜 PVP_RANK: "pvpRank", // pvp排行榜
GUILD_INFO: "guildInfo", // 公会信息 GUILD_INFO: "guildInfo", // 公会信息
GUILD_ACTIVE_RANK: "guildActiveRank", // 公会周活跃排行榜 GUILD_ACTIVE_RANK: "guildActiveRank", // 公会周活跃排行榜
DB_GAME: 'db_game', // 服务器列表 DB_GAME: 'dbGame', // 服务器列表
ONLINE_USERS: 'onlineUsers', // 在线用户情况 ONLINE_USERS: 'onlineUsers', // 在线用户情况
CHANNEL_SERVERS: 'chat:channelServers', // 渠道对应的 chat 服务器 Id, CHANNEL_SERVERS: 'chat:channelServers', // 渠道对应的 chat 服务器 Id,
USER_GATE_ACTIVITY: 'usrGateAct', // 蛮夷入侵玩家排行 USER_GATE_ACTIVITY: 'usrGateAct', // 蛮夷入侵玩家排行
GATE_ACTIVITY: 'gateAct', // 蛮夷入侵军团排行 GATE_ACTIVITY: 'gateAct', // 蛮夷入侵军团排行
USER_CITY_ACTIVITY: 'usrCityAct', // 诸侯混战玩家排行 USER_CITY_ACTIVITY: 'usrCityAct', // 诸侯混战玩家排行
CITY_ACTIVITY: 'cityAct', // 诸侯混战军团排行 CITY_ACTIVITY: 'cityAct', // 诸侯混战军团排行
RACE_ACTIVITY: 'raceAct', // 粮草先行军团排行 RACE_ACTIVITY: 'raceAct', // 粮草先行军团排行
TOP_LINEUP_INFO: 'topLineInfo', // 最强阵容数据
TOP_LINEUP_RANK: 'topLineRank', // 最强阵容排行
TOP_HERO_RANK: 'topHeroRank', // 最强武将排行
HERO_INFO: 'heroInfo', // 最强武将信息
HERO_NUM_RANK: 'heroNum', // 武将数量排行
USER_LV: 'usrLv', // 主公等级排行榜
SUM_CE_RANK: 'sumCeRank', // 总战力排名
DUNGEON_RANK: 'dungeonRank', // 秘境排名
DUNGEON_LINEUP: 'dungeonLineup', // 秘境通关阵容
MAIN_RANK: 'mainRank', // 主线通关排名
MAIN_ELITE_RANK: 'mainEliteRank', // 精英通关排名
GUILD_LV_RANK: "guildLvRank", // 公会等级排行榜
HERO_RANK: "heroRank", // 武将排行榜
SHOW_LINEUP: "showLineup", // 展示阵容
} }
// 各排行榜对应hash的key // 各排行榜对应hash的key
@@ -247,13 +261,97 @@ export const REDIS_RANK_TO_INFO = new Map([
[REDIS_KEY.TOWER_RANK, REDIS_KEY.USER_INFO], [REDIS_KEY.TOWER_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.PVP_RANK, REDIS_KEY.USER_INFO], [REDIS_KEY.PVP_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.GUILD_ACTIVE_RANK, REDIS_KEY.GUILD_INFO], [REDIS_KEY.GUILD_ACTIVE_RANK, REDIS_KEY.GUILD_INFO],
[REDIS_KEY.GUILD_LV_RANK, REDIS_KEY.GUILD_INFO],
[REDIS_KEY.GATE_ACTIVITY, REDIS_KEY.GUILD_INFO], [REDIS_KEY.GATE_ACTIVITY, REDIS_KEY.GUILD_INFO],
[REDIS_KEY.USER_GATE_ACTIVITY, REDIS_KEY.USER_INFO], [REDIS_KEY.USER_GATE_ACTIVITY, REDIS_KEY.USER_INFO],
[REDIS_KEY.CITY_ACTIVITY, REDIS_KEY.GUILD_INFO], [REDIS_KEY.CITY_ACTIVITY, REDIS_KEY.GUILD_INFO],
[REDIS_KEY.USER_CITY_ACTIVITY, REDIS_KEY.USER_INFO], [REDIS_KEY.USER_CITY_ACTIVITY, REDIS_KEY.USER_INFO],
[REDIS_KEY.RACE_ACTIVITY, REDIS_KEY.GUILD_INFO] [REDIS_KEY.RACE_ACTIVITY, REDIS_KEY.GUILD_INFO],
[REDIS_KEY.TOP_LINEUP_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.TOP_HERO_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.HERO_NUM_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.USER_LV, REDIS_KEY.USER_INFO],
[REDIS_KEY.SUM_CE_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.DUNGEON_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.MAIN_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.MAIN_ELITE_RANK, REDIS_KEY.USER_INFO],
[REDIS_KEY.HERO_RANK, REDIS_KEY.USER_INFO]
]); ]);
export const REDIS_RANK_TO_EXTRA = new Map([
[REDIS_KEY.TOP_LINEUP_RANK, [REDIS_KEY.TOP_LINEUP_INFO]],
[REDIS_KEY.TOP_HERO_RANK, [REDIS_KEY.HERO_INFO]],
[REDIS_KEY.DUNGEON_RANK, [REDIS_KEY.DUNGEON_LINEUP]],
[REDIS_KEY.HERO_RANK, [REDIS_KEY.HERO_INFO, REDIS_KEY.SHOW_LINEUP]]
]);
// 排行榜类型
export enum RANK_TYPE {
TOP_LINTUP = 1, // 最强阵容战力
TOP_HERO = 2, // 最强武将
HERO_NUM = 3, // 武将数量
USER_LV = 4, // 主公等级
SUM_CE = 5, // 总战力
TOWER = 6, // 镇念塔
DUNGEON = 7, // 秘境
MAIN = 8, // 主线
MAIN_ELITE = 9, // 精英
GUILD_LV = 10, // 军团按等级排序
GUILD_ACTIVE = 11, // 军团活跃度排序
HERO = 12, // 武将排行
}
// 接口中的排行榜类型对应的redis中的key
export const RANK_TYPE_TO_KEY = new Map([
[RANK_TYPE.TOP_LINTUP, REDIS_KEY.TOP_LINEUP_RANK],
[RANK_TYPE.TOP_HERO, REDIS_KEY.TOP_HERO_RANK],
[RANK_TYPE.HERO_NUM, REDIS_KEY.HERO_NUM_RANK],
[RANK_TYPE.USER_LV, REDIS_KEY.USER_LV],
[RANK_TYPE.SUM_CE, REDIS_KEY.SUM_CE_RANK],
[RANK_TYPE.TOWER, REDIS_KEY.TOWER_RANK],
[RANK_TYPE.DUNGEON, REDIS_KEY.DUNGEON_RANK],
[RANK_TYPE.MAIN, REDIS_KEY.MAIN_RANK],
[RANK_TYPE.MAIN_ELITE, REDIS_KEY.MAIN_ELITE_RANK],
[RANK_TYPE.GUILD_LV, REDIS_KEY.GUILD_LV_RANK],
[RANK_TYPE.GUILD_ACTIVE, REDIS_KEY.GUILD_ACTIVE_RANK],
[RANK_TYPE.HERO, REDIS_KEY.HERO_RANK]
]);
// field处理方法
export enum COMPOSE_FIELD_TYPE {
ROLE = 1,
GUILD = 2,
ROLE_HERO = 3
}
// 各个key的field如何处理
export const KEY_TO_COMPOSE_FIELD = new Map([
[REDIS_KEY.USER_INFO, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.TOWER_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.PVP_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.GUILD_INFO, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.GUILD_ACTIVE_RANK, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.GUILD_LV_RANK, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.USER_GATE_ACTIVITY, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.GATE_ACTIVITY, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.USER_CITY_ACTIVITY, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.CITY_ACTIVITY, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.RACE_ACTIVITY, COMPOSE_FIELD_TYPE.GUILD],
[REDIS_KEY.TOP_LINEUP_INFO, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.TOP_LINEUP_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.TOP_HERO_RANK, COMPOSE_FIELD_TYPE.ROLE_HERO],
[REDIS_KEY.HERO_INFO, COMPOSE_FIELD_TYPE.ROLE_HERO],
[REDIS_KEY.HERO_NUM_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.USER_LV, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.DUNGEON_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.DUNGEON_LINEUP, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.MAIN_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.MAIN_ELITE_RANK, COMPOSE_FIELD_TYPE.ROLE],
[REDIS_KEY.HERO_RANK, COMPOSE_FIELD_TYPE.ROLE_HERO],
[REDIS_KEY.SHOW_LINEUP, COMPOSE_FIELD_TYPE.ROLE],
]);
export const FUNC_OPT_TYPE = { export const FUNC_OPT_TYPE = {
LEVEL_UP: 1, LEVEL_UP: 1,
BATTLE_END: 2 BATTLE_END: 2

View File

@@ -2,7 +2,7 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref } from '@typegoose/typegoose'; import { index, getModelForClass, prop, DocumentType, Ref } from '@typegoose/typegoose';
import Role, { RoleType } from './Role'; import Role, { RoleType } from './Role';
import { genCode } from '../pubUtils/util'; import { genCode } from '../pubUtils/util';
import { GUILD_STRUCTURE, GUILD_STATUS, GUILD_PER_PAGE, GUILD_SELECT } from '../consts'; import { GUILD_STRUCTURE, GUILD_STATUS, GUILD_PER_PAGE, GUILD_SELECT, RANK_TYPE, REDIS_KEY } from '../consts';
import { getCurWeekTime, nowSeconds } from '../pubUtils/timeUtil'; import { getCurWeekTime, nowSeconds } from '../pubUtils/timeUtil';
import { reduceCe } from '../pubUtils/util'; import { reduceCe } from '../pubUtils/util';
@@ -28,6 +28,9 @@ export default class Guild extends BaseModel {
@prop({ required: true, default: 1 }) @prop({ required: true, default: 1 })
lv: number; lv: number;
@prop({ required: true, default: 1 })
lvUpdateTime: number;
@prop({ required: true, default: 1 }) @prop({ required: true, default: 1 })
memberCnt: number; memberCnt: number;
@@ -98,7 +101,7 @@ export default class Guild extends BaseModel {
public static async createGuild(params: { name: string, icon: number, notice: string }, role: RoleType, serverId: number) { public static async createGuild(params: { name: string, icon: number, notice: string }, role: RoleType, serverId: number) {
const doc = new GuildModel(); const doc = new GuildModel();
const update = Object.assign(doc.toJSON(), params, { leader: role._id, members: [role.roleId], guildCe: role.ce, serverId }); const update = Object.assign(doc.toJSON(), params, { leader: role._id, members: [role.roleId], guildCe: role.ce, serverId, lvUpdateTime: nowSeconds() });
delete update._id; delete update._id;
const code = genCode(6); const code = genCode(6);
const result: GuildType = await GuildModel.findOneAndUpdate({ code }, update, { upsert: true, new: true }) const result: GuildType = await GuildModel.findOneAndUpdate({ code }, update, { upsert: true, new: true })
@@ -132,12 +135,19 @@ export default class Guild extends BaseModel {
} }
public static async getRank(serverId: number, page: number = 1) { public static async getRank(type: string, serverId: number, page: number = 1) {
let sort = {}, condition = {};
switch(type) {
case REDIS_KEY.GUILD_LV_RANK:
sort = { lv: -1, lvUpdateTime: 1 }; break;
case REDIS_KEY.GUILD_ACTIVE_RANK:
sort = { activeWeekly: -1, activeUpdateTime: 1 }; condition = { activeWeekly: { $gt: 0 } }; break;
}
const guildList: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, serverId }, {_id: 0}) const guildList: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, serverId, ...condition }, {_id: 0})
.sort({ activeWeekly: -1, activeUpdateTime: -1 }) .sort(sort)
.limit(100).skip((page - 1) * 100) .limit(100).skip((page - 1) * 100)
.select('code icon name lv leader activeWeekly activeUpdateTime') .select(GUILD_SELECT.RANK)
.populate('leader', {roleName: 1, title: 1, frame: 1, head: 1, spine: 1, lv: 1, _id: 0}, 'Role') .populate('leader', {roleName: 1, title: 1, frame: 1, head: 1, spine: 1, lv: 1, _id: 0}, 'Role')
.lean({ virtuals: true }); .lean({ virtuals: true });
return guildList; return guildList;
@@ -189,7 +199,7 @@ export default class Guild extends BaseModel {
public static async upStructure(code: string, id: number, cost: number, select?: string) { public static async upStructure(code: string, id: number, cost: number, select?: string) {
if (id == GUILD_STRUCTURE.ARMY_CENTER) { if (id == GUILD_STRUCTURE.ARMY_CENTER) {
const result: GuildType = await GuildModel.findOneAndUpdate({ code, 'structure.id': id, fund: { $gte: cost } }, { $inc: { 'structure.$.lv': 1, lv: 1, fund: -1 * cost }, $set: { isMemberMax: false } }, { new: true }).select(select).lean(); const result: GuildType = await GuildModel.findOneAndUpdate({ code, 'structure.id': id, fund: { $gte: cost } }, { $inc: { 'structure.$.lv': 1, lv: 1, fund: -1 * cost }, $set: { isMemberMax: false, lvUpdateTime: nowSeconds() } }, { new: true }).select(select).lean();
return result; return result;
} else { } else {
const result: GuildType = await GuildModel.findOneAndUpdate({ code, 'structure.id': id, fund: { $gte: cost } }, { $inc: { 'structure.$.lv': 1, fund: -1 * cost } }, { new: true }).select(select).lean(); const result: GuildType = await GuildModel.findOneAndUpdate({ code, 'structure.id': id, fund: { $gte: cost } }, { $inc: { 'structure.$.lv': 1, fund: -1 * cost } }, { new: true }).select(select).lean();

View File

@@ -4,6 +4,7 @@ import Equip, { } from './Equip';
import { CounterModel } from './Counter'; import { CounterModel } from './Counter';
import { COUNTER, EQUIP_TYPE } from '../consts'; import { COUNTER, EQUIP_TYPE } from '../consts';
import { reduceCe } from '../pubUtils/util'; import { reduceCe } from '../pubUtils/util';
import { nowSeconds } from '../pubUtils/timeUtil';
class CeAttrData { class CeAttrData {
@prop({ required: true }) @prop({ required: true })
@@ -90,6 +91,8 @@ export default class Hero extends BaseModel {
lv: number; // 武将等级 lv: number; // 武将等级
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) }) @prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
ce: number; // 武将战力 ce: number; // 武将战力
@prop({ required: false, set: (val: boolean) => val, get: () => true })
isReducedCe: boolean; // 如果战力没有缩过就会返回false缩过了就会返回true
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
historyCe: number; // 武将历史最高战力 historyCe: number; // 武将历史最高战力
@prop({required: true, type: CeAttrData, default: [], _id: false }) @prop({required: true, type: CeAttrData, default: [], _id: false })
@@ -190,7 +193,7 @@ export default class Hero extends BaseModel {
return hero; return hero;
} }
public static async createHero(heroInfo: {roleId: string, serverId: number, roleName: string, hid: number, hName: string, star: number, quality: number, job: number, lv?: number, exp?: number, skins:Skin[]}, lean = true) { public static async createHero(heroInfo: HeroUpdate, lean = true) {
const doc = new HeroModel(); const doc = new HeroModel();
const seqId = await CounterModel.getNewCounter(COUNTER.HID)||-1; const seqId = await CounterModel.getNewCounter(COUNTER.HID)||-1;
const update = Object.assign(doc.toJSON(), heroInfo, {seqId}); const update = Object.assign(doc.toJSON(), heroInfo, {seqId});
@@ -267,7 +270,17 @@ export default class Hero extends BaseModel {
return user; return user;
} }
public static async getRank(hid: number, serverId: number, select?: string, limit = 100) { public static async getAllRank(serverId: number, select?: string, limit = 200) {
let result: HeroType[] = await HeroModel.find({serverId}, { _id: false} ).select(select).limit(limit).sort({ ce: -1, updatedAt: 1 }).lean({ getters: true });
return result;
}
public static async getMyTopHero(roleId: string, select?: string) {
let result: HeroType = await HeroModel.findOne({ roleId }, { _id: false} ).select(select).sort({ ce: -1, updatedAt: 1 }).lean({ getters: true });
return result;
}
public static async getRank(hid: number, serverId: number, select?: string, limit = 200) {
let result: HeroType[] = await HeroModel.find({serverId, hid}, { _id: false} ).select(select).limit(limit).lean({ getters: true }); let result: HeroType[] = await HeroModel.find({serverId, hid}, { _id: false} ).select(select).limit(limit).lean({ getters: true });
return result; return result;
} }

View File

@@ -160,6 +160,8 @@ export default class Role extends BaseModel {
topLineup: Array<TopHero>; // 总战力 topLineup: Array<TopHero>; // 总战力
@prop({ required: true, default: 100 }) @prop({ required: true, default: 100 })
tili: number; // 体力值 tili: number; // 体力值
@prop({ required: false, set: (val: boolean) => val, get: () => true })
isReducedCe: boolean; // 如果战力没有缩过就会返回false缩过了就会返回true
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
vLv: number; // VIP 等级 vLv: number; // VIP 等级
@@ -264,6 +266,26 @@ export default class Role extends BaseModel {
recFrdApplyCnt: number; // 玩家收取好友申请数量 recFrdApplyCnt: number; // 玩家收取好友申请数量
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
updatedMailAt: number; updatedMailAt: number;
// 排行相关
@prop({ required: true, default: 0 })
heroNum: number; // 武将数量
@prop({ required: true, default: 0 })
heroNumUpdatedAt: number; // 武将数量更新时间
@prop({ required: true, default: 0 })
dungeonWarId: number; // 秘境通关关卡
@prop({ required: true, default: 0 })
dungeonUpdatedAt: number; // 秘境通关时间
@prop({ required: true, default: 0 })
mainWarId: number; // 主线通关关卡
@prop({ required: true, default: 0 })
mainUpdatedAt: number; // 秘境通关时间
@prop({ required: true, default: 0 })
mainEliteWarId: number; // 精英通关关卡
@prop({ required: true, default: 0 })
mainEliteUpdatedAt: number; // 精英通关时间
public static async findAllByUid(uid: number, getters = false, virtuals = true) { public static async findAllByUid(uid: number, getters = false, virtuals = true) {
const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId head frame spine lv updatedAt').lean({ getters, virtuals}); const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId head frame spine lv updatedAt').lean({ getters, virtuals});
return role; return role;
@@ -436,13 +458,31 @@ export default class Role extends BaseModel {
} }
// 获取排行榜 // 获取排行榜
public static async getRank(type: string, serverId: number, fields: string[], page = 1, limit = 100) { public static async getRank(type: string, serverId: number, select?: string, page = 1, limit = 200) {
let sortBy = {}; let sortBy = {};
if(type == 'tower') { let condition = {};
sortBy['towerLv'] = -1; switch(type) {
sortBy['towerUpTime'] = 1; case 'tower':
sortBy = { towerLv: -1, towerUpTime: 1 }; condition = { towerLv: { $gt: 0 } }; break;
case 'topLineup':
sortBy = { topLineupCe: -1, updatedAt: 1 }; condition = { topLineupCe: { $gt: 0 } }; break;
case 'heroNum':
sortBy = { heroNum: -1, heroNumUpdatedAt: 1 }; condition = { heroNum: { $gt: 0 } }; break;
case 'lv':
sortBy = { lv: -1, updatedAt: 1 }; condition = { lv: { $gt: 0 } }; break;
case 'ce':
sortBy = { ce: -1, updatedAt: 1 }; condition = { ce: { $gt: 0 } }; break;
case 'dungeon':
sortBy = { dungeonWarId: -1, dungeonUpdatedAt: 1 }; condition = { dungeonWarId: { $gt: 0 } }; break;
case 'main':
sortBy = { mainWarId: -1, mainUpdatedAt: 1 }; condition = { mainWarId: { $gt: 0 } }; break;
case 'mainElite':
sortBy = { mainEliteWarId: -1, mainEliteUpdatedAt: 1 }; condition = { mainEliteWarId: { $gt: 0 } }; break;
default:
sortBy = {}; break;
} }
const ranks: RoleType[] = await RoleModel.find({serverId}).select(fields.join(' ')).sort(sortBy).limit(limit).skip((page - 1) * limit).lean({ virtuals: true });
const ranks: RoleType[] = await RoleModel.find({serverId, ...condition}).select(select).sort(sortBy).limit(limit).skip((page - 1) * limit).lean({ virtuals: true, getters: true });
return ranks; return ranks;
} }
@@ -453,7 +493,7 @@ export default class Role extends BaseModel {
let dungeonHeroes = role && role.dungeonHeroes; let dungeonHeroes = role && role.dungeonHeroes;
let hasHero = dungeonHeroes&&dungeonHeroes.find(cur => cur.battleId == battleId); let hasHero = dungeonHeroes&&dungeonHeroes.find(cur => cur.battleId == battleId);
if(!dungeonHeroes || !hasHero) { if(!dungeonHeroes || !hasHero) {
role = await RoleModel.findOneAndUpdate({roleId}, {$push:{dungeonHeroes: {battleId, heroes}}}) role = await RoleModel.findOneAndUpdate({roleId}, {$push:{dungeonHeroes: {battleId, heroes}}, $set: { dungeonWarId: battleId, dungeonUpdatedAt: nowSeconds() }});
} }
return role; return role;
} }
@@ -471,6 +511,22 @@ export default class Role extends BaseModel {
return result; return result;
} }
public static async incRoleInfo(roleId: string, inc: RoleInc, set: RoleUpdate, getters = false, virtuals = true) {
delete set._id;
let result: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$inc: inc, $set: set}, {new: true}).lean({ getters, virtuals });
return result;
}
public static async updateMainWarId(roleId: string, mainWarId: number, mainUpdatedAt: number, getters = false, virtuals = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({roleId, mainWarId: { $lt: mainWarId }}, {$set:{mainWarId, mainUpdatedAt}}, {new: true}).lean({ getters, virtuals });
return result;
}
public static async updateMainEliteWarId(roleId: string, mailEliteWarId: number, mainEliteUpdatedAt: number, getters = false, virtuals = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({roleId, mailEliteWarId: { $lt: mailEliteWarId }}, {$set:{mailEliteWarId, mainEliteUpdatedAt}}, {new: true}).lean({ getters, virtuals });
return result;
}
// 记录加入公会 // 记录加入公会
public static async joinGuild(roleId: string, guildCode: string, guildName: string) { public static async joinGuild(roleId: string, guildCode: string, guildName: string) {
const result = await RoleModel.findOneAndUpdate({ roleId, hasGuild: false }, { hasGuild: true, guildCode, guildName }, { new: true }).lean(); const result = await RoleModel.findOneAndUpdate({ roleId, hasGuild: false }, { hasGuild: true, guildCode, guildName }, { new: true }).lean();
@@ -576,6 +632,7 @@ export const RoleModel = getModelForClass(Role);
export interface RoleType extends Pick<DocumentType<Role>, keyof Role>{}; export interface RoleType extends Pick<DocumentType<Role>, keyof Role>{};
export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项 export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项
export type RoleInc = Partial<Pick<DocumentType<Role>, 'heroNum'|'blockCnt'|'friendCnt'|'gold'|'coin'>>;
// 初始化 // 初始化
function getInitialTeraph() { function getInitialTeraph() {

View File

@@ -4,6 +4,7 @@ import { RoleUpdate, RoleType } from "../db/Role";
import { reduceCe } from "../pubUtils/util"; import { reduceCe } from "../pubUtils/util";
import { GuildUpdateParam } from "../db/Guild"; import { GuildUpdateParam } from "../db/Guild";
import { currentId } from "async_hooks"; import { currentId } from "async_hooks";
import { HeroType } from "../db/Hero";
// 排行榜返回玩家值 // 排行榜返回玩家值
export class RankParam { export class RankParam {
@@ -17,7 +18,7 @@ export class RankParam {
title: number; title: number;
ce: number; ce: number;
constructor(role: RoleUpdate, needReduceCe = false) { constructor(role: RoleUpdate) {
this.roleName = role.roleName; this.roleName = role.roleName;
this.lv = role.lv; this.lv = role.lv;
this.vLv = role.vLv; this.vLv = role.vLv;
@@ -25,11 +26,11 @@ export class RankParam {
this.frame = role.frame; this.frame = role.frame;
this.spine = role.spine; this.spine = role.spine;
this.title = role.title; this.title = role.title;
this.guildName = role.guildName; this.guildName = role.guildName||"";
if(needReduceCe) { if(role.isReducedCe) {
this.ce = reduceCe(role.ce);
} else {
this.ce = role.ce; this.ce = role.ce;
} else {
this.ce = reduceCe(role.ce);
} }
} }
} }
@@ -39,16 +40,26 @@ export class RoleRankInfo extends RankParam {
roleId: string; roleId: string;
num: number; num: number;
time: number; time: number;
hero: LineupParam[];
lineup: LineupParam[];
setInfo(rank: number, roleId: string, num: number, time: number) { setInfo(rank: number, myId: myIdInter, num: number, time: number) {
this.rank = rank; this.rank = rank;
this.roleId = roleId; this.roleId = myId.roleId;
this.num = num; this.num = num;
this.time = time; this.time = time;
} }
isMyInfo(myId: string) { isMyInfo(myId: myIdInter) {
return this.roleId == myId; return this.roleId == myId.roleId;
}
setTopLine(lineup: LineupParam[]){
this.lineup = lineup;
}
setSingleHero(hero: LineupParam[]){
this.hero = hero;
} }
} }
@@ -85,15 +96,15 @@ export class GuildRankInfo extends GuildRankParam {
num: number; num: number;
time: number; time: number;
setInfo(rank: number, code: string, num: number, time: number) { setInfo(rank: number, myId: myIdInter, num: number, time: number) {
this.rank = rank; this.rank = rank;
this.code = code; this.code = myId.guildCode;
this.num = num; this.num = num;
this.time = time; this.time = time;
} }
isMyInfo(myId: string) { isMyInfo(myId: myIdInter) {
return this.code == myId; return this.code == myId.guildCode;
} }
} }
@@ -115,6 +126,25 @@ export class GuildLeader {
} }
} }
// 排行榜返回玩家值
export class LineupParam {
hid: number;
star: number;
colorStar: number;
lv: number;
quality: number;
job: number;
constructor(hero: HeroType) {
this.hid = hero.hid;
this.star = hero.star;
this.colorStar = hero.colorStar;
this.lv = hero.lv;
this.quality = hero.quality;
this.job = hero.job;
}
}
export class SimpleGuildRankParam { export class SimpleGuildRankParam {
rank: number = 0; rank: number = 0;
code: string = ""; code: string = "";
@@ -163,12 +193,14 @@ export class KeyName {
serverId?: number; serverId?: number;
guildCode?: string; guildCode?: string;
cityId?: number; cityId?: number;
hid?: number;
constructor(key: string, param: KeyNameParam) { constructor(key: string, param: KeyNameParam) {
this.key = key; this.key = key;
if(param.serverId) this.serverId = param.serverId; if(param.serverId) this.serverId = param.serverId;
if(param.guildCode) this.guildCode = param.guildCode; if(param.guildCode) this.guildCode = param.guildCode;
if(param.cityId) this.cityId = param.cityId; if(param.cityId) this.cityId = param.cityId;
if(param.hid) this.hid = param.hid;
} }
public getName() { public getName() {
@@ -176,6 +208,7 @@ export class KeyName {
if(this.serverId) res += `:${this.serverId}`; if(this.serverId) res += `:${this.serverId}`;
if(this.guildCode) res += `:${this.guildCode}`; if(this.guildCode) res += `:${this.guildCode}`;
if(this.cityId) res += `:${this.cityId}`; if(this.cityId) res += `:${this.cityId}`;
if(this.hid) res += `:${this.hid}`;
return res; return res;
} }
@@ -196,4 +229,11 @@ export class KeyName {
} }
} }
export type KeyNameParam = Partial<KeyName>; export type KeyNameParam = Partial<KeyName>;
export interface myIdInter {
roleId?: string;
guildCode?: string;
hid?: number;
}

View File

@@ -1,4 +1,4 @@
import { dicHero } from "./dictionary/DicHero"; import { dicHero, dicMyHeroes } from "./dictionary/DicHero";
import { dicGoods, blueprt, dicJewel, figureCondition } from "./dictionary/DicGoods"; import { dicGoods, blueprt, dicJewel, figureCondition } from "./dictionary/DicGoods";
import { dicBlueprtCompose } from "./dictionary/DicBlueprtCompose"; import { dicBlueprtCompose } from "./dictionary/DicBlueprtCompose";
import { dicBlueprtPossibility } from "./dictionary/DicBlueprtPossibility"; import { dicBlueprtPossibility } from "./dictionary/DicBlueprtPossibility";
@@ -166,7 +166,8 @@ export const gameData = {
raceEventItems: decodeRaceEventItems(), raceEventItems: decodeRaceEventItems(),
shop: dicShop, shop: dicShop,
shopItem: dicShopItem, shopItem: dicShopItem,
shopList: dicShopList shopList: dicShopList,
dicMyHeroes: dicMyHeroes
}; };
// 在此提供一些原先在gamedata中提供的方法以便更方便获取gameData数据 // 在此提供一些原先在gamedata中提供的方法以便更方便获取gameData数据

View File

@@ -34,8 +34,12 @@ let arr = JSON.parse(str);
type KeysEnum<T> = { [P in keyof Required<T>]: true }; type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicHeroKeys: KeysEnum<DicHero> = {heroId: true, name: true, quality: true, camp: true, jobid: true, skill: true, pieceId: true, initialStars: true, pieceCount: true, baseAbilityArr: true, baseAbilityUpArr: true, initialSkin: true}; const DicHeroKeys: KeysEnum<DicHero> = {heroId: true, name: true, quality: true, camp: true, jobid: true, skill: true, pieceId: true, initialStars: true, pieceCount: true, baseAbilityArr: true, baseAbilityUpArr: true, initialSkin: true};
export const dicMyHeroes = new Array<number>();
export const dicHero = new Map<number, DicHero>(); export const dicHero = new Map<number, DicHero>();
arr.forEach(o => { arr.forEach(o => {
if(o.heroId > 0 && o.heroId <= 300) {
dicMyHeroes.push(o.heroId);
}
o.baseAbilityArr = parseBaseAbilityArr(o); o.baseAbilityArr = parseBaseAbilityArr(o);
o.baseAbilityUpArr = parseBaseAbilityUpArr(o); o.baseAbilityUpArr = parseBaseAbilityUpArr(o);

View File

@@ -1,17 +1,18 @@
import { HeroModel } from '../db/Hero'; import { HeroModel, HeroUpdate, HeroType } from '../db/Hero';
import { ItemModel } from '../db/Item'; import { ItemModel } from '../db/Item';
import { EquipModel, RandSe, Holes } from './../db/Equip'; import { EquipModel, RandSe, Holes } from './../db/Equip';
import { BagInter, EquipInter } from './interface'; import { BagInter, EquipInter } from './interface';
import { gameData } from './data'; import { gameData } from './data';
import { RANDOM_SE_COUNT, FIX_ATTRIBUTES_RAN, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, CONSUME_TYPE } from '../consts'; import { RANDOM_SE_COUNT, FIX_ATTRIBUTES_RAN, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, CONSUME_TYPE, HERO_SYSTEM_TYPE } from '../consts';
import { getRandValueByMinMax, getRandEelm } from './util'; import { getRandValueByMinMax, getRandEelm } from './util';
import { findWhere } from 'underscore'; import { findWhere } from 'underscore';
import { RoleModel, RoleType } from '../db/Role'; import { RoleModel, RoleType } from '../db/Role';
import { Figure } from '../domain/dbGeneral'; import { Figure } from '../domain/dbGeneral';
import { getBeforeDaySeconds } from './timeUtil'; import { getBeforeDaySeconds } from './timeUtil';
import { calPlayerCeAndSave } from './playerCe';
export async function addSkins(roleId: string, id: number) { export async function addSkins(roleId: string, id: number) {
let skinInfo = gameData.fashion.get(id); let skinInfo = gameData.fashion.get(id);
@@ -213,4 +214,4 @@ function unlockSingleFigure(dbFigures: Figure[], id: number, unlockDirect = fals
} }
return figure return figure
} }

View File

@@ -24,7 +24,7 @@ import { DicJob } from './dictionary/DicJob';
export async function calPlayerCeAndSave(type: number, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array<number>) { export async function calPlayerCeAndSave(type: number, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array<number>) {
let role = await RoleModel.findByRoleId(roleId); let role = await RoleModel.findByRoleId(roleId);
let { attr: roleAttrs = [] } = role; let { attr: roleAttrs = [], serverId } = role;
let heroAttrs = calPlayerCe(originHero, update, type, args); // 根据操作计算attr的增加 let heroAttrs = calPlayerCe(originHero, update, type, args); // 根据操作计算attr的增加
@@ -52,7 +52,7 @@ export async function calPlayerCeAndSave(type: number, roleId: string, originHer
ce: reduceCe(heroCe), ce: reduceCe(heroCe),
incHeroCe: reduceCe(incCe), incHeroCe: reduceCe(incCe),
}); });
return { pushHeros, role, topLineupCe, hero, guild } return { pushHeros, role, topLineupCe, hero, guild, serverId }
} }
//全局属性加成 //全局属性加成
@@ -89,8 +89,10 @@ export async function reCalAllHeroCe(type: number, roleId: string, update: RoleU
update.topLineupCe = topLineupCe; update.topLineupCe = topLineupCe;
role = await RoleModel.updateRoleInfo(roleId, update); role = await RoleModel.updateRoleInfo(roleId, update);
let guild = await GuildModel.updateCe(roleId, allIncCe); // 公会更新战力 let guild = await GuildModel.updateCe(roleId, allIncCe); // 公会更新战力
return { role, pushHeros, ce: role.ce, topLineupCe: role.topLineupCe, guild } return { role, pushHeros, ce: role.ce, topLineupCe: role.topLineupCe, guild, serverId: role.serverId }
} }
// 计算武将全局战力 // 计算武将全局战力

View File

@@ -12,7 +12,7 @@ import { getHeroInfoById } from 'app/pubUtils/gamedata';
import { calPlayerCeAndSave, reCalAllHeroCe } from 'app/pubUtils/playerCe'; import { calPlayerCeAndSave, reCalAllHeroCe } from 'app/pubUtils/playerCe';
import { getExpByLv, getHeroExpByLv, gameData } from 'app/pubUtils/data'; import { getExpByLv, getHeroExpByLv, gameData } from 'app/pubUtils/data';
import { isString } from 'underscore'; import { isString } from 'underscore';
import { getAge } from 'app/pubUtils/timeUtil'; import { getAge, nowSeconds } from 'app/pubUtils/timeUtil';
import { shouldRefresh, resResult } from 'app/pubUtils/util'; import { shouldRefresh, resResult } from 'app/pubUtils/util';
import { authenticate } from 'app/pubUtils/httpUtil'; import { authenticate } from 'app/pubUtils/httpUtil';
@@ -304,6 +304,7 @@ export default class Auth extends Service {
let skinIds = new Array<number>(); let skinIds = new Array<number>();
let conditions = new Array<{type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>() let conditions = new Array<{type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number }>()
let heroNum = 0;
for (let hid of DEFAULT_HEROES) { for (let hid of DEFAULT_HEROES) {
let hero = await HeroModel.findByHidAndRole(hid, roleId); let hero = await HeroModel.findByHidAndRole(hid, roleId);
if (hero) { if (hero) {
@@ -325,8 +326,10 @@ export default class Auth extends Service {
conditions.push({type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: initialSkin}); conditions.push({type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: initialSkin});
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, roleId, hero, {}); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, roleId, hero, {});
heroNum ++;
} }
await RoleModel.incRoleInfo(role.roleId, { heroNum }, { heroNumUpdatedAt: nowSeconds() });
// 解锁形象 // 解锁形象
await ctx.service.utils.unlockFigure(roleId, conditions, role); await ctx.service.utils.unlockFigure(roleId, conditions, role);