diff --git a/game-server/app/servers/battle/handler/guildHandler.ts b/game-server/app/servers/battle/handler/guildHandler.ts index 7c1987989..2c87a2029 100644 --- a/game-server/app/servers/battle/handler/guildHandler.ts +++ b/game-server/app/servers/battle/handler/guildHandler.ts @@ -1,8 +1,8 @@ import { Application, BackendSession, pinus, ChannelService } from 'pinus'; -import { resResult, getRandEelm, reduceCe } from '../../../pubUtils/util'; +import { resResult, getRandEelm, reduceCe, getRefTime } from '../../../pubUtils/util'; import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE } from '../../../consts'; import { UserGuildModel } from '../../../db/UserGuild'; -import { checkAuth, joinGuild, getGuildWithRefActive, getUserGuildWithRefActive, addGuildActive, message } from '../../../services/guildService'; +import { checkAuth, joinGuild, getGuildWithRefActive, getUserGuildWithRefActive, addGuildActive, message, settleGuildWeekly } from '../../../services/guildService'; import { GuildModel, GuildType } from '../../../db/Guild'; import { RoleModel, RoleType } from '../../../db/Role'; import { ARMY } from '../../../pubUtils/dicParam'; @@ -227,7 +227,7 @@ export class GuildHandler { const serverId = session.get('serverId'); const sid = session.get('sid'); - let userGuild = await getUserGuildWithRefActive(roleId, 'honour job auth guildCode receivedActive'); + let userGuild = await getUserGuildWithRefActive(roleId, 'job auth guildCode receivedActive activeRecord activeDaily activeWeekly'); if(!userGuild) { return resResult(STATUS.SUCCESS, { hasGuild: false }) }; @@ -495,7 +495,7 @@ export class GuildHandler { let select = ['role', 'job']; const checkDetailResult = await checkAuth(GUILD_OPERATE.GET_MEMBER_LIST_DETAIL, roleId, code); if(checkDetailResult) { - select.push('auth', 'honourWeekly honourUpdateTime'); + select.push('auth', 'activeWeekly activeUpdateTime'); } let list = await UserGuildModel.getListByGuild(code, select.join(' '), { auth: 1 }); console.log('**', JSON.stringify(list)) @@ -508,11 +508,11 @@ export class GuildHandler { let leader = result.shift(); result.sort((a, b) => { - if(sort == 'honour') { - if(b.honourWeekly == a.honourWeekly) { - return a.honourUpdateTime - b.honourUpdateTime + if(sort == 'active') { + if(b.activeWeekly == a.activeWeekly) { + return a.activeUpdateTime - b.activeUpdateTime } else { - return b.honourWeekly - a.honourWeekly + return b.activeWeekly - a.activeWeekly } } else if (sort == 'loginTime') { return b.loginTime - a.loginTime; @@ -640,7 +640,7 @@ export class GuildHandler { return resResult(STATUS.GUILD_LEADER_LOGIN); } // 上周周功勋最高的人 - const topUserGuild = await UserGuildModel.findTopHonour(code, 'auth role roleId'); + const topUserGuild = await UserGuildModel.findTopActive(code, 'auth role roleId'); if (!topUserGuild) { return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); } @@ -740,7 +740,8 @@ export class GuildHandler { const checkResult = await checkAuth(GUILD_OPERATE.GET_REC, roleId, code); if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - const list = await GuildRecModel.getGuildRec(code); + let startTime = getRefTime(new Date(), 0, -3); + const list = await GuildRecModel.getGuildRec(code, startTime.getTime()); return resResult(STATUS.SUCCESS, { list }); } @@ -826,16 +827,33 @@ export class GuildHandler { // debug接口: 添加公会活跃值 - async debugAddActive(msg: { code: string, active: number }, session: BackendSession) { + async debugAddActive(msg: { code: string, active: number, id: number }, session: BackendSession) { + const roleId = session.get('roleId'); const serverId = session.get('serverId'); - const { code, active } = msg; + const { code, active, id } = msg; const guild = await addGuildActive(code, serverId, active); if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); + let userGuild = await UserGuildModel.getMyGuild(roleId, 'activeRecord receivedActive'); + let {activeRecord} = userGuild; + let curActiveRecord = activeRecord.find(cur => cur.id == id); + if( curActiveRecord ) { + curActiveRecord.count ++; + } else { + activeRecord.push({id, count: 1}); + } + userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord, activeDaily: userGuild.activeDaily + active, activeWeekly: userGuild.activeWeekly + active}) + let { activeDaily, activeWeekly } = guild; - return resResult(STATUS.SUCCESS, { activeDaily, activeWeekly }); + return resResult(STATUS.SUCCESS, { activeDaily, activeWeekly, myInfo: userGuild }); } + // debug接口: 调用定时任务 + async debugWeeklyRask(msg: { }, session: BackendSession) { + + await settleGuildWeekly(); + return resResult(STATUS.SUCCESS); + } } \ No newline at end of file diff --git a/game-server/app/services/guildService.ts b/game-server/app/services/guildService.ts index 477b89208..ea9332586 100644 --- a/game-server/app/services/guildService.ts +++ b/game-server/app/services/guildService.ts @@ -1,7 +1,7 @@ -import { gameData } from "../pubUtils/data"; +import { gameData, getGuildActiveWeekReward } from "../pubUtils/data"; import { GuildModel, GuildType } from "../db/Guild"; import { resResult, shouldRefreshWeek, shouldRefresh } from "../pubUtils/util"; -import { STATUS, GUILD_OPERATE, MAIL_TYPE } from "../consts"; +import { STATUS, GUILD_OPERATE, MAIL_TYPE, GUILD_AUTH, GUILD_JOB } from "../consts"; import { RoleModel, RoleType } from "../db/Role"; import { UserGuildModel, UserGuildType } from "../db/UserGuild"; import { UserGuildApplyModel } from "../db/UserGuildApply"; @@ -12,6 +12,8 @@ import { GuildRecType } from "../db/GuildRec"; import { MailModel } from "../db/Mail"; import { RewardInter } from "../pubUtils/interface"; import { getRedis } from "./redisService"; +import { ARMY } from "../pubUtils/dicParam"; +import { sendMail } from "./mailService"; /** * @description 检查该玩家是否有权限做操作 @@ -121,14 +123,14 @@ export async function addGuildActive(guildCode: string, serverId: number, active export async function getUserGuildWithRefActive(roleId: string, select: string) { let userGuild = await UserGuildModel.getMyGuild(roleId, select? select + ' +refTimeDaily': '+refTimeDaily'); if(!userGuild) return false; - let { receivedActive, refTimeDaily } = userGuild; + let { receivedActive, refTimeDaily, activeDaily, activeRecord } = userGuild; const now = new Date(); let isRefDaily = shouldRefresh(refTimeDaily, now, 0); if(isRefDaily) { - receivedActive = 0; refTimeDaily = now; + receivedActive = 0; refTimeDaily = now; activeDaily = 0; activeRecord = []; - userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive, refTimeDaily }, select); + userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive, refTimeDaily, activeDaily, activeRecord }, select); if(!userGuild) return false; } @@ -141,15 +143,68 @@ export async function getUserGuildWithRefActive(roleId: string, select: string) */ export async function settleGuildWeekly() { console.log('————— settleGuildWeekly —————'); - const guildList = await GuildModel.findAllGuild('code activeWeekly'); + const guildList = await GuildModel.findAllGuild('code activeWeekly memberCnt'); + + for(let { code, activeWeekly, memberCnt } of guildList) { + const userGuildList = await UserGuildModel.getListByGuild(code, 'roleId auth activeWeekly', { activeWeekly: -1, activeUpdateTime: 1 }); + + let activeMemberCnt = 0; // 活跃度高于100的成员人数 + let otherMemberNum = 0; // 除了大将军以外从活跃高到底成员人数,用户计算活跃排名百分比 + let jobCnt = new Map(); + let members = new Map(); + + for(let {roleId, auth, activeWeekly} of userGuildList) { + let active = false; + let job = 0; + + if(activeWeekly > 100) { + activeMemberCnt ++; + active = true; + } + + if(auth == GUILD_AUTH.LEADER) { + job = GUILD_JOB.DAJIANGJUN; + } else if (activeWeekly <= 100) { + job = GUILD_JOB.SHIBING; + } else { + otherMemberNum++; + for(let [id, {rankProportion}] of gameData.guildPosition) { + let rankCnt = Math.ceil(memberCnt * rankProportion / 100); + console.log('*', id, memberCnt, rankProportion, otherMemberNum, rankCnt) + job = id; + if(otherMemberNum < rankCnt) break; + } + } + await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }); + if(!jobCnt.has(job)) jobCnt.set(job, 0); + jobCnt.set(job, jobCnt.get(job) + 1); + + members.set(roleId, {job, active}); + } - for(let { code, activeWeekly } of guildList) { // 转换周活跃奖励 - const userGuildList = await UserGuildModel.getListByGuild(code, 'honourWeekly', { honourWeekly: -1, honourUpdateTime: 1 }); - + let allWeeklyReward = getGuildActiveWeekReward(activeWeekly); + let ratio = 1; + let averageBase = ratio * ( 1- ARMY.ARMY_POSITION_WEEKREWARD) / 100; // 70% 活跃值高于100均分 + let positionBase = ratio * ARMY.ARMY_POSITION_WEEKREWARD / 100; // 30% 职位均分 + for(let [roleId, {job, active}] of members) { + let myAverageRatio = active? (averageBase / activeMemberCnt): 0; + let jobActiveRatio = gameData.guildPosition.get(job).activeRatio / 100; + let myJobRewardRatio = positionBase * jobActiveRatio / jobCnt.get(job); + let reward = allWeeklyReward.map(cur => { + return { + id: cur.id, + count: Math.ceil(cur.count * (myAverageRatio + myJobRewardRatio)) + } + }); + await sendMail(MAIL_TYPE.GUILD_ACTIVE_REWARD, roleId, '系统', [], reward); + } + + await GuildModel.updateInfo(code, { activeWeekly: 0 }, {}); } await SystemConfigModel.updateSystemConfig({settleGuildWeeklyTime: nowSeconds()}); // 记录一下 + console.log('————— settleGuildWeekly结束 —————'); } export const message = { diff --git a/game-server/app/services/mailService.ts b/game-server/app/services/mailService.ts index 90cd21c97..ad6b7615b 100644 --- a/game-server/app/services/mailService.ts +++ b/game-server/app/services/mailService.ts @@ -4,7 +4,7 @@ import { getRedis } from "./redisService"; import { pinus } from "pinus"; import { gameData } from "../pubUtils/data"; -export async function sendMail(operate: number, toRoleId: string, sendName: string, params: string[], goods: RewardInter[] = []) { +export async function sendMail(operate: number, toRoleId: string, sendName: string = '系统', params: string[] = [], goods: RewardInter[] = []) { let content = getContent( operate, params); let mail = await MailModel.addMail({roleId: toRoleId, goods, sendName, mailId: 1, content}); diff --git a/shared/consts/constModules/guildConst.ts b/shared/consts/constModules/guildConst.ts index bda55e9c4..745a1ed35 100644 --- a/shared/consts/constModules/guildConst.ts +++ b/shared/consts/constModules/guildConst.ts @@ -32,8 +32,8 @@ export enum GUILD_AUTH { // 职位 export enum GUILD_JOB { - JIANGJUN = 1, - FUJIANGJUN = 2, + DAJIANGJUN = 1, + JIANGJUN = 2, XIAOWEI = 3, SHIZHANG = 4, WUZHANG = 5, diff --git a/shared/db/GuildRec.ts b/shared/db/GuildRec.ts index 6c9611d64..ffd4c670d 100644 --- a/shared/db/GuildRec.ts +++ b/shared/db/GuildRec.ts @@ -34,8 +34,8 @@ export default class GuildRec extends BaseModel { return result; } - public static async getGuildRec(guildCode: string) { - const result: GuildRecType[] = await GuildRecModel.find({ guildCode }).sort({createTime: -1}).lean(); + public static async getGuildRec(guildCode: string, time: number) { + const result: GuildRecType[] = await GuildRecModel.find({ guildCode, createTime: { $gte: time } }).sort({createTime: -1}).lean(); return result; } } diff --git a/shared/db/UserGuild.ts b/shared/db/UserGuild.ts index 190bd3985..dc33c63b6 100644 --- a/shared/db/UserGuild.ts +++ b/shared/db/UserGuild.ts @@ -28,10 +28,13 @@ export default class UserGuild extends BaseModel { job: number; @prop({ required: true, default: 0 }) - honourWeekly: number; + activeWeekly: number; + @prop({ required: true, default: 0 }) + activeDaily: number; + @prop({ required: true, default: Date.now() }) - honourUpdateTime: number; + activeUpdateTime: number; @prop({ required: true, default: USER_GUILD_STATUS.ON, enum: USER_GUILD_STATUS}) status: number; @@ -76,7 +79,7 @@ export default class UserGuild extends BaseModel { return myGuild; } - public static async getListByGuild(guildCode: string, select?: string, sort: { auth?: number, honourWeekly?: number, honourUpdateTime?: number } = {auth: 1}) { + public static async getListByGuild(guildCode: string, select?: string, sort: { auth?: number, activeWeekly?: number, activeUpdateTime?: number } = {auth: 1}) { const userGuilds: UserGuildType[] = await UserGuildModel.find({ guildCode, status: USER_GUILD_STATUS.ON }) .select(select) .sort(sort) @@ -85,9 +88,9 @@ export default class UserGuild extends BaseModel { return userGuilds; } - public static async findTopHonour(guildCode: string, select?: string) { + public static async findTopActive(guildCode: string, select?: string) { const userGuilds: UserGuildType = await UserGuildModel.findOne({ guildCode, status: USER_GUILD_STATUS.ON, auth: { $ne: GUILD_AUTH.LEADER } }) - .sort({ honourWeekly: -1, honourUpdateTime: 1 }) + .sort({ activeWeekly: -1, activeUpdateTime: 1 }) .select(select) .populate('role', 'roleId roleName ce headHid sHid lv title loginTime', 'Role') .lean(); @@ -96,12 +99,12 @@ export default class UserGuild extends BaseModel { public static async createUserGuild(guildCode: string, role: RoleType, isLeader: boolean) { const doc = new UserGuildModel(); - let job = isLeader? GUILD_JOB.JIANGJUN: GUILD_JOB.SHIZHANG; + let job = isLeader? GUILD_JOB.DAJIANGJUN: GUILD_JOB.SHIBING; let auth = isLeader? GUILD_AUTH.LEADER: GUILD_AUTH.MEMBER; const update = Object.assign(doc.toJSON(), { guildCode, roleId: role.roleId, role: role._id, job, auth }); delete update._id; const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId: role.roleId, guildCode, status: USER_GUILD_STATUS.ON }, update, { upsert: true, new: true }) - .select('honourWeekly honourUpdateTime job auth receivedActive') + .select('activeDaily activeRecord activeWeekly activeUpdateTime job auth receivedActive') .lean(); return result; @@ -124,17 +127,12 @@ export default class UserGuild extends BaseModel { return result; } - public static async addHonourWeekly(roleId: string, inc: number, select?: string) { - const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $inc: { honourWeekly: inc } }, { new: true }).select(select).lean(); - return result; - } - public static async receiveTrainRewards(roleId: string, trainId: number, lean = true) { const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON, 'trainRewards':{$ne: trainId }}, {$push:{trainRewards: trainId} },{new: true}).lean(lean); return result; } - + } export const UserGuildModel = getModelForClass(UserGuild); diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index 1e3178bb0..81ff0468b 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -51,6 +51,7 @@ import { dicGuildPosition } from "./dictionary/DicGuildPosition"; import { dicMail } from "./dictionary/DicMail"; import { dicArmyTrainJuDian } from './dictionary/dicArmyTrainJuDian'; import { dicTrainSoloReward } from './dictionary/dicTrainSoloReward'; +import { RewardInter } from "./interface"; export const gameData = { blurprtCompose: dicBlueprtCompose, @@ -350,3 +351,12 @@ export function getTrainBaseByLv(lv: number) { } +export function getGuildActiveWeekReward(point: number) { + let result = gameData.guildActiveWeekReward.find(cur => { + let {weekPointMax, weekPointMin} = cur; + return point >= weekPointMin && point <= (weekPointMax || weekPointMax == -1); + }); + let reward = new Array(); + if(result) reward = result.reward; + return reward; +} diff --git a/shared/pubUtils/dictionary/DicGuildActiveWeekReward.ts b/shared/pubUtils/dictionary/DicGuildActiveWeekReward.ts index 6a9ee1da5..d440febd5 100644 --- a/shared/pubUtils/dictionary/DicGuildActiveWeekReward.ts +++ b/shared/pubUtils/dictionary/DicGuildActiveWeekReward.ts @@ -19,10 +19,10 @@ export interface DicGuildActiveWeekReward { const str = readJsonFile(FILENAME.DIC_ACTIVE_DAY_REWARD); let arr = JSON.parse(str); -export const dicGuildActiveWeekReward = new Map(); +export const dicGuildActiveWeekReward = new Array(); arr.forEach(o => { o.reward = parseGoodStr(o.Reward) - dicGuildActiveWeekReward.set(o.id, o); + dicGuildActiveWeekReward.push(o); }); arr = undefined; \ No newline at end of file diff --git a/shared/pubUtils/dictionary/DicGuildPosition.ts b/shared/pubUtils/dictionary/DicGuildPosition.ts index f5c31b18b..53bdde157 100644 --- a/shared/pubUtils/dictionary/DicGuildPosition.ts +++ b/shared/pubUtils/dictionary/DicGuildPosition.ts @@ -16,7 +16,7 @@ export interface DicGuildPosition { readonly activeRatio: number; } -const str = readJsonFile(FILENAME.DIC_BLUEPRT_COMPOSE); +const str = readJsonFile(FILENAME.DIC_GUILD_POSITION); let arr = JSON.parse(str); export const dicGuildPosition = new Map(); diff --git a/shared/pubUtils/dictionary/DicStructure.ts b/shared/pubUtils/dictionary/DicStructure.ts index 932e08c42..93129ffe9 100644 --- a/shared/pubUtils/dictionary/DicStructure.ts +++ b/shared/pubUtils/dictionary/DicStructure.ts @@ -102,7 +102,7 @@ export interface DicDonateBase { // 捐献值 readonly donateValue: {type: number, count: number}[]; // 捐献奖励 - readonly donateReward: {fund: number, honour: number}[]; + readonly donateReward: {fund: number, active: number}[]; // 今日捐献宝箱领取奖励系数 readonly boxRewardRatio: number; } @@ -259,16 +259,16 @@ export function parseDonateValue(str: string) { return result } -// {"fund": number, "honour": number} +// {"fund": number, "active": number} export function parseDonateReward(str: string) { - let result = new Array<{ fund: number, honour: number }>(); + let result = new Array<{ fund: number, active: number }>(); if (!str) return result; let decodeArr = decodeArrayListStr(str); - for (let [fund, honour] of decodeArr) { - if (isNaN(parseInt(fund)) || isNaN(parseInt(honour))) { + for (let [fund, active] of decodeArr) { + if (isNaN(parseInt(fund)) || isNaN(parseInt(active))) { throw new Error('data table format wrong'); } - result.push({ fund: parseInt(fund), honour: parseInt(honour) }); + result.push({ fund: parseInt(fund), active: parseInt(active) }); } return result } diff --git a/shared/pubUtils/itemUtils.ts b/shared/pubUtils/itemUtils.ts index 6cd9e4848..4d40ca98d 100644 --- a/shared/pubUtils/itemUtils.ts +++ b/shared/pubUtils/itemUtils.ts @@ -28,10 +28,6 @@ export async function addSkins(roleId: string, id: number) { export async function addBags(roleId: string, roleName: string, data: BagInter) { let { id, count, itemName, type, hid } = data; let item = await ItemModel.increaseItem(roleId, id, count, { roleId, roleName, itemName, id, type, hid }); - - if(item.id == CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR) ) { - await UserGuildModel.addHonourWeekly(roleId, count); - } return { id: item.id, count: item.count }; }