Files
ZYZ/shared/db/GVGLeague.ts

226 lines
10 KiB
TypeScript

import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose';
import Role, { RoleType } from '../db/Role';
import { genCode } from '../pubUtils/util';
import { GuildType } from './Guild';
import { LEAGUE_AUTH } from '../consts';
import { nowSeconds } from '../pubUtils/timeUtil';
class Member {
@prop({ required: true })
roleId: string;
@prop({ required: true })
guildCode: string;
@prop({ required: true })
auth: number;
@prop({ required: true })
time: number;
}
@index({ leagueCode: 1, status: 1 })
@index({ guildCodes: 1, status: 1 })
@index({ 'members.roleId': 1, status: 1 })
export default class GVGLeague extends BaseModel {
@prop({ required: true })
leagueCode: string; // 唯一id
@prop({ required: true, type: String })
guildCodes: string[]; // 包含军团
@prop({ required: true, ref: () => Role, type: mongoose.Schema.Types.ObjectId })
leader: Ref<Role>;
@prop({ required: true, default: '' })
name: string; // 名称
@prop({ required: true, default: 1 })
icon: number; // 图标
@prop({ required: true, default: '' })
notice: string; // 公告
@prop({ required: true, default: 0 })
guildCnt: number; // 军团数量
@prop({ required: true, default: 0 })
memberCnt: number; // 玩家人数
@prop({ required: true, default: false })
isAuto: boolean; // 是否是自动创建的
@prop({ required: true, default: 1 })
status: number; // 1-健在 0-解散
@prop({ required: true, default: 1 })
type: number; // 1-单服 2-跨服
@prop({ required: true, default: 1 })
serverId: number; // 服务器id
@prop({ required: true, default: [], type: Member, _id: false })
members: Member[];
public static async checkName(name: string) {
const result = await GVGLeagueModel.exists({ name, status: 1 });
return result;
}
public static async createLeague(guild: GuildType, params: GVGLeagueUpdate) {
const { code, name, memberCnt, leader, members } = guild;
const doc = new GVGLeagueModel();
const leagueCode = genCode(6);
let _leader = <RoleType>leader;
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.LEADER: LEAGUE_AUTH.MEMBER, guildCode: code, time: nowSeconds() }));
const update = Object.assign(doc.toJSON(), { guildCodes: [code], name: `${name}联军`, guildCnt: 1, memberCnt, isAuto: true, leader: _leader?._id, members: _members, leagueCode }, params);
delete update._id;
const result: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ guildCodes: code, status: 1 }, { $setOnInsert: update }, { upsert: true, new: true })
.select({ _id: 0, __v: 0, createdAt: 0, updatedAt: 0 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return result;
}
public static async findLeagueByGuild(guildCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOne({ guildCodes: guildCode, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.lean();
return league
}
public static async findByCondition(type: number, serverIds: number[], page: number, name: string) {
let query = {
status: 1, type, serverId: { $in: serverIds }
};
if(name) {
query['name'] = { $regex: new RegExp(name, 'i') };
}
const league: GVGLeagueType[] = await GVGLeagueModel.find(query)
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.skip((page - 1) * 30).limit(30)
.lean();
return league
}
public static async findByCode(leagueCode: string, select = '') {
const league: GVGLeagueType = await GVGLeagueModel.findOne({ leagueCode, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
.select(select)
.lean();
return league
}
public static async findByCodeWithoutPopulate(leagueCode: string, select = '') {
const league: GVGLeagueType = await GVGLeagueModel.findOne({ leagueCode, status: 1 }).select(select).lean();
return league
}
public static async findByCodes(leagueCodes: string[]) {
const leagues: GVGLeagueType[] = await GVGLeagueModel.find({ leagueCode: { $in: leagueCodes }, status: 1 })
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, guildName: 1, _id: 0 }, 'Role')
.lean();
return leagues
}
public static async findByCodesWithoutPopulate(leagueCodes: string[], select = '') {
const leagues: GVGLeagueType[] = await GVGLeagueModel.find({ leagueCode: { $in: leagueCodes }, status: 1 }).select(select).lean();
return leagues
}
public static async joinGuild(leagueCode: string, guild: GuildType) {
const { code, memberCnt, leader, members } = guild;
let _leader = <RoleType>leader;
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.SUB_LEADER: LEAGUE_AUTH.MEMBER, guildCode: code, time: nowSeconds() }));
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
{ $push: { guildCodes: code, members: { $each: _members } }, $inc: { guildCnt: 1, memberCnt: memberCnt }
}, { new: true }).lean();
return league
}
public static async findAllLeague() {
const leagues: { leagueCode: string, memberCnt: number, serverId: number }[] = await GVGLeagueModel.aggregate([
{ $match: { status: 1 } },
{ $project: { leagueCode: 1, memberCnt: 1, serverId: 1 } }
]);
return leagues;
}
public static async findActiveLeagueMembers() {
const leagues: { members: Member[] }[] = await GVGLeagueModel.aggregate([
{ $match: { status: 1 } },
{ $project: { members: 1 } }
]);
return leagues;
}
public static async quitGuild(leagueCode: string, guild: GuildType) {
const { code, memberCnt, members } = guild;
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
{ $pull: { guildCodes: code, members: { roleId: { $in: members } } }, $inc: { guildCnt: -1, memberCnt: -memberCnt }
}, { new: true }).lean();
return league
}
public static async dismiss(leagueCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $set: { status: 0 }}, { new: true }).lean();
return league
}
public static async dismissByIds(_ids: string[]) {
await GVGLeagueModel.updateMany({ _id: { $in: _ids } }, { $set: { status: 0 }});
}
public static async abdicate(leagueCode: string, fromRoleId: string, toRoleId: string, leader: string) {
let league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': fromRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.SUB_LEADER }}, { new: true }).lean();
league = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': toRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.LEADER, leader }}, { new: true }).lean();
return league
}
public static async setInfo(leagueCode: string, name: string, notice: string, icon: number) {
let updateInfo: GVGLeagueUpdate = {};
if(name != undefined) updateInfo.name = name;
if(notice != undefined) updateInfo.notice = notice;
if(icon != undefined) updateInfo.icon = icon;
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $set: updateInfo }, { new: true }).lean();
return league;
}
public static async joinMember(leagueCode: string, roleId: string, guildCode: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $push: { members: { roleId, auth: LEAGUE_AUTH.MEMBER, guildCode, time: nowSeconds() } }, $inc: { memberCnt: 1 } }, { new: true }).lean();
return league;
}
public static async quitMember(leagueCode: string, roleId: string) {
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $pull: { members: { roleId } }, $inc: { memberCnt: -1 } }, { new: true }).lean();
return league;
}
public static async abdicateGuild(leagueCode: string, fromRoleId: string, toRoleId: string, leader: string) {
let league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': fromRoleId }, { $set: { 'members.$.auth': LEAGUE_AUTH.MEMBER }}).lean();
const member = league.members.find(cur => cur.roleId == fromRoleId);
const updateInfo = { 'members.$.auth': member?.auth };
if(member?.auth == LEAGUE_AUTH.LEADER) updateInfo['leader'] = leader;
league = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': toRoleId }, { $set: updateInfo }, { new: true }).lean();
return league
}
public static async findAutoCreateLeague() {
let leagues: GVGLeagueType[] = await GVGLeagueModel.find({ isAuto: true, status: 1 }).lean();
return leagues
}
public static async setMemberTime(leagueCode: string, roleId: string, time: number) {
let league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1, 'members.roleId': roleId }, { $set: { 'members.$.time': time} }, { new: true }).lean();
return league
}
}
export const GVGLeagueModel = getModelForClass(GVGLeague);
export interface GVGLeagueType extends Pick<DocumentType<GVGLeague>, keyof GVGLeague> {
id: number;
};
export type GVGLeagueUpdate = Partial<GVGLeagueType>; // 将所有字段变成可选项