排行榜:奖励显示首通信息

This commit is contained in:
luying
2021-09-09 20:42:05 +08:00
parent 4c42c45fba
commit e859d5c778
11 changed files with 259 additions and 96 deletions

View File

@@ -10,6 +10,7 @@ import { reloadResources } from '../../../pubUtils/data';
import { GeneralRankParam } from '../../../domain/rank';
import { getAllGuildActivityStatus } from '../../../services/guildActivityService';
import { MailParam } from '../../../domain/roleField/mail';
import { RankFirstType } from '../../../db/RankFirst';
export default function (app: Application) {
new HandlerService(app, {});
@@ -188,12 +189,12 @@ export class ChatRemote {
* @description 全服推送排行榜更新信息
* @param serverId
*/
public async sendRankTopUpdated(serverId: number, rank: GeneralRankParam & { general: number }) {
public async sendRankTopUpdated(serverId: number, ranks: (RankFirstType & {status: number})[]) {
let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId);
let channel = this.channelService.getChannel(roomId, false);
if (!channel) return;
channel.pushMessage(this.RANK_TOP_UPDATE, resResult(STATUS.SUCCESS, { rank }));
channel.pushMessage(this.RANK_TOP_UPDATE, resResult(STATUS.SUCCESS, { ranks }));
}
/**

View File

@@ -697,7 +697,7 @@ export class GuildHandler {
const sid = session.get('sid');
const { code, id } = msg;
const guild = await GuildModel.findByCode(code, serverId, 'lv structure');
const guild = await GuildModel.findByCode(code, serverId, 'lv structure activeWeekly lvUpdateTime');
if (!guild) {
return resResult(STATUS.GUILD_NOT_FOUND);
}
@@ -717,13 +717,13 @@ export class GuildHandler {
}
const cost = getStructureConsume(id, curStructure.lv);
const result = await GuildModel.upStructure(code, id, cost, 'code fund structure lv name');
const result = await GuildModel.upStructure(code, id, cost, 'code fund structure lv activeWeekly lvUpdateTime name');
if (!result) {
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.setRankWithGuildInfo2(code, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild);
await r.setRankWithGuildInfo2(code, result.lv, result.activeWeekly, result.lvUpdateTime, result);
}
const resultStructure = result.structure.find(cur => cur.id == id);

View File

@@ -4,7 +4,7 @@ import { STATUS, RANK_TYPE_TO_KEY, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SE
import { RoleModel } from "../../../db/Role";
import { UserGuildModel } from "../../../db/UserGuild";
import { GuildModel } from "../../../db/Guild";
import { Rank, getGeneralRank } from "../../../services/rankService";
import { Rank, getGeneralRank, getRankFirstReward } from "../../../services/rankService";
import { nowSeconds } from "../../../pubUtils/timeUtil";
import { gameData } from "../../../pubUtils/data";
import { addItems } from "../../../services/rewardService";
@@ -34,6 +34,20 @@ export class RoleHandler {
return resResult(STATUS.SUCCESS, { ranks });
}
async getRankReward(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let role = await RoleModel.findByRoleId(roleId, 'rankReceived');
if (!role) return resResult(STATUS.WRONG_PARMS);
let ranks = await getRankFirstReward(role, serverId);
return resResult(STATUS.SUCCESS, { ranks });
}
async getRank(msg: { type: number }, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId');

View File

@@ -58,7 +58,9 @@ export class RoleHandler {
}
await createHero.createWithInitInfo(infos, initInfos.figureInfo);
await createHero.pushMessage(pinus, sid);
console.log('updateRedisRank before', Date.now())
await createHero.updateRedisRank(Rank);
console.log('updateRedisRank after', Date.now())
let heroes = createHero.getResultHeroes();
console.log('****** createHeroes after', Date.now())

View File

@@ -4,6 +4,7 @@ import { reloadResources } from '../../../pubUtils/data';
import { HeroUpdate } from '../../../db/Hero';
import { RoleUpdate } from '../../../db/Role';
import { SkinUpdate } from '../../../db/Skin';
import { RankFirstModel, RankFirstType } from '../../../db/RankFirst';
import { getInitRoleInfo } from '../../../pubUtils/roleUtil';
import { DEFAULT_HEROES } from '../../../consts';
import { Figure } from '../../../domain/dbGeneral';
@@ -18,12 +19,35 @@ export class RoleRemote {
this.app = app;
this.channelService = app.get('channelService');
this.setInitRole();
this.loadRankFirst();
}
private channelService: ChannelService;
private initHeroes: Map<number, HeroUpdate> = new Map(); // hid => hero
private initRole: RoleUpdate = {};
private initSkins: Map<number, SkinUpdate> = new Map(); // hid => skin
private figureInfo: {heads: Figure[], frames: Figure[], spines: Figure[]};
private rankFirstRewards: Map<number, Map<number, RankFirstType>> = new Map();
private async loadRankFirst() {
let rankFirstRewards = await RankFirstModel.findAllRankRewards();
for(let rank of rankFirstRewards) {
if(!this.rankFirstRewards.has(rank.serverId)) {
this.rankFirstRewards.set(rank.serverId, new Map());
}
this.rankFirstRewards.get(rank.serverId).set(rank.id, rank);
}
}
public setRankFirst(rank: RankFirstType) {
if(!this.rankFirstRewards.has(rank.serverId)) {
this.rankFirstRewards.set(rank.serverId, new Map());
}
this.rankFirstRewards.get(rank.serverId).set(rank.id, rank);
}
public getRankFirstById(serverId: number, id: number) {
return this.rankFirstRewards.get(serverId)?.get(id);
}
public setInitRole() {
let result = getInitRoleInfo();

View File

@@ -10,7 +10,7 @@ import { FrontendOrBackendSession, pinus } from 'pinus';
import { resResult } from '../pubUtils/util';
import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE } from '../consts';
import { getAllShopList } from './shopService';
import { getGeneralRank } from './rankService';
import { getGeneralRank, getRankFirstReward } from './rankService';
import { getFriendList, getApplyList } from './friendService';
import { getDailyBattleList } from './dailyBattleService';
import { getExpeditionStatus } from './expeditionService';
@@ -77,7 +77,8 @@ async function getModuleData(type: string, data: { role: RoleType, session: Fron
case 'shop': // 商店
return await getAllShopList(roleId);
case 'rank': // 排名
return await getGeneralRank(role, serverId);
const rewards = await getRankFirstReward(role, serverId);
return { rewards }
case 'mail': // 邮件
return await getMails(roleId, serverId);
case 'friend': // 好友

View File

@@ -10,6 +10,9 @@ import { gameData } from "../pubUtils/data";
import { nowSeconds } from "../pubUtils/timeUtil";
import { getWorldChannelSid } from "./chatChannelService";
import { pinus } from "pinus";
import ts = require("typescript");
import { RankFirstModel, RankFirstType, RankFirstUpdateParam } from "../db/RankFirst";
import { getRandSingleEelm } from "../pubUtils/util";
/**
@@ -61,8 +64,7 @@ export class Rank {
case REDIS_KEY.GUILD_LV_RANK:
this.valueConfig = [
new ValueConfig(true, 'lv', 0, false, false),
new ValueConfig(false, 'active', 5, false, false),
new ValueConfig(false, 'time', 10, true, true)
new ValueConfig(false, 'active', 5, false, false)
];
break;
default:
@@ -844,22 +846,45 @@ export class Rank {
}
private async checkMyRankAndPush(myId: myIdInter, oldScore: number, newScore: number) {
if (this.isInit) return;
let ts = this;
if (ts.isInit) return;
let myRank = await this.getMyRank(myId);
console.log('*******', ts.key, myRank, newScore, oldScore);
if (myRank == 1 && newScore > oldScore) {
let serverId = this.keyName.serverId;
let sid = await getWorldChannelSid(serverId);
for (let { id, general } of gameData.rank) {
let dicRank = gameData.rank.find(({ id }) => {
let redisKey = RANK_TYPE_TO_KEY.get(id);
if (redisKey == this.key) {
let r = new Rank(redisKey, { serverId }, false, 1);
let ranks = <RoleRankInfo[]>await r.getRankByRange();
if (ranks.length > 0) {
let param = new GeneralRankParam(id, ranks[0] || new RoleRankInfo({}, false), general);
pinus.app.rpc.chat.chatRemote.sendRankTopUpdated.toServer(sid, serverId, { ...param, general });
return redisKey == ts.key
});
console.log('*******', dicRank);
if(dicRank) {
let r = new Rank(ts.key, { serverId }, false, 1);
let ranks = await r.getRankByRange();
let rankFirstRecs: (RankFirstType & { status: number })[] = [];
if(ranks.length > 0 && ranks[0]) {
let userInfo: RankParam, guildInfo: GuildRankParam;
if(ranks[0] instanceof RoleRankInfo) {
userInfo = ranks[0];
}
if(ranks[0] instanceof GuildRankInfo) {
guildInfo = ranks[0];
}
break;
for(let [id, { rankId, condition }] of gameData.generalRankReward) {
console.log(rankId, dicRank.id, oldScore, condition, newScore);
if(dicRank.id == rankId && oldScore < condition && newScore >= condition) {
let rankFirstRec = await RankFirstModel.createRankFirst(serverId, id, rankId, { userInfo, guildInfo });
let roleServers = pinus.app.getServersByType('role');
for(let server of roleServers) {
pinus.app.rpc.role.roleRemote.setRankFirst.toServer(server.id, rankFirstRec);
}
rankFirstRecs.push({ ... rankFirstRec, status: 1});
}
}
}
if(rankFirstRecs.length > 0) {
pinus.app.rpc.chat.chatRemote.sendRankTopUpdated.toServer(sid, serverId, rankFirstRecs);
}
}
}
@@ -1017,4 +1042,31 @@ export async function getGeneralRank(role: RoleType & { rankReceived: number[] }
}
}
return result;
}
/**
* 获取排行榜总览
* @param role 玩家数据
* @param serverId 所在服务器
*/
export async function getRankFirstReward(role: RoleType & { rankReceived: number[] }, serverId: number) {
let { rankReceived = [] } = role;
let result: (RankFirstUpdateParam & {status: number})[] = [];
for (let [id, { rankId: type } ] of gameData.generalRankReward) {
let roleServers = pinus.app.getServersByType('role');
let curServer = roleServers.find(cur => cur.id == pinus.app.getServerId());
if(!curServer) {
curServer = getRandSingleEelm(roleServers);
}
let rankFirst = await pinus.app.rpc.role.roleRemote.getRankFirstById.toServer(curServer.id, serverId, id);
if(rankFirst) {
let status = rankReceived.includes(id)?2: 1;
result.push({...rankFirst, status});
} else {
result.push({ id, type, status: 0 });
}
}
return result;
}

View File

@@ -283,15 +283,17 @@ export default class GMUsers extends Service {
await GroupMailModel.deleteMany({ roleId });
await GroupMailModel.deleteMany({ targetRoleId: roleId });
let userGuild = await UserGuildModel.getMyGuild(roleId);
if(userGuild.auth == 1) {
const guild = await GuildModel.dismiss(userGuild.guildCode, role.serverId);
await UserGuildModel.dismiss(userGuild.guildCode);
const { members } = guild;
await RoleModel.dissmissGuild(members);
await UserGuildApplyModel.deleteApplyByGuild(userGuild.guildCode);
} else {
await GuildModel.update({ members: { $in: [roleId] } }, { $pull: { members: roleId }, $inc: { memberCnt: -1, managerCnt: userGuild.auth == 2? -1: 0, guildCe: -role.ce }, $set: { isMemberMax: false } })
if(userGuild) {
if(userGuild.auth == 1) {
const guild = await GuildModel.dismiss(userGuild.guildCode, role.serverId);
await UserGuildModel.dismiss(userGuild.guildCode);
const { members } = guild;
await RoleModel.dissmissGuild(members);
await UserGuildApplyModel.deleteApplyByGuild(userGuild.guildCode);
} else {
await GuildModel.update({ members: { $in: [roleId] } }, { $pull: { members: roleId }, $inc: { memberCnt: -1, managerCnt: userGuild.auth == 2? -1: 0, guildCe: -role.ce }, $set: { isMemberMax: false } })
}
}
await GuildModel.updateMany({ invitedMembers: { $in: [roleId] } }, { $pull: { invitedMembers: roleId } });
await GuildRecModel.deleteMany({ roleId });

40
shared/db/RankFirst.ts Normal file
View File

@@ -0,0 +1,40 @@
/**
* 秘境首通
*/
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { RankParam, GuildRankParam } from '../domain/rank';
export default class RankFirst extends BaseModel {
@prop({ required: true })
serverId: number; // 服务器id
@prop({ required: true })
id: number; // 奖励表id
@prop({ required: true })
type: number; // 排行榜id
@prop({ required: true, type: () => RankParam, _id: false })
userInfo: RankParam; // 玩家信息
@prop({ required: true, type: () => GuildRankParam, _id: false })
guildInfo: GuildRankParam; // 军团信息
public static async createRankFirst(serverId: number, id: number, type: number, update: RankFirstUpdateParam) {
const rec: RankFirstType = await RankFirstModel.findOneAndUpdate({ serverId, id, type}, { $setOnInsert: update }, { new: true, upsert: true }).lean();
return rec;
}
public static async findAllRankRewards() {
let rewards: RankFirstType[] = await RankFirstModel.find({}, { _id: false }).select('serverId id type userInfo guildInfo').lean();
return rewards;
}
}
export const RankFirstModel = getModelForClass(RankFirst);
export interface RankFirstType extends Pick<DocumentType<RankFirst>, keyof RankFirst>{}
export type RankFirstUpdateParam = Partial<RankFirstType>; // 将所有字段变成可选项

View File

@@ -66,6 +66,69 @@ export class RankParam {
}
}
export class GuildLeader {
@prop({ required: true })
roleId: string;
@prop({ required: true })
roleName: string;
@prop({ required: true })
title: number;
@prop({ required: true })
lv: number;
@prop({ required: true })
head: number;
@prop({ required: true })
frame: number;
@prop({ required: true })
spine: number;
constructor(leader: { roleId: string, roleName: string, title: number, lv: number, head: number, frame: number, spine: number}) {
this.roleId = leader.roleId;
this.roleName = leader.roleName;
this.title = leader.title;
this.lv = leader.lv;
this.head = leader.head;
this.frame = leader.frame;
this.spine = leader.spine;
}
}
// 排行榜返回玩家值
export class LineupParam {
@prop({ required: true })
hid: number;
@prop({ required: true })
star: number;
@prop({ required: true })
colorStar: number;
@prop({ required: true })
lv: number;
@prop({ required: true })
quality: number;
@prop({ required: true })
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 RoleRankInfo extends RankParam {
rank: number = 1;
roleId: string = "";
@@ -94,23 +157,24 @@ export class RoleRankInfo extends RankParam {
}
}
// 公会排行榜返回值
export class GuildRankParam {
@prop({ required: true })
icon: number;
@prop({ required: true })
name: string;
@prop({ required: true })
lv: number;
@prop({ required: true })
memberCnt: number;
leader: {
roleId: string;
roleName: string;
title: number;
lv: number;
head: number;
frame: number;
spine: number;
};
@prop({ required: true, _id: false })
leader: GuildLeader;
@prop({ required: true })
guildCe: number;
constructor(guild: GuildUpdateParam) {
@@ -186,56 +250,6 @@ export class RoleAndGuildRankInfo {
}
}
export class GuildLeader {
roleId: string;
roleName: string;
title: number;
lv: number;
head: number;
frame: number;
spine: number;
constructor(leader: { roleId: string, roleName: string, title: number, lv: number, head: number, frame: number, spine: number}) {
this.roleId = leader.roleId;
this.roleName = leader.roleName;
this.title = leader.title;
this.lv = leader.lv;
this.head = leader.head;
this.frame = leader.frame;
this.spine = leader.spine;
}
}
// 排行榜返回玩家值
export class LineupParam {
@prop({ required: true })
hid: number;
@prop({ required: true })
star: number;
@prop({ required: true })
colorStar: number;
@prop({ required: true })
lv: number;
@prop({ required: true })
quality: number;
@prop({ required: true })
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 {
rank: number = 0;
code: string = "";
@@ -366,4 +380,4 @@ export class GeneralRankParam {
this.num = rankInfo.num;
this.received = received;
}
}
}

View File

@@ -72,7 +72,7 @@ export class UpdateHeroes {
funcs: number[] = [];
incHeroNum: number = 0;
incRoleCe: number = 0;
pushHeroes: {hid: number, incHeroCe: number, ce: number}[] = [];
pushHeroes: {hid: number, incHeroCe: number, ce: number, hero: HeroUpdate}[] = [];
roleUpdate: RoleUpdate;
role: RoleType;
guild: GuildType;
@@ -104,7 +104,7 @@ export class UpdateHeroes {
if(isCreate) this.incHeroNum ++;
if(heroInfo != originCe) this.incRoleCe += heroInfo.ce - originCe;
this.addRoleUpdateParam(await calculatetopLineup(role, heroInfo.hid, heroInfo.ce, heroInfo._id ));
this.pushHeroes.push({ hid: heroInfo.hid, incHeroCe: heroInfo.ce - originCe, ce: heroInfo.ce });
this.pushHeroes.push({ hid: heroInfo.hid, incHeroCe: heroInfo.ce - originCe, ce: heroInfo.ce, hero: heroInfo });
}
// 更新战力相关的各个表
@@ -127,37 +127,50 @@ export class UpdateHeroes {
public async updateRedisRank(Rank: any) {
let role = await this.getRole();
let { serverId, roleId, pushHeroes } = this;
console.log('******** guildInfo before', Date.now());
// 更新军团信息
if(this.guild) {
let r = new Rank(REDIS_KEY.GUILD_INFO, { code: this.guild.code });
await r.generParamAndSet(REDIS_KEY.GUILD_INFO, { guildCode: this.guild.code }, { guild: this.guild });
}
console.log('******** guildInfo after', Date.now());
console.log('******** heroNum before', Date.now());
// 武将数量
if(this.incHeroNum > 0) {
let r = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role);
}
console.log('******** heroNum after', Date.now());
console.log('******** topLineup before', Date.now());
// 最强阵容
let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, reduceCe(role.topLineupCe), 0, role);
console.log('******** topLineup after', Date.now());
console.log('******** hero before', Date.now());
// 最强武将
for(let { hid, ce } of pushHeroes) {
for(let { hid, ce, hero } of pushHeroes) {
console.log('******** hero before', hid, Date.now());
let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId });
await r2.setRankWithHeroInfo(roleId, hid, ce, 0);
await r2.setRankWithHeroInfo(roleId, hid, ce, 0, hero);
let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid });
await r4.setRankWithHeroInfo(roleId, hid, ce, 0);
await r4.setRankWithHeroInfo(roleId, hid, ce, 0, hero);
console.log('******** hero after', hid, Date.now());
}
console.log('******** hero after', Date.now());
console.log('******** sumCe before', Date.now());
// 总战力
let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId });
await r3.setRankWithRoleInfo(roleId, reduceCe(role.ce), 0, role);
console.log('******** sumCe after', Date.now());
console.log('******** lineup info before', Date.now());
// 更新最强五人阵容信息
let r5 = new Rank(REDIS_KEY.TOP_LINEUP_INFO, { serverId });
await r5.generParamAndSet(REDIS_KEY.TOP_LINEUP_INFO, { roleId }, { role });
console.log('******** lineup info after', Date.now());
}
public async pushMessage(pinus: any, sid: string) {