活动:限时排行榜

This commit is contained in:
luying
2022-03-03 14:11:56 +08:00
parent d0eb46ece4
commit f099daf80b
27 changed files with 871 additions and 151 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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, []);

View File

@@ -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);

View File

@@ -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 });
}

View File

@@ -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 });

View File

@@ -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<number, ActivityInRemote> = 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;

View File

@@ -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 = <GuildRankInfo[]>(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 = <RoleRankInfo[]>(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);
}

View File

@@ -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':

View File

@@ -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
}
}

View File

@@ -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<RoleRankInfo | GuildRankInfo>();
@@ -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 }
}

View File

@@ -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, <RoleType>rank.role);
} else if(r.infoKey == REDIS_KEY.GUILD_INFO) {
await r.setRankWithGuildInfo(rank.guildCode, rank.score, rank.time||0, <GuildType>rank.guild);
}
}
}
}
}
/**
@@ -444,6 +471,10 @@ export function redisClient() {
return client;
}
export async function hasKey(key: string) {
return await redisClient().existsAsync(key);
}
/**************** 数据库表end */

View File

@@ -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 —————————————— //
// —————————————— 自动开服 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 —————————————— //