Files
ZYZ/game-server/app/services/guildService.ts
2021-01-25 11:41:36 +08:00

284 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, GUILD_AUTH, GUILD_JOB } from "../consts";
import { RoleModel, RoleType } from "../db/Role";
import { UserGuildModel, UserGuildType } from "../db/UserGuild";
import { UserGuildApplyModel } from "../db/UserGuildApply";
import { SystemConfigModel } from "../db/SystemConfig";
import { nowSeconds } from "../pubUtils/timeUtil";
import { pinus } from "pinus";
import { GuildRecType } from "../db/GuildRec";
import { ARMY } from "../pubUtils/dicParam";
import { sendMail } from "./mailService";
/**
* @description 检查该玩家是否有权限做操作
* @param func 操作id
* @param auth 权限
*/
export async function checkAuth(func: number, roleId: string, code?: string, userGuild?: UserGuildType) {
const auth = await UserGuildModel.getMyAuth(roleId, code, userGuild);
const dicGuildAuth = gameData.guildAuth.get(func);
console.log(auth, dicGuildAuth)
if(!dicGuildAuth) return false;
return dicGuildAuth.includes(auth);
}
/**
* @description 加入公会
* @param code 公会code
* @param lv 公会当前等级,判断人数用
* @param roleId 加入的玩家
*/
export async function joinGuild(code: string, lv: number, roleId: string, serverId: number) {
// TODO 加redlock
const result = await RoleModel.joinGuild(roleId);
if(!result) {
return { status: 0, resResult: resResult(STATUS.GUILD_HAS_JOIN) };
}
const dicCenterBase = gameData.centerBase.get(lv);
if(!dicCenterBase) {
return { status: 0, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) };
}
const maxMemberCnt = dicCenterBase.peopleNum;
const guild = await GuildModel.addGuild(code, roleId, maxMemberCnt, serverId);
if(!guild) {
return { status: 0, resResult: resResult(STATUS.GUILD_MEMBER_MAX) };
}
const role = await RoleModel.findByRoleId(roleId);
const userGuild = await UserGuildModel.createUserGuild(guild.code, role, false);
if(!userGuild) {
return { status: 0, resResult: resResult(STATUS.GUILD_CREATE_ERROR) };
}
await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请
return { status: 1, guild, userGuild, roleName: role.roleName, memberCnt: guild.memberCnt }
}
/**
* 刷新军团活跃
* @param guildCode 军团唯一code
* @param serverId 区
*/
export async function getGuildWithRefActive(guildCode: string, serverId: number) {
// TODO 加写锁
let guild = await GuildModel.findByCode(guildCode, serverId, '+refTimeDaily');
if(!guild) return false;
console.log(JSON.stringify(guild));
const now = new Date();
let { activeDaily, refTimeDaily} = guild;
let isRefDaily = shouldRefresh(refTimeDaily, now, 0);
if(isRefDaily) {
activeDaily = 0; refTimeDaily = now;
guild = await GuildModel.updateInfo(guildCode, { activeDaily, refTimeDaily }, {});
}
return guild;
}
/**
* 增加活跃
* @param guildCode 军团唯一code
* @param serverId 区
* @param active 增加的活跃
*/
export async function addActive(roleId: string, serverId: number, id: number, active: number) {
let userGuild = await getUserGuildWithRefActive(roleId, 'activeRecord receivedActive activeDaily activeWeekly guildCode');
if(!userGuild) return false;
let guildCode = userGuild.guildCode;
let guild = await getGuildWithRefActive(guildCode, serverId);
if(!guild) return false;
let {activeRecord} = userGuild;
if(id != 0) { // 用于debug传0时直接增加活跃
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: active, activeWeekly: active });
guild = await GuildModel.updateInfo(guildCode, { }, { activeDaily: active, activeWeekly: active });
return { guild, userGuild };
}
/**
* 获取用户公会表并刷新活跃
* @param roleId 用户id
* @param select 筛选字段
*/
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, activeDaily, activeRecord } = userGuild;
const now = new Date();
let isRefDaily = shouldRefresh(refTimeDaily, now, 0);
if(isRefDaily) {
receivedActive = 0; refTimeDaily = now; activeDaily = 0; activeRecord = [];
userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive, refTimeDaily, activeDaily, activeRecord }, {}, select);
if(!userGuild) return false;
}
return userGuild;
}
/**
* 每周结算上周公会周功勋和 活跃并发奖励(未完)
*
*/
export async function settleGuildWeekly() {
console.log('————— settleGuildWeekly —————');
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<number, number>();
let members = new Map<string, {job: number, active: boolean}>();
for(let {roleId, auth, activeWeekly} of userGuildList) {
let active = false;
let job = 0;
if(activeWeekly > ARMY.ARMY_WEEKHONOUR_LIMIT) {
activeMemberCnt ++;
active = true;
}
if(auth == GUILD_AUTH.LEADER) {
job = GUILD_JOB.DAJIANGJUN;
} else if (activeWeekly <= ARMY.ARMY_WEEKHONOUR_LIMIT) {
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});
}
// 转换周活跃奖励
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 = {
getChannel: function(name: string, create: boolean = false) {
let channel = pinus.app.get('channelService').getChannel(name, create);
return channel
},
enterChannel: function (guildCode: string, roleId: string, sid: string) {
// 加入channel
let channel = this.getChannel(`guild${guildCode}`, true);
let users = channel.getMembers();
if (users.indexOf(roleId) === -1) {
channel.add(roleId, sid);
}
return channel
},
memberQuit: function (guildCode: string, roleId: string, guild: GuildType,sid?: string) {
// 被踢出公会
this.pushMessageByUids(`guild${guildCode}`, 'onMemberQuit', roleId, {
code: guildCode,
roleId
}, sid);
// 更新人数减少
this.updateInfo(guildCode, { memberCnt: guild.memberCnt });
},
dismiss: function(guildCode: string) {
let channel = this.getChannel(`guild${guildCode}`);
if(!!channel) {
channel.pushMessage('onDismiss', resResult(STATUS.SUCCESS, { code: guildCode }));
channel.destroy();
}
},
updateInfo: function(guildCode: string, info: any) {
let channel = this.getChannel(`guild${guildCode}`);
if(!!channel) {
channel.pushMessage('onGuildInfoUpdate', resResult(STATUS.SUCCESS, {code: guildCode, ...info}));
}
},
changeLeader: function(guildCode: string, managerCnt: number, newLeader: RoleType, oldLeaderId: string) {
let { roleId, roleName, sHid, headHid, lv, loginTime } = newLeader;
this.updateInfo(guildCode, {managerCnt, leader: { roleId, roleName, sHid, headHid, lv, loginTime }});
this.demotion(guildCode, oldLeaderId);
this.promotion(guildCode, roleId);
},
demotion: function(guildCode: string, roleId: string) {
this.pushMessageByUids(`guild${guildCode}`, 'onDemotion', roleId, {
code: guildCode
});
},
promotion: function(guildCode: string, roleId: string) {
this.pushMessageByUids(`guild${guildCode}`, 'onPromotion', roleId, {
code: guildCode
});
},
addRec: function(guildRecType: GuildRecType) {
let { guildCode, type, params, createTime } = guildRecType;
let channel = this.getChannel(`guild${guildCode}`);
if(!!channel) {
channel.pushMessage('onGuildRecAdd', resResult(STATUS.SUCCESS, {type, params, createTime}));
}
},
pushMessageByUids: function (name: string, path: string, roleId: string, message: {code: string, roleId?: string}, sid?: string) {
let channel = this.getChannel(name);
let uids = [];
if(!sid) {
sid = channel && channel.getMember(roleId)['sid'];
}
if(sid) {
uids.push({roleId, sid});
pinus.app.get('channelService').pushMessageByUids(path, resResult(STATUS.SUCCESS, message), uids);
}
}
}