From f099daf80b2a737cb3b45bc8a954208d517eadf2 Mon Sep 17 00:00:00 2001 From: luying Date: Thu, 3 Mar 2022 14:11:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B4=BB=E5=8A=A8=EF=BC=9A=E9=99=90=E6=97=B6?= =?UTF-8?q?=E6=8E=92=E8=A1=8C=E6=A6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/handler/activityHandler.ts | 2 +- .../activity/handler/timeLimitRankHandler.ts | 99 ++++++++++++++ .../servers/activity/remote/activityRemote.ts | 2 +- .../servers/guild/handler/donateHandler.ts | 35 +++-- .../app/servers/guild/handler/guildHandler.ts | 15 ++- .../app/servers/role/handler/rankHandler.ts | 55 +------- .../app/services/activity/activityService.ts | 10 +- .../services/activity/timeLimitRankService.ts | 124 +++++++++++++++++ game-server/app/services/connectorService.ts | 2 +- game-server/app/services/donateService.ts | 55 ++++++-- game-server/app/services/rankService.ts | 101 +++++++++++++- game-server/app/services/redisService.ts | 39 +++++- game-server/app/services/timeTaskService.ts | 60 ++++++++- shared/consts/constModules/activityConst.ts | 1 + shared/consts/constModules/mailConst.ts | 5 +- shared/consts/constModules/sysConst.ts | 125 ++++++++++++------ shared/consts/dataName.ts | 1 + shared/db/ActivityTimeLimitRank.ts | 66 +++++++++ shared/db/Guild.ts | 6 + shared/domain/activityField/activityField.ts | 20 +++ shared/domain/activityField/firstGiftField.ts | 5 +- .../activityField/luckyTurntableField.ts | 7 +- .../activityField/timeLimitRankField.ts | 91 +++++++++++++ shared/domain/rank.ts | 39 +++++- shared/pubUtils/dictionary/DicStructure.ts | 6 +- .../jsons/dic_army_structureCentre.json | 30 +++-- shared/resource/jsons/dic_email_content.json | 21 +++ 27 files changed, 871 insertions(+), 151 deletions(-) create mode 100644 game-server/app/servers/activity/handler/timeLimitRankHandler.ts create mode 100644 game-server/app/services/activity/timeLimitRankService.ts create mode 100644 shared/db/ActivityTimeLimitRank.ts create mode 100644 shared/domain/activityField/timeLimitRankField.ts mode change 100755 => 100644 shared/resource/jsons/dic_army_structureCentre.json diff --git a/game-server/app/servers/activity/handler/activityHandler.ts b/game-server/app/servers/activity/handler/activityHandler.ts index bc9ba4174..6f5f102fd 100644 --- a/game-server/app/servers/activity/handler/activityHandler.ts +++ b/game-server/app/servers/activity/handler/activityHandler.ts @@ -42,7 +42,7 @@ export class ActivityHandler { let activityData = await getActivityById(activityId); if (activityData) { let playerActivityData = await getActivity(serverId, roleId, activityId, activityData.type); - if(playerActivityData && playerActivityData.canShow && playerActivityData.canShow()) { + if(playerActivityData) { playerGroupActivityArray.push(playerActivityData); } } diff --git a/game-server/app/servers/activity/handler/timeLimitRankHandler.ts b/game-server/app/servers/activity/handler/timeLimitRankHandler.ts new file mode 100644 index 000000000..b3cc7c7f0 --- /dev/null +++ b/game-server/app/servers/activity/handler/timeLimitRankHandler.ts @@ -0,0 +1,99 @@ +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '../../../pubUtils/util'; +import { DEBUG_MAGIC_WORD, getRedisKeyByRankType, HERO_SELECT, ITEM_CHANGE_REASON, RANK_TYPE, ROLE_SELECT, STATUS } from '../../../consts'; +import { addItems, combineItems, handleCost } from '../../../services/rewardService'; +import { ActivityTurntableModel } from '../../../db/ActivityTurntableRec'; +import { pick } from 'underscore'; +import { addReward, stringToRewardInter, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getTimeLimitRankData, getTimeLimitRankDataShow, sendRankMail, takeSnapshot } from '../../../services/activity/timeLimitRankService'; +import { getRankInHandler, Rank } from '../../../services/rankService'; +import { getActivityById } from '../../../services/activity/activityService'; +import { TimeLimitRankData } from '../../../domain/activityField/timeLimitRankField'; +import { hasKey } from '../../../services/redisService'; +import { KeyName } from '../../../domain/rank'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new TimeLimitRankHandler(app); +} + +export class TimeLimitRankHandler { + constructor(private app: Application) { + } + + /************************幸运转盘****************************/ + /** + * @description 幸运转盘活动 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof TimeLimitRankHandler + */ + async getTimeLimitRankData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + + let playerData = await getTimeLimitRankDataShow(activityId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 获得排行榜 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof TimeLimitRankHandler + */ + async getRank(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getTimeLimitRankData(activityId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + let type = playerData.rankType; + + let redisKey = getRedisKeyByRankType(type, true); + let keyName = new KeyName(redisKey, { serverId, activityId }); + if(!(await hasKey(keyName.getName()))) { + redisKey = getRedisKeyByRankType(type); + } + if (!redisKey) return resResult(STATUS.WRONG_PARMS); + + let result = await getRankInHandler(redisKey, type, { serverId, activityId: playerData.activityId }, session); + if(!result) return resResult(STATUS.WRONG_PARMS); + + return resResult(STATUS.SUCCESS, { + ...pick(playerData, ['activityId', 'tabName', 'beginTime', 'endTime', 'rankEndTime', 'rankType']), + ...result + }); + } + + + async debugSendMail(msg: { magicWord: string, activityId: number }, session: BackendSession) { + const { magicWord, activityId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let playerData = await getTimeLimitRankData(activityId); + await sendRankMail(playerData); + return resResult(STATUS.SUCCESS); + } + + async debugTakeSnapshot(msg: { magicWord: string, activityId: number }, session: BackendSession) { + const { magicWord, activityId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let activityData = await getActivityById(activityId); + + let playerData = new TimeLimitRankData(activityData, 0); + if(!playerData.needSnapshot) return resResult(STATUS.WRONG_PARMS); + await takeSnapshot(playerData, activityData.groupId); + return resResult(STATUS.SUCCESS); + } +} diff --git a/game-server/app/servers/activity/remote/activityRemote.ts b/game-server/app/servers/activity/remote/activityRemote.ts index 25d113194..ab681ca41 100644 --- a/game-server/app/servers/activity/remote/activityRemote.ts +++ b/game-server/app/servers/activity/remote/activityRemote.ts @@ -72,7 +72,7 @@ export class ActivityRemote { this.activityByType.clear(); for(let [_, activity] of this.activities) { - let servers = this.groupToServer.get(activity.activityId)||[]; + let servers = this.groupToServer.get(activity.groupId)||[]; for(let serverId of servers) { if(!this.activityByServer.has(serverId)) { this.activityByServer.set(serverId, []); diff --git a/game-server/app/servers/guild/handler/donateHandler.ts b/game-server/app/servers/guild/handler/donateHandler.ts index 7c02bc0f6..39652e124 100644 --- a/game-server/app/servers/guild/handler/donateHandler.ts +++ b/game-server/app/servers/guild/handler/donateHandler.ts @@ -8,7 +8,7 @@ import { getArmyDonateBaseByLv, getArmyDonateBoxBaseById } from '../../../pubUti import { GuildModel } from '../../../db/Guild'; import { handleCost, addItems } from '../../../services/rewardService'; import { CHAT_SERVER, GUILD_POINT_WAYS } from '../../../consts'; -import { getDonation } from '../../../services/donateService'; +import { addFund, getDonation } from '../../../services/donateService'; import { getUserGuildWithRefActive, refreshUserGuild } from '../../../services/guildService'; import { ARMY } from '../../../pubUtils/dicParam'; import { addActive } from '../../../services/guildService' @@ -36,10 +36,14 @@ export class DonationHandler { const { myUserGuild } = msg; let userGuild = await refreshUserGuild(myUserGuild, roleId); - if (!userGuild) + if (!userGuild) return resResult(STATUS.WRONG_PARMS); + + let guild = await GuildModel.findGuild(userGuild.guildCode, serverId, 'structure lv'); + if(!guild) { return resResult(STATUS.WRONG_PARMS); + } const { guildCode: code, donateCnt, receiveBoxs } = userGuild; - let { donateFund, reports, donationLv } = await getDonation(code, serverId); + let { donateFund, reports, donationLv } = await getDonation(code, guild, serverId); return resResult(STATUS.SUCCESS, { receiveBoxs, donateFund, reports, donateCnt: donateCnt || 0, donationLv }); } /** @@ -53,8 +57,8 @@ export class DonationHandler { const roleName: string = session.get('roleName'); const serverId: number = parseInt(session.get('serverId')); const sid: string = session.get('sid'); - - let res: any = await lockData(serverId, DATA_NAME.DONATE, roleId);// 玩家可能会快速做多次操作,加一下锁 + const guildCode: string = session.get('guildCode'); + let res: any = await lockData(serverId, DATA_NAME.DONATE, guildCode);// 锁定资金的增加 try { if (!res) { return resResult(STATUS.REDLOCK_ERR); @@ -66,11 +70,18 @@ export class DonationHandler { return resResult(STATUS.WRONG_PARMS); } const { guildCode: code, donateCnt: resdonateCnt } = userGuild; + + let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); + if(!guild) { + res.releaseCallback(); + return resResult(STATUS.WRONG_PARMS); + } + if (resdonateCnt >= ARMY.ARMY_DONATE_TIMES) { res.releaseCallback(); return resResult(STATUS.GUILD_DONATE_TIMES_NOT_ENOUGH); } - let { donationLv } = await getDonation(code, serverId); + let { donationLv } = await getDonation(code, guild, serverId); let { donateReward } = getArmyDonateBaseByLv(donationLv); let { rewardGood, rewardFund, cosume } = donateReward.get(id); let result = await handleCost(roleId, sid, [cosume], ITEM_CHANGE_REASON.DONATE); @@ -85,8 +96,8 @@ export class DonationHandler { if (!!rewardGood) goods = await addItems(roleId, roleName, sid, [rewardGood], ITEM_CHANGE_REASON.DONATE); //增加基金 - const { fund } = await GuildModel.updateInfo(code, {}, { fund: rewardFund }, 'fund'); - this.app.rpc.chat.guildRemote.updateInfo.toServer(CHAT_SERVER, code, { fund }); + await addFund(code, serverId, rewardFund); + await addActive(roleId, serverId, GUILD_POINT_WAYS.DONATE, id); // 任务 await checkTask(roleId, sid, TASK_TYPE.GUILD_DONATE, 1, true, {}); @@ -115,10 +126,16 @@ export class DonationHandler { if (!userGuild) return resResult(STATUS.WRONG_PARMS); const { guildCode: code, receiveBoxs: resReceiveBoxs } = userGuild; + + let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); + if(!guild) { + return resResult(STATUS.WRONG_PARMS); + } + if (resReceiveBoxs.indexOf(id) != -1) return resResult(STATUS.GUILD_DONATE_BOXS_IS_GOT); let { boxRewards, fund, level } = getArmyDonateBoxBaseById(id); - let { donateFund, donationLv } = await getDonation(code, serverId); + let { donateFund, donationLv } = await getDonation(code, guild, serverId); if( donationLv < level) return resResult(STATUS.GUILD_DONATE_LV_NOT_ENOUGH) if (donateFund < fund) return resResult(STATUS.GUILD_DONATE_BOXS_NOT_GOT); diff --git a/game-server/app/servers/guild/handler/guildHandler.ts b/game-server/app/servers/guild/handler/guildHandler.ts index af56c31c0..e36073497 100644 --- a/game-server/app/servers/guild/handler/guildHandler.ts +++ b/game-server/app/servers/guild/handler/guildHandler.ts @@ -27,6 +27,7 @@ import { checkActivityTask, checkTask } from '../../../services/taskService'; import { guildInter } from '../../../pubUtils/interface'; import * as dicParam from '../../../pubUtils/dicParam'; import { reportTAEvent } from '../../../services/sdkService'; +import { addFund } from '../../../services/donateService'; export default function (app: Application) { @@ -932,9 +933,17 @@ export class GuildHandler { // if (magicWord !== DEBUG_MAGIC_WORD) { // return resResult(STATUS.TOKEN_ERR); // } - const guild = await GuildModel.updateInfo(code, {}, { fund: count }, 'fund'); - let chatSid = await getGuildChannelSid(code); - this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { fund: guild.fund }); + + let guild = await GuildModel.findByCode(code); + if(!guild) { + return resResult(STATUS.WRONG_PARMS); + } + + guild = await addFund(code, guild.serverId, count); + if(!guild) { + return resResult(STATUS.WRONG_PARMS); + } + return resResult(STATUS.SUCCESS, { code, fund: guild.fund }); } diff --git a/game-server/app/servers/role/handler/rankHandler.ts b/game-server/app/servers/role/handler/rankHandler.ts index 3cb661e93..527028be3 100644 --- a/game-server/app/servers/role/handler/rankHandler.ts +++ b/game-server/app/servers/role/handler/rankHandler.ts @@ -1,10 +1,10 @@ import { Application, BackendSession, HandlerService, pinus, } from "pinus"; import { resResult } from "../../../pubUtils/util"; -import { STATUS, RANK_TYPE_TO_KEY, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SELECT, RANK_FIRST_REWARD_STATUS, ITEM_CHANGE_REASON } from "../../../consts"; +import { STATUS, getRedisKeyByRankType, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SELECT, RANK_FIRST_REWARD_STATUS, ITEM_CHANGE_REASON } from "../../../consts"; import { RoleModel } from "../../../db/Role"; import { UserGuildModel } from "../../../db/UserGuild"; import { GuildModel } from "../../../db/Guild"; -import { Rank, getGeneralRank, getRankFirstReward } from "../../../services/rankService"; +import { Rank, getGeneralRank, getRankFirstReward, getRankInHandler } from "../../../services/rankService"; import { nowSeconds } from "../../../pubUtils/timeUtil"; import { gameData } from "../../../pubUtils/data"; import { addItems } from "../../../services/rewardService"; @@ -55,51 +55,10 @@ export class RoleHandler { let guildCode = session.get('guildCode'); let { type } = msg; - let redisKey = RANK_TYPE_TO_KEY.get(type); + let redisKey = getRedisKeyByRankType(type); if (!redisKey) return resResult(STATUS.WRONG_PARMS); - let r = new Rank(redisKey, { serverId }); - r.setGenerFieldsFun((obj => { - let result = new RoleAndGuildRankInfo(obj.rank, obj.num); - if(obj instanceof GuildRankInfo) { - result.setGuildInfo(obj); - } - if(obj instanceof RoleRankInfo) { - result.setUserInfo(obj); - } - return result - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }); - if (!myRank) { - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - 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 - 1, 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); - } else if (type == RANK_TYPE.GUILD_LV) { - if(role.hasGuild) { - let guild = await GuildModel.findByCode(guildCode, serverId); - myRank = await r.generMyRankWithGuild2(roleId, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); - } - } - } - - return resResult(STATUS.SUCCESS, { type, ranks, myRank }); + let result = await getRankInHandler(redisKey, type, { serverId }, session); + return resResult(STATUS.SUCCESS, { type, ...result }); } // 查看活跃排行榜 @@ -110,7 +69,7 @@ export class RoleHandler { let { type } = msg; - let redisKey = RANK_TYPE_TO_KEY.get(type); + let redisKey = getRedisKeyByRankType(type); if (!redisKey) return resResult(STATUS.WRONG_PARMS); let r = new Rank(redisKey, { serverId }); @@ -134,7 +93,7 @@ export class RoleHandler { let serverId = session.get('serverId') let { type, hid } = msg; - let redisKey = RANK_TYPE_TO_KEY.get(type); + let redisKey = getRedisKeyByRankType(type); if (!redisKey) return resResult(STATUS.WRONG_PARMS); let r = new Rank(redisKey, { serverId, hid }); diff --git a/game-server/app/services/activity/activityService.ts b/game-server/app/services/activity/activityService.ts index 5dd4152bc..be0ef0239 100644 --- a/game-server/app/services/activity/activityService.ts +++ b/game-server/app/services/activity/activityService.ts @@ -33,6 +33,7 @@ import { ActivityGroupTypeModel } from '../../db/ActivityGroupType'; import { ServerlistModel } from '../../db/Serverlist'; import { ActivityInRemote, transActivityInRemoteToModelType } from '../../domain/activityField/activityField'; import { getPlayerLuckyTurntableDataShow } from './luckyTurntableService'; +import { getTimeLimitRankDataShow } from './timeLimitRankService'; /** * 获取活动数据 @@ -191,6 +192,11 @@ export async function getActivity(serverId: number, roleId: string, activityId: activityData = await getPlayerLuckyTurntableDataShow(activityId, serverId, roleId); break; } + case ACTIVITY_TYPE.TIME_LIMIT_RANK: // 限时排行 + { + activityData = await getTimeLimitRankDataShow(activityId); + break; + } default: { console.log('未知活动类型.........', activityType) break; @@ -241,11 +247,11 @@ export function _getActivityById(activityId: number) { export function _getActivitiesByType(serverId: number, type: number) { let activityByType = pinus.app.get('activityByType')?.get(serverId)?.get(type)||[]; let activities: Map = pinus.app.get('activities'); - let result: ActivityInRemote[] = []; + let result: ActivityModelType[] = []; for(let activityId of activityByType) { let activity = activities.get(activityId); if(activity && activity.beginTime <= Date.now()) { - result.push(activity); + result.push(transActivityInRemoteToModelType(activity)); } } return result; diff --git a/game-server/app/services/activity/timeLimitRankService.ts b/game-server/app/services/activity/timeLimitRankService.ts new file mode 100644 index 000000000..6afa53925 --- /dev/null +++ b/game-server/app/services/activity/timeLimitRankService.ts @@ -0,0 +1,124 @@ +import { ACTIVITY_TYPE, getRedisKeyByRankType, MAIL_TYPE, REDIS_KEY } from "../../consts"; +import { ActivityGroupModel } from "../../db/ActivityGroup"; +import { ActivityTimeLimitRankModel, ActivityTimeLimitRankModelTypeParam } from "../../db/ActivityTimeLimitRank"; +import { GuildModel, GuildType } from "../../db/Guild"; +import { RoleModel } from "../../db/Role"; +import { TimeLimitRankData } from "../../domain/activityField/timeLimitRankField"; +import { GuildRankInfo, RoleRankInfo } from "../../domain/rank"; +import { sendMailByContent, sendMailToGuildByContent } from "../mailService"; +import { Rank } from "../rankService"; +import { getActivitiesByType, getActivityById } from "./activityService"; +import { stringToRewardInter } from "./giftPackageService"; + + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getTimeLimitRankData(activityId: number) { + let activityData = await getActivityById(activityId); + + let playerData = new TimeLimitRankData(activityData, 0); + return playerData; +} + +export async function getTimeLimitRankDataShow(activityId: number) { + let playerData = await getTimeLimitRankData(activityId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + + +/** + * @description 记录每次活动获得的资金排行榜 + * @param serverId + * @param code + * @param fund + */ +export async function recordGuildFund(serverId: number, guild: GuildType, fund: number) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TIME_LIMIT_RANK); + for(let activity of activities) { + let playerData = new TimeLimitRankData(activity, 0); + if(playerData.canRecord()) { + await ActivityTimeLimitRankModel.addGuildScore(serverId, playerData.activityId, playerData.rankType, guild.code, fund, guild._id); + + let redisKey = getRedisKeyByRankType(playerData.rankType); + // 加入排行 + let r = new Rank(redisKey, { serverId, activityId: playerData.activityId }); + await r.setRankWithGuildInfo(guild.code, fund, Date.now(), guild, true); + } + } +} + +/** + * 活动结束发送排行榜奖励 + * @param data {TimeLimitRankData} 活动数据 + * @returns + */ +export async function sendRankMail(data: TimeLimitRankData) { + let redisKey = getRedisKeyByRankType(data.rankType); + if (!redisKey) return null; + let r = new Rank(redisKey, { activityId: data.activityId }); + if(r.infoKey == REDIS_KEY.GUILD_INFO) { + let allRank = (await r.getRankByRange()); + + for(let { rank, code, name } of allRank) { + let reward = data.getRewardByRank(rank); + if(reward) { + await sendMailToGuildByContent(MAIL_TYPE.TIME_LIMIT_RANK, code, { + params: [data.tabName,`${rank}`], + goods: stringToRewardInter(reward.rewards) + }); + } + } + } else { + let allRank = (await r.getRankByRange()); + + for(let { rank, roleId } of allRank) { + let reward = data.getRewardByRank(rank); + if(reward) { + await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, { + params: [data.tabName, `${rank}`], + goods: stringToRewardInter(reward.rewards) + }); + } + } + } +} + +export async function takeSnapshot(data: TimeLimitRankData, groupId: number) { + let redisKey = getRedisKeyByRankType(data.rankType); + let targetRedisKey = getRedisKeyByRankType(data.rankType, true); + if (!redisKey || !targetRedisKey || redisKey == targetRedisKey) return null; + + let activityGroup = await ActivityGroupModel.findGroupData(groupId); + let serverIds = activityGroup? activityGroup.serverIds: []; + + let insertInfos: ActivityTimeLimitRankModelTypeParam[] = []; + for(let serverId of serverIds) { + let r = new Rank(redisKey, { serverId, activityId: data.activityId }); + let allRank = await r.getRankDataByRankWithoutDetail(); + let targetR = new Rank(targetRedisKey, { serverId, activityId: data.activityId }); + for(let rank of allRank) { + await targetR.setRank(rank.myId, rank.scores); + + let insertBaseInfo = { + serverId, activityId: data.activityId, rankType: data.rankType, score: rank.scores[0]||0, time: rank.scores[1]||0 + } + if(rank.myId.roleId) { + let role = await RoleModel.findByRoleId(rank.myId.roleId, '_id roleId'); + if(role) insertInfos.push({ ...insertBaseInfo, roleId: role.roleId, role: role._id }); + } else if(rank.myId.guildCode) { + let guild = await GuildModel.findByCode(rank.myId.guildCode, serverId, '_id guildCode'); + if(guild) insertInfos.push({ ...insertBaseInfo, guildCode: guild.code, guild: guild._id }); + } + } + } + await ActivityTimeLimitRankModel.insertRanks(insertInfos); +} \ No newline at end of file diff --git a/game-server/app/services/connectorService.ts b/game-server/app/services/connectorService.ts index d9cb9ca31..ad0f6c833 100644 --- a/game-server/app/services/connectorService.ts +++ b/game-server/app/services/connectorService.ts @@ -135,7 +135,7 @@ async function getModuleData(type: string, data: { role: RoleType, session: Fron case 'donate': if (hasGuild) { const { guildCode: code, donateCnt, receiveBoxs } = userGuild; - let { donateFund, reports, donationLv } = await getDonation(code, serverId); + let { donateFund, reports, donationLv } = await getDonation(code, guild, serverId); return { receiveBoxs, donateFund, reports, donateCnt: donateCnt || 0, donationLv }; } case 'task': diff --git a/game-server/app/services/donateService.ts b/game-server/app/services/donateService.ts index d268d3845..4396c83ab 100644 --- a/game-server/app/services/donateService.ts +++ b/game-server/app/services/donateService.ts @@ -1,22 +1,29 @@ import { DonationModel } from '../db/Donation'; import { getZeroPoint, nowSeconds } from '../pubUtils/timeUtil'; -import { GuildModel } from '../db/Guild'; +import { GuildModel, GuildType } from '../db/Guild'; import { findWhere } from 'underscore'; import { GUILD_STRUCTURE } from '../consts/constModules/guildConst'; +import { getGuildChannelSid } from './chatService'; +import { pinus } from 'pinus'; +import { lockData } from './redLockService'; +import { ACTIVITY_TYPE, DATA_NAME } from '../consts'; +import { gameData } from '../pubUtils/data'; +import { shouldRefresh } from '../pubUtils/util'; +import { getActivitiesByType } from './activity/activityService'; +import { recordGuildFund } from './activity/timeLimitRankService'; /** * 获得军团捐献,并检查是否刷新捐献数据 * @param code * @param serverId */ -export async function getDonation(code: string, serverId: number) { +export async function getDonation(code: string, guild: GuildType, serverId: number) { let donation = await DonationModel.getDonation(code); if (!donation) { - donation = await createDonation(code, serverId); + donation = await createDonation(code, guild, serverId); } if (donation.refTime < getZeroPoint()) { - let { structure } = await GuildModel.findGuild(code, serverId, 'structure'); - let { lv } = findWhere(structure, {id: GUILD_STRUCTURE.DONATE}); + let { lv } = guild.structure.find(cur => cur.id == GUILD_STRUCTURE.DONATE); donation = await DonationModel.updateDonation(code, { donateFund:0, reports:[], refTime: nowSeconds(), donationLv: lv}); } return donation; @@ -27,9 +34,41 @@ export async function getDonation(code: string, serverId: number) { * @param code * @param serverId */ -export async function createDonation(code: string, serverId: number) { - let { structure } = await GuildModel.findGuild(code, serverId, 'structure'); - let { lv } = findWhere(structure, {id: GUILD_STRUCTURE.DONATE}); +export async function createDonation(code: string, guild: GuildType, serverId: number) { + let { lv } = guild.structure.find(cur => cur.lv == GUILD_STRUCTURE.DONATE); let donation = await DonationModel.createDonation(code, lv); return donation; +} + +// 增加资金 +export async function addFund(code: string, serverId: number, fund: number) { + try { + let guild = await GuildModel.findByCode(code, serverId, 'lv todayFund refTodayFund'); + let {lv, todayFund, refTodayFund} = guild; + if(!guild) return null + + let dicStructure = gameData.centerBase.get(lv); + if(!dicStructure) return null + if(shouldRefresh(refTodayFund, new Date())) { + todayFund = 0; + refTodayFund = new Date(); + } + if(todayFund + fund > dicStructure.maxFund) { + todayFund = dicStructure.maxFund; + fund = dicStructure.maxFund - todayFund; + } else { + todayFund += fund; + } + if(fund < 0) return null + + guild = await GuildModel.updateInfo(code, { todayFund, refTodayFund }, { fund }); + let chatSid = await getGuildChannelSid(code); + pinus.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { fund: guild.fund }); + await recordGuildFund(serverId, guild, fund); + + return guild + } catch(e) { + return null + } + } \ No newline at end of file diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts index bfebeafad..47e2960d6 100644 --- a/game-server/app/services/rankService.ts +++ b/game-server/app/services/rankService.ts @@ -1,5 +1,5 @@ -import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, GuildLeader, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo } from "../domain/rank"; -import { REDIS_RANK_TO_INFO, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, REDIS_RANK_TO_EXTRA, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD, RANK_TYPE_TO_KEY, COUNTER } from "../consts"; +import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, GuildLeader, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo, RoleAndGuildRankInfo } from "../domain/rank"; +import { getInfoKeyByRedisKey, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD, getRedisKeyByRankType, COUNTER, RANK_TYPE } from "../consts"; import { redisClient, delKeys } from "./redisService"; import { RoleType, RoleModel } from "../db/Role"; import { GuildType, GuildModel } from "../db/Guild"; @@ -9,11 +9,13 @@ import { PvpDefenseModel } from "../db/PvpDefense"; import { gameData } from "../pubUtils/data"; import { getSeconds, nowSeconds } from "../pubUtils/timeUtil"; import { getWorldChannelSid } from "./chatChannelService"; -import { pinus } from "pinus"; +import { BackendSession, pinus } from "pinus"; import { RankFirstModel, RankFirstType, RankFirstUpdateParam } from "../db/RankFirst"; import { getRandSingleEelm } from "../pubUtils/util"; import { RANK_FIRST_REWARD_STATUS } from '../consts'; import { CounterModel } from "../db/Counter"; +import { ActivityTimeLimitRankModel } from "../db/ActivityTimeLimitRank"; +import { stringify } from "querystring"; /** @@ -35,8 +37,9 @@ export class Rank { constructor(key: REDIS_KEY, keyParam: KeyNameParam, isUnion = false, limit = 200) { this.key = key; this.keyName = new KeyName(key, keyParam); - this.infoKey = REDIS_RANK_TO_INFO.get(key); - this.extraKeys = REDIS_RANK_TO_EXTRA.get(key) || []; + let { infoKey, extraKey } = getInfoKeyByRedisKey(key); + this.infoKey = infoKey; + this.extraKeys = extraKey; this.isUnion = isUnion; this.limit = limit; this.setValueConfig(key); @@ -51,6 +54,7 @@ export class Rank { case REDIS_KEY.TOP_LINEUP_RANK: case REDIS_KEY.TOP_HERO_RANK: case REDIS_KEY.SUM_CE_RANK: + case REDIS_KEY.SUM_CE_SNAPSHOT: case REDIS_KEY.HERO_RANK: this.valueConfig = [ new ValueConfig(true, 'score', 0, false, false) @@ -653,6 +657,34 @@ export class Rank { return { myRank: newMyRank, ranks: newRanks } } + /** + * 获取排行榜原始数据 + * @param from + * @param to + */ + public async getRankDataByRankWithoutDetail(from: number | string = '+inf', to: number | string = '-inf') { + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES"); + let ranks: { rank: number, myId: {roleId?: string, guildCode?: string, hid?: number}, scores: number[] }[] = []; + + let num = 0; + for (let ii = 0; ii < rankFromDb.length; ii += 2) { + if (num >= this.limit) break; + + const field = rankFromDb[ii]; + let myId = this.decodeFields(this.key, field); + const scores = this.decodeScore(rankFromDb[ii + 1]); + + ranks.push({ rank: num, myId, scores }); + num++; + } + return ranks + } + public async getRankByRange(from: number | string = '+inf', to: number | string = '-inf') { let ranks = new Array(); @@ -862,7 +894,7 @@ export class Rank { let serverId = this.keyName.serverId; let sid = await getWorldChannelSid(serverId); let dicRank = gameData.rank.find(({ id }) => { - let redisKey = RANK_TYPE_TO_KEY.get(id); + let redisKey = getRedisKeyByRankType(id); return redisKey == ts.key }); // console.log('*******', dicRank); @@ -1043,7 +1075,7 @@ export async function getGeneralRank(role: RoleType & { rankReceived: number[] } let result: (GeneralRankParam & {general: number})[] = []; for (let { id, general } of gameData.rank) { - let redisKey = RANK_TYPE_TO_KEY.get(id); + let redisKey = getRedisKeyByRankType(id); if (redisKey) { let received = rankReceived.filter(rewardId => { let dic = gameData.generalRankReward.get(rewardId); @@ -1087,4 +1119,59 @@ export async function getGeneralRank(role: RoleType & { rankReceived: number[] } } } return result; +} + +export async function getRankInHandler(redisKey: REDIS_KEY, type: RANK_TYPE, keyParam: KeyNameParam, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let r = new Rank(redisKey, keyParam); + r.setGenerFieldsFun((obj => { + let result = new RoleAndGuildRankInfo(obj.rank, obj.num); + if(obj instanceof GuildRankInfo) { + result.setGuildInfo(obj); + } + if(obj instanceof RoleRankInfo) { + result.setUserInfo(obj); + } + return result + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }); + if (!myRank) { + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + 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 - 1, 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); + } else if (type == RANK_TYPE.GUILD_LV) { + if(role.hasGuild) { + let guild = await GuildModel.findByCode(guildCode, serverId); + myRank = await r.generMyRankWithGuild2(roleId, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); + } + } else if (type == RANK_TYPE.GUILD_FUND) { + if(role.hasGuild) { + let limitRank = await ActivityTimeLimitRankModel.findByCode(serverId, keyParam.activityId, guildCode); + myRank = await r.generMyRankWithGuild(guildCode, limitRank?.score||0, limitRank?.time); + } + } + } + return { ranks, myRank } } \ No newline at end of file diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 3cd23812e..2191f7e5e 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -1,16 +1,20 @@ -import { COM_BTL_QUALITY, GUILD_ACTIVITY_TYPE } from './../consts'; +import { ACTIVITY_TYPE, COM_BTL_QUALITY, getRedisKeyByRankType, GUILD_ACTIVITY_TYPE } from './../consts'; import * as Redis from 'redis'; import {REDIS_KEY} from '../consts' import { GameModel } from "../db/Game"; -import { promisifyAll } from 'bluebird'; import { pinus, ServerInfo } from 'pinus'; import { GuildRankParam, GuildLeader, RankParam, LineupParam } from '../domain/rank'; import { comBtlRanges } from '../pubUtils/data'; -import { setRankRedisFromDb } from './rankService'; +import { Rank, setRankRedisFromDb } from './rankService'; import { ServerlistModel } from '../db/Serverlist'; import moment = require('moment'); import { getRedisSubChannel } from '../pubUtils/sdkUtil'; import { getRandSingleEelm } from '../pubUtils/util'; +import { ActivityModel } from '../db/Activity'; +import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField'; +import { ActivityTimeLimitRankModel } from '../db/ActivityTimeLimitRank'; +import { RoleType } from '../db/Role'; +import { GuildType } from '../db/Guild'; /** * 在服务重新启动时,将信息存入redis @@ -38,11 +42,14 @@ export async function initAllRank() { await delKeys(REDIS_KEY.HERO_RANK); await delKeys(REDIS_KEY.SHOW_LINEUP); // await delKeys(REDIS_KEY.PVP_RANK); + await delKeys(REDIS_KEY.GUILD_FUND); + await delKeys(REDIS_KEY.SUM_CE_SNAPSHOT); await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {}); - for(let {id} of serverList) { + for(let {id, activityGroupId} of serverList) { await initRank(id); + await initActivitiesRank(id, activityGroupId) } } @@ -65,7 +72,27 @@ export async function initRank(serverId: number) { await setRankRedisFromDb(REDIS_KEY.MAIN_RANK, { serverId }); await setRankRedisFromDb(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); await setRankRedisFromDb(REDIS_KEY.HERO_RANK, { serverId }); +} +export async function initActivitiesRank(serverId: number, activityGroupId: number[]) { + let activities = await ActivityModel.findOpenActivityByType(activityGroupId, ACTIVITY_TYPE.TIME_LIMIT_RANK, new Date()); + for(let activity of activities) { + let data = new TimeLimitRankData(activity, 0); + if(data.beginTime <= Date.now() && data.endTime >= Date.now()) { + let redisKey = getRedisKeyByRankType(data.rankType, true); + + let ranks = await ActivityTimeLimitRankModel.getRank(serverId, data.activityId); + let r = new Rank(redisKey, { serverId, activityId: data.activityId }); + r.setIsInit(true); + for (let rank of ranks) { + if(r.infoKey == REDIS_KEY.USER_INFO) { + await r.setRankWithRoleInfo(rank.roleId, rank.score, rank.time||0, rank.role); + } else if(r.infoKey == REDIS_KEY.GUILD_INFO) { + await r.setRankWithGuildInfo(rank.guildCode, rank.score, rank.time||0, rank.guild); + } + } + } + } } /** @@ -444,6 +471,10 @@ export function redisClient() { return client; } +export async function hasKey(key: string) { + return await redisClient().existsAsync(key); +} + /**************** 数据库表end */ diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index 1d9b08128..0adb5795e 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -5,13 +5,13 @@ import { nowSeconds, getTimeFun, getSeconds, getZeroPoint } from '../pubUtils/ti import { getTodayGuildActivity, gameData } from '../pubUtils/data'; import { pvpSeasonEnd } from './pvpService'; import { getAllOnlineRoles, getAllServers, delGuildActivityRank } from './redisService'; -import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_STATUS, SERVER_TIMER } from '../consts'; +import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, SEND_NAME, SERVER_OPEN_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_STATUS, SERVER_TIMER, ACTIVITY_TYPE, getRedisKeyByRankType, MAIL_TYPE, REDIS_KEY } from '../consts'; import { RoleModel } from '../db/Role'; import { pinus } from 'pinus'; import { indexOf } from 'underscore'; import { PvpSeasonResultModel } from '../db/PvpSeasonResult'; import { settleGuildWeekly } from './guildService'; -import { sendMailByContent, SendMailFun } from './mailService'; +import { sendMailByContent, SendMailFun, sendMailToGuildByContent } from './mailService'; import { getGuildActivityByDic, sendEndMsgToAll, autoDeclare, sendGuildActivityStatus } from './guildActivity/guildActivityService'; import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction } from './auctionService'; import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity'; @@ -35,6 +35,11 @@ import { infologger } from '../util/logger'; import { MailModel, MailType } from '../db/Mail'; import { GroupMailModel, GroupMailType } from '../db/GroupMail'; import { ServerMailModel, ServerMailType } from '../db/ServerMail'; +import { ActivityModel } from '../db/Activity'; +import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField'; +import { GuildRankInfo, RoleRankInfo } from '../domain/rank'; +import { stringToRewardInter } from './activity/giftPackageService'; +import { sendRankMail, takeSnapshot } from './activity/timeLimitRankService'; const PER_SECOND = 1 * 1000; const PER_DAY = 24 * 60 * 60; @@ -89,6 +94,9 @@ export async function init() { // 自动开服 await initAutoCreateServer(); + + // 限时排行榜 + await initTimeLimitRank(); } // —————————————— PVP 及赛季相关 —————————————— // @@ -673,4 +681,50 @@ async function autoCreateServerSchedule(region: RegionType) { await createNewServer(region, (latestServer?.serverId||0) + 1, params); } } -// —————————————— 自动开服 end —————————————— // \ No newline at end of file +// —————————————— 自动开服 end —————————————— // + +// —————————————— 活动 start —————————————— // +async function initTimeLimitRank() { + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + let activityGroupId: number[] = []; + for(let { activityGroupId: ids } of servers) { + for(let id of ids) { + if(activityGroupId.indexOf(id) == -1) activityGroupId.push(id); + } + } + let activities = await ActivityModel.findActivityByType(activityGroupId, ACTIVITY_TYPE.TIME_LIMIT_RANK, 1); + for(let activity of activities) { + let data = new TimeLimitRankData(activity, 0); + if(data.sendMailTime > Date.now()) { + await setSendRankMailSchedule(data); + } + if(data.rankEndTime > Date.now() && data.needSnapshot()) { + await setTakeRankSnapshotSchedule(data, activity.groupId); + } + } + +} + +async function setSendRankMailSchedule(data: TimeLimitRankData) { + + if(scheduledJobs[`rankMail${data.activityId}`]) { + scheduledJobs[`rankMail${data.activityId}`].cancel(); + } + + scheduleJob(`rankMail${data.activityId}`, data.sendMailTime, async () => { + await sendRankMail(data); + }) +} + + +async function setTakeRankSnapshotSchedule(data: TimeLimitRankData, groupId: number) { + + if(scheduledJobs[`snapshot${data.activityId}`]) { + scheduledJobs[`snapshot${data.activityId}`].cancel(); + } + + scheduleJob(`snapshot${data.activityId}`, data.rankEndTime, async () => { + await takeSnapshot(data, groupId); + }) +} +// —————————————— 活动 end —————————————— // \ No newline at end of file diff --git a/shared/consts/constModules/activityConst.ts b/shared/consts/constModules/activityConst.ts index cf428cc38..8c3ea77de 100644 --- a/shared/consts/constModules/activityConst.ts +++ b/shared/consts/constModules/activityConst.ts @@ -53,6 +53,7 @@ export enum ACTIVITY_TYPE { NEW_HERO_GK = 38, //新将演绎 (配置N个武将,每个武将有X个关卡;活动期间,*天(时间自定义)开启每个武将对应的一个关卡,只有第一次通关会获得奖励) NEW_HERO_GACHA = 39, //新将擢迁(新武将抽卡) LUCKY_TURNTABLE = 40, // 幸运转盘 + TIME_LIMIT_RANK = 41, // 限时排行榜 } /** diff --git a/shared/consts/constModules/mailConst.ts b/shared/consts/constModules/mailConst.ts index abffe162e..a1e53a364 100644 --- a/shared/consts/constModules/mailConst.ts +++ b/shared/consts/constModules/mailConst.ts @@ -47,8 +47,9 @@ export enum MAIL_TYPE { EQUIP_OVER = 18, // 装备超数量 TOWER_TASK_REWARD = 19, // 镇念塔派遣过期奖励 MONTHLY_REWARD = 20, // 月卡奖品 - TREAT_ROLE_NAME = 21, // 月卡奖品 - TREAT_GUILD_INFO = 22, // 月卡奖品 + TREAT_ROLE_NAME = 21, // 改玩家名 + TREAT_GUILD_INFO = 22, // 改军团名 + TIME_LIMIT_RANK = 23, // 限时排行榜 }; export const SEND_NAME = '系统'; diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 02543cce6..05a16e1d5 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -238,36 +238,59 @@ export enum REDIS_KEY { PAY_CHANNEL = 'pay', // 支付订阅频道 TREAT_ROLE_CHANNEL = 'treatRole', // 处理玩家账号名频道 TREAT_GUILD_CHANNEL = 'treatGuild', // 处理公会账号名频道 + GUILD_FUND = 'guildFund', // 限时排行 + SUM_CE_SNAPSHOT = "sumCeTL", // 限时战力排行榜 } // 各排行榜对应hash的key -export const REDIS_RANK_TO_INFO = new Map([ - [REDIS_KEY.TOWER_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_LV_RANK, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.GATE_ACTIVITY, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.USER_GATE_ACTIVITY, REDIS_KEY.USER_INFO], - [REDIS_KEY.CITY_ACTIVITY, REDIS_KEY.GUILD_INFO], - [REDIS_KEY.USER_CITY_ACTIVITY, REDIS_KEY.USER_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 function getInfoKeyByRedisKey(redisKey: REDIS_KEY) { + switch(redisKey) { + case REDIS_KEY.TOWER_RANK: // 天梯排行榜 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.PVP_RANK: // pvp排行榜 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.TOP_LINEUP_RANK: // 最强阵容排行 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [REDIS_KEY.TOP_LINEUP_INFO] }; + case REDIS_KEY.TOP_HERO_RANK: // 最强武将排行 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [REDIS_KEY.HERO_INFO] }; + case REDIS_KEY.HERO_NUM_RANK: // 武将数量排行 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.USER_LV: // 主公等级排行榜 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.SUM_CE_RANK: // 总战力排名 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.DUNGEON_RANK: // 秘境排名 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [REDIS_KEY.DUNGEON_LINEUP] }; + case REDIS_KEY.MAIN_RANK: // 主线通关排名 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.MAIN_ELITE_RANK: // 精英通关排名 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.HERO_RANK: // 武将排行榜 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [REDIS_KEY.HERO_INFO] }; + + case REDIS_KEY.GUILD_ACTIVE_RANK: // 公会周活跃排行榜 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; + case REDIS_KEY.GUILD_LV_RANK: // 公会等级排行榜 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; + case REDIS_KEY.GUILD_FUND: // 军团资金 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; -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]] -]); + case REDIS_KEY.GATE_ACTIVITY: // 蛮夷入侵军团排行 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; + case REDIS_KEY.USER_GATE_ACTIVITY: // 蛮夷入侵玩家排行 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.CITY_ACTIVITY: // 诸侯混战军团排行 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; + case REDIS_KEY.USER_CITY_ACTIVITY: // 诸侯混战玩家排行 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + case REDIS_KEY.RACE_ACTIVITY: // 粮草先行军团排行 + return { infoKey: REDIS_KEY.GUILD_INFO, extraKey: [] }; + + case REDIS_KEY.SUM_CE_SNAPSHOT: // 战力限时排行榜的快照 + return { infoKey: REDIS_KEY.USER_INFO, extraKey: [] }; + + } +} // 排行榜类型 export enum RANK_TYPE { @@ -279,26 +302,43 @@ export enum RANK_TYPE { TOWER = 6, // 镇念塔 MAIN = 7, // 主线 MAIN_ELITE = 8, // 精英 - GUILD_LV = 9, // 军团按等级排序 + GUILD_LV = 9, // 军团按等级排序 GUILD_ACTIVE = 11, // 军团活跃度排序 HERO = 12, // 武将排行 + GUILD_FUND = 13, // 军团积分排行,限时类型的排行榜,仅计算期限内增加的值 } // 接口中的排行榜类型对应的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] -]); +export function getRedisKeyByRankType(rankType: RANK_TYPE, isTimelimit = false) { + switch(rankType) { + case RANK_TYPE.TOP_LINTUP: // 最强阵容战力 + return REDIS_KEY.TOP_LINEUP_RANK; + case RANK_TYPE.TOP_HERO: // 最强武将 + return REDIS_KEY.TOP_HERO_RANK; + case RANK_TYPE.HERO_NUM: // 武将数量 + return REDIS_KEY.HERO_NUM_RANK; + case RANK_TYPE.USER_LV: // 主公等级 + return REDIS_KEY.USER_LV; + case RANK_TYPE.SUM_CE: // 总战力 + return isTimelimit? REDIS_KEY.SUM_CE_SNAPSHOT: REDIS_KEY.SUM_CE_RANK; + case RANK_TYPE.TOWER: // 镇念塔 + return REDIS_KEY.TOWER_RANK; + case RANK_TYPE.MAIN: // 主线 + return REDIS_KEY.MAIN_RANK; + case RANK_TYPE.MAIN_ELITE: // 精英 + return REDIS_KEY.MAIN_ELITE_RANK; + case RANK_TYPE.GUILD_LV: // 军团按等级排序 + return REDIS_KEY.GUILD_LV_RANK; + case RANK_TYPE.GUILD_ACTIVE: // 军团活跃度排序 + return REDIS_KEY.GUILD_ACTIVE_RANK; + case RANK_TYPE.HERO: // 武将排行 + return REDIS_KEY.HERO_RANK; + case RANK_TYPE.GUILD_FUND: // 军团积分排行,限时类型的排行榜,仅计算期限内增加的值 + return REDIS_KEY.GUILD_FUND; + } +} + +export const RANK_TYPE_TO_KEY = new Map(); // field处理方法 export enum COMPOSE_FIELD_TYPE { @@ -334,7 +374,8 @@ export const KEY_TO_COMPOSE_FIELD = new Map([ [REDIS_KEY.SHOW_LINEUP, COMPOSE_FIELD_TYPE.ROLE], [REDIS_KEY.SUM_CE_RANK, COMPOSE_FIELD_TYPE.ROLE], [REDIS_KEY.PVP_RANK, COMPOSE_FIELD_TYPE.ROLE], - + [REDIS_KEY.GUILD_FUND, COMPOSE_FIELD_TYPE.GUILD], + [REDIS_KEY.SUM_CE_SNAPSHOT, COMPOSE_FIELD_TYPE.ROLE], ]); diff --git a/shared/consts/dataName.ts b/shared/consts/dataName.ts index 75078a6ec..c8ace4cd7 100644 --- a/shared/consts/dataName.ts +++ b/shared/consts/dataName.ts @@ -11,4 +11,5 @@ export enum DATA_NAME { GAMEMAIL = 'Mail', AUCTION_LOT = 'LotCode', DONATE = 'Donate', + FUND = 'fund', } diff --git a/shared/db/ActivityTimeLimitRank.ts b/shared/db/ActivityTimeLimitRank.ts new file mode 100644 index 000000000..fb4fc7b92 --- /dev/null +++ b/shared/db/ActivityTimeLimitRank.ts @@ -0,0 +1,66 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose'; +import Guild from './Guild'; +import Role, { } from './Role'; + +/** + * 活动系统 - 限时排行榜 +*/ +@index({ activityId: 1 }) + +export default class Activity_Time_Limit_Rank extends BaseModel { + @prop({ required: true }) + serverId: number; // 区Id + + @prop({ required: true }) + activityId: number; // 活动Id + + @prop({ required: false }) + guildCode: string; // 军团 + + @prop({ ref: 'Guild', type: mongoose.Schema.Types.ObjectId }) + guild: Ref; + + @prop({ required: false }) + roleId: string; // 军团 + + @prop({ ref: 'Role', type: mongoose.Schema.Types.ObjectId }) + role: Ref; + + @prop({ required: true }) + score: number; // 活动期间内的积分 + + @prop({ required: true }) + time: number; // 更新时间 + + public static async addGuildScore(serverId: number, activityId: number, rankType: number, guildCode: string, fund: number, guild?: string) { + let rec: ActivityTimeLimitRankModelType = await ActivityTimeLimitRankModel.findOneAndUpdate({ + serverId, activityId, guildCode + }, { + $setOnInsert: { guild }, $set: { time: Date.now(), rankType }, $inc: { score: fund } + }, { new: true, upsert: true }).lean(); + return rec; + } + + public static async findByCode(serverId: number, activityId: number, guildCode: string) { + let rec: ActivityTimeLimitRankModelType = await ActivityTimeLimitRankModel.findOne({ serverId, activityId, guildCode }).lean(); + return rec; + } + + public static async insertRanks(insertInfos: ActivityTimeLimitRankModelTypeParam[]) { + await ActivityTimeLimitRankModel.insertMany(insertInfos); + return insertInfos; + } + + public static async getRank(serverId: number, activityId: number) { + let rec: ActivityTimeLimitRankModelType[] = await ActivityTimeLimitRankModel.find({ serverId, activityId }) + .populate('role').populate('guild') + .sort({ score: 1, time: -1 }).lean(); + return rec; + } +} + +export const ActivityTimeLimitRankModel = getModelForClass(Activity_Time_Limit_Rank); + +export interface ActivityTimeLimitRankModelType extends Pick, keyof Activity_Time_Limit_Rank> { } +export type ActivityTimeLimitRankModelTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/db/Guild.ts b/shared/db/Guild.ts index 3549a77ce..b5242d1c8 100644 --- a/shared/db/Guild.ts +++ b/shared/db/Guild.ts @@ -59,6 +59,12 @@ export default class Guild extends BaseModel { @prop({ required: true, default: 0 }) fund: number; + @prop({ required: true, default: 0 }) + todayFund: number; // 今天获得的资金,只增不减 + + @prop({ required: true, default: 0 }) + refTodayFund: Date; + @prop({ required: true, default: 0 }) activeDaily: number; diff --git a/shared/domain/activityField/activityField.ts b/shared/domain/activityField/activityField.ts index 54c2892b4..2e12384a9 100644 --- a/shared/domain/activityField/activityField.ts +++ b/shared/domain/activityField/activityField.ts @@ -6,6 +6,7 @@ import { deltaDays } from '../../pubUtils/util'; // 活动数据 export abstract class ActivityBase { activityId: number = 0; + name: string = ''; beginTime: number = 0; endTime: number = 0; type: number = 0; @@ -23,9 +24,27 @@ export abstract class ActivityBase { } public canShow() { + console.log('#### canShow', this.beginTime <= Date.now(), this.endTime >= Date.now()) return this.beginTime <= Date.now() && this.endTime >= Date.now() } + /** + * getBaseKeys + */ + public getBaseKeys() { + return { + activityId: this.activityId, + name: this.name, + beginTime: this.beginTime, + endTime: this.endTime, + type: this.type, + todayIndex: this.todayIndex, + delayDay: this.delayDay, + roundIndex: this.roundIndex, + nextRefreshTime: this.nextRefreshTime, + } + } + constructor(activityData: ActivityModelType, createTime: number) { this.activityId = activityData.activityId; this.delayDay = activityData.delayDay ? activityData.delayDay : 0; @@ -34,6 +53,7 @@ export abstract class ActivityBase { this.todayIndex = deltaDays(moment(this.beginTime).toDate(), new Date) + 1; this.roundIndex = 1; this.nextRefreshTime = this.endTime; + this.name = activityData.name; this.type = activityData.type; console.log('今天是活动第几天', activityData.beginTime, new Date, this.todayIndex) diff --git a/shared/domain/activityField/firstGiftField.ts b/shared/domain/activityField/firstGiftField.ts index c9fc5c315..2cff14629 100644 --- a/shared/domain/activityField/firstGiftField.ts +++ b/shared/domain/activityField/firstGiftField.ts @@ -138,7 +138,10 @@ export class FirstGiftData extends ActivityBase { } public getShowResult() { - return pick(this, 'list'); + return { + ...this.getBaseKeys(), + list: this.list, + } } constructor(activityData: ActivityModelType, createTime: number) { diff --git a/shared/domain/activityField/luckyTurntableField.ts b/shared/domain/activityField/luckyTurntableField.ts index cfbac2b66..a1077b7fb 100644 --- a/shared/domain/activityField/luckyTurntableField.ts +++ b/shared/domain/activityField/luckyTurntableField.ts @@ -171,7 +171,12 @@ export class LuckyTurntableData extends ActivityBase { public getShowResult() { return { - ...pick(this, ['cost', 'freeCount', 'todayCount', 'count', 'box']), + ...this.getBaseKeys(), + cost: this.cost, + freeCount: this.freeCount, + todayCount: this.todayCount, + count: this.count, + box: this.box, pool: this.pool.map(pool => pool.getShowResult()), records: this.records.map(record => [record.roleName, record.gid, record.count]) } diff --git a/shared/domain/activityField/timeLimitRankField.ts b/shared/domain/activityField/timeLimitRankField.ts new file mode 100644 index 000000000..4fe5b80f4 --- /dev/null +++ b/shared/domain/activityField/timeLimitRankField.ts @@ -0,0 +1,91 @@ +import { pick } from 'underscore'; +import { RANK_TYPE } from '../../consts'; +import { ActivityModelType } from '../../db/Activity'; +import { ActivityTurntableModelType, TurntableRecord } from '../../db/ActivityTurntableRec'; +import { RewardInter } from '../../pubUtils/interface'; +import { getRandEelmWithWeight, parseGoodStr } from '../../pubUtils/util'; +import { ActivityBase } from './activityField'; + +interface TimeLimitRewardInDb { + rank: number; // 第几名 + rewards: string; // type&id&count +} + +interface TimeLimitInDb { + rankType: number; // 排行榜类型 + hid: number; // 如果有单个武将排行,这里写武将id + rankEndTime: number; // 排行榜统计结束时间。13位时间戳,之后会在后台加时间筛选,在此之前先找wo + sendMailTime: number; // 发送奖励时间。13位时间戳 + rankRewards: TimeLimitRewardInDb[]; // 不同排名的奖励 + tabName: string; // 排行榜标签名 +} + + +export class TimeLimitRankReward { + rank: number + rewards: string; + + constructor(data: TimeLimitRewardInDb) { + this.rank = data.rank; + this.rewards = data.rewards; + } +} + +// 新云转盘活动数据 +export class TimeLimitRankData extends ActivityBase { + rankType: number; // 排行榜类型 + hid: number; // 如果有单个武将排行,这里写武将id + rankEndTime: number; // 排行榜统计结束时间。13位时间戳,之后会在后台加时间筛选,在此之前先找wo + sendMailTime: number; // 发送奖励时间。13位时间戳 + rankRewards: TimeLimitRankReward[] = []; // 不同排名的奖励 + tabName: string; // 标签名 + + // 是否可以记录 + public canRecord() { + return this.beginTime <= Date.now() && this.rankEndTime >= Date.now(); + } + + public getRewardByRank(rank: number) { + let result: TimeLimitRankReward; + for(let reward of this.rankRewards) { + if(reward.rank > rank) break; + result = reward; + } + return result; + } + + public needSnapshot() { + switch(this.rankType) { + case RANK_TYPE.GUILD_FUND: + return false; + default: + return true; + } + } + + public initData(data: string) { + let dataObj: TimeLimitInDb = JSON.parse(data); + this.rankType = dataObj.rankType; + this.hid = dataObj.hid; + this.rankEndTime = dataObj.rankEndTime; + this.sendMailTime = dataObj.sendMailTime; + for(let rank of dataObj.rankRewards) { + this.rankRewards.push(new TimeLimitRankReward(rank)); + } + this.tabName = dataObj.tabName; + } + + public getShowResult() { + return { + ...this.getBaseKeys(), + rankType: this.rankType, + rankEndTime: this.rankEndTime, + tabName: this.tabName, + } + } + + constructor(activityData: ActivityModelType, createTime: number) { + super(activityData, createTime) + this.initData(activityData.data) + } +} \ No newline at end of file diff --git a/shared/domain/rank.ts b/shared/domain/rank.ts index 99a05c51f..c24be6317 100644 --- a/shared/domain/rank.ts +++ b/shared/domain/rank.ts @@ -7,6 +7,7 @@ import { HeroType, } from "../db/Hero"; import { getSeconds } from "../pubUtils/timeUtil"; import { prop } from "@typegoose/typegoose"; import { pick } from "underscore"; +import { REDIS_KEY } from "../consts"; // 排行榜返回玩家值 export class RankParam { @@ -317,6 +318,7 @@ export class KeyName { cityId?: number; hid?: number; seasonNum?: number; + activityId?: number; constructor(key: string, param: KeyNameParam) { this.key = key; @@ -325,16 +327,39 @@ export class KeyName { if(param.cityId) this.cityId = param.cityId; if(param.hid) this.hid = param.hid; if(param.seasonNum) this.seasonNum = param.seasonNum; + if(param.activityId) this.activityId = param.activityId; } public getName() { - let res = this.key; - if(this.serverId) res += `:${this.serverId}`; - if(this.guildCode) res += `:${this.guildCode}`; - if(this.cityId) res += `:${this.cityId}`; - if(this.hid) res += `:${this.hid}`; - if(this.seasonNum) res += `:${this.seasonNum}`; - return res; + switch(this.key) { + case REDIS_KEY.TOP_LINEUP_RANK: + case REDIS_KEY.TOP_HERO_RANK: + case REDIS_KEY.HERO_NUM_RANK: + case REDIS_KEY.SUM_CE_RANK: + case REDIS_KEY.USER_LV: + case REDIS_KEY.MAIN_RANK: + case REDIS_KEY.MAIN_ELITE_RANK: + case REDIS_KEY.GUILD_LV_RANK: + case REDIS_KEY.GUILD_ACTIVE_RANK: + case REDIS_KEY.GATE_ACTIVITY: + case REDIS_KEY.RACE_ACTIVITY: + case REDIS_KEY.TOWER_RANK: + return `${this.key}:${this.serverId}`; + case REDIS_KEY.HERO_RANK: + return `${this.key}:${this.serverId}:${this.hid}`; + case REDIS_KEY.PVP_RANK: + return `${this.key}:${this.seasonNum}`; + case REDIS_KEY.CITY_ACTIVITY: + return `${this.key}:${this.serverId}:${this.cityId}`; + case REDIS_KEY.USER_CITY_ACTIVITY: + REDIS_KEY.USER_GATE_ACTIVITY + return `${this.key}:${this.serverId}:${this.guildCode}`; + case REDIS_KEY.GUILD_FUND: + case REDIS_KEY.SUM_CE_SNAPSHOT: + return `${this.key}:${this.serverId}:${this.activityId}`; + default: + return this.key; + } } public getNameWithPlus(...plus: string[]) { diff --git a/shared/pubUtils/dictionary/DicStructure.ts b/shared/pubUtils/dictionary/DicStructure.ts index 27c020f09..05fede9ef 100644 --- a/shared/pubUtils/dictionary/DicStructure.ts +++ b/shared/pubUtils/dictionary/DicStructure.ts @@ -15,13 +15,16 @@ export interface DicCentreBase { readonly peopleNum: number; // 管理员人数 readonly managerNum: number; + // 每日最大可获得资金 + readonly maxFund: number; } const DicCenterKeys: KeysEnum = { id: true, level: true, peopleNum: true, - managerNum: true + managerNum: true, + maxFund: true, }; // 炼器堂 @@ -183,6 +186,7 @@ export function loadStructure() { arrCenter.forEach(o => { setStructureConsume(o); if(o.peopleNum > maxMemberCnt.max) maxMemberCnt.max = o.peopleNum; + o.maxFund = o.feeLimit; dicCenterBase.set(o.level, _.pick(o, Object.keys(DicCenterKeys))); }); arrCenter = undefined; diff --git a/shared/resource/jsons/dic_army_structureCentre.json b/shared/resource/jsons/dic_army_structureCentre.json old mode 100755 new mode 100644 index 41f2de8d4..8bab72320 --- a/shared/resource/jsons/dic_army_structureCentre.json +++ b/shared/resource/jsons/dic_army_structureCentre.json @@ -7,7 +7,8 @@ "managerNum": 3, "consume": 100000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 10000 }, { "id": 2, @@ -17,7 +18,8 @@ "managerNum": 3, "consume": 250000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 20000 }, { "id": 3, @@ -27,7 +29,8 @@ "managerNum": 3, "consume": 700000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 30000 }, { "id": 4, @@ -37,7 +40,8 @@ "managerNum": 4, "consume": 1600000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 40000 }, { "id": 5, @@ -47,7 +51,8 @@ "managerNum": 4, "consume": 3400000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 50000 }, { "id": 6, @@ -57,7 +62,8 @@ "managerNum": 4, "consume": 7000000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 60000 }, { "id": 7, @@ -67,7 +73,8 @@ "managerNum": 5, "consume": 12250000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 70000 }, { "id": 8, @@ -77,7 +84,8 @@ "managerNum": 5, "consume": 18250000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 80000 }, { "id": 9, @@ -87,7 +95,8 @@ "managerNum": 5, "consume": 27250000, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 90000 }, { "id": 10, @@ -97,6 +106,7 @@ "managerNum": 5, "consume": 99999999, "buildWords": "&", - "imageName": "jttubiao_1" + "imageName": "jttubiao_1", + "feeLimit": 100000 } ] \ No newline at end of file diff --git a/shared/resource/jsons/dic_email_content.json b/shared/resource/jsons/dic_email_content.json index d78712746..a13c522e4 100644 --- a/shared/resource/jsons/dic_email_content.json +++ b/shared/resource/jsons/dic_email_content.json @@ -145,5 +145,26 @@ "sendName": "&", "content": "亲爱的小将军,以下是您未领取的【月卡】每日奖励,请查收", "time": 24 + }, + { + "id": 21, + "title": "&", + "sendName": "&", + "content": "您的名称不合规则,已修改为默认名,这是您的补偿", + "time": 24 + }, + { + "id": 22, + "title": "&", + "sendName": "&", + "content": "您军团的名称不合规则,已修改为默认名", + "time": 24 + }, + { + "id": 23, + "title": "&", + "sendName": "&", + "content": "您在限时排行%d中达到第%d名,可获得以下奖励", + "time": 720 } ] \ No newline at end of file