✨ feat(gvg): 组建期
This commit is contained in:
48
shared/db/GVGConfig.ts
Normal file
48
shared/db/GVGConfig.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
|
||||
import { CounterModel } from './Counter';
|
||||
import { COUNTER } from '../consts';
|
||||
|
||||
@index({ configId: -1 })
|
||||
export default class GVGConfig extends BaseModel {
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
configId: number; // 配置唯一id
|
||||
|
||||
@prop({ required: true })
|
||||
teamTime: number; // 组建期开始
|
||||
|
||||
@prop({ required: true })
|
||||
prepareTime: number; // 准备期开始
|
||||
|
||||
@prop({ required: true })
|
||||
battleTime: number; // 激战期开始
|
||||
|
||||
@prop({ required: true })
|
||||
scheduleTime: number; // 下次定时任务时间
|
||||
|
||||
public static async createNewConfig(teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) {
|
||||
const configId = await CounterModel.getNewCounter(COUNTER.GVG_CONFIG);
|
||||
const result: GVGConfigType = await GVGConfigModel.findOneAndUpdate({ configId }, { $set: { teamTime, prepareTime, battleTime, scheduleTime } }, { upsert: true, new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findConfig() {
|
||||
let configId = await CounterModel.getCounter(COUNTER.GVG_CONFIG);
|
||||
const result: GVGConfigType = await GVGConfigModel.findOne({ configId }, { _id: 0 }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async updateConfig(configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) {
|
||||
const result: GVGConfigType = await GVGConfigModel.findOneAndUpdate({ configId }, { $set: { teamTime, prepareTime, battleTime, scheduleTime } }, { new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const GVGConfigModel = getModelForClass(GVGConfig);
|
||||
|
||||
export interface GVGConfigType extends Pick<DocumentType<GVGConfig>, keyof GVGConfig> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGConfigUpdate = Partial<GVGConfigType>; // 将所有字段变成可选项
|
||||
195
shared/db/GVGLeague.ts
Normal file
195
shared/db/GVGLeague.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
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';
|
||||
|
||||
class Member {
|
||||
@prop({ required: true })
|
||||
roleId: string;
|
||||
@prop({ required: true })
|
||||
auth: 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: 0 })
|
||||
leagueCe: 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, guildCe, 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 }));
|
||||
const update = Object.assign(doc.toJSON(), { guildCodes: [code], name: `${name}联军`, guildCnt: 1, memberCnt, isAuto: true, leagueCe: guildCe, 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) {
|
||||
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')
|
||||
.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, _id: 0 }, 'Role')
|
||||
.lean();
|
||||
return leagues
|
||||
}
|
||||
|
||||
public static async joinGuild(leagueCode: string, guild: GuildType) {
|
||||
const { code, memberCnt, leader, guildCe, members } = guild;
|
||||
let _leader = <RoleType>leader;
|
||||
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.SUB_LEADER: LEAGUE_AUTH.MEMBER }));
|
||||
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
|
||||
{ $push: { guildCodes: code, members: { $each: _members } }, $inc: { guildCnt: 1, memberCnt: memberCnt, leagueCe: guildCe }
|
||||
}, { new: true }).lean();
|
||||
return league
|
||||
}
|
||||
|
||||
public static async findAllLeague() {
|
||||
const leagues: { leagueCode: string, memberCnt: number }[] = await GVGLeagueModel.aggregate([
|
||||
{ $match: { status: 1 } },
|
||||
{ $project: { leagueCode: 1, memberCnt: 1 } }
|
||||
]);
|
||||
return leagues;
|
||||
}
|
||||
|
||||
public static async quitGuild(leagueCode: string, guild: GuildType) {
|
||||
const { code, memberCnt, members, guildCe } = guild;
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
|
||||
{ $pull: { guildCodes: code, members: { roleId: { $in: members } } }, $inc: { guildCnt: -1, memberCnt: -memberCnt, leagueCe: -guildCe }
|
||||
}, { 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 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 updateCe(roleId: string, incCe: number) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ 'members.roleId': roleId, status: 1 }, { $inc: { leagueCe: incCe } }, { new: true }).lean();
|
||||
return league;
|
||||
}
|
||||
|
||||
public static async joinMember(leagueCode: string, roleId: string, ce: number) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $push: { members: { roleId, auth: LEAGUE_AUTH.MEMBER } }, $inc: { memberCnt: 1, leagueCe: ce } }, { new: true }).lean();
|
||||
return league;
|
||||
}
|
||||
|
||||
public static async quitMember(leagueCode: string, roleId: string, ce: number) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $pull: { members: { roleId } }, $inc: { memberCnt: -1, leagueCe: -ce } }, { 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
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGLeagueModel = getModelForClass(GVGLeague);
|
||||
|
||||
export interface GVGLeagueType extends Pick<DocumentType<GVGLeague>, keyof GVGLeague> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGLeagueUpdate = Partial<GVGLeagueType>; // 将所有字段变成可选项
|
||||
104
shared/db/GVGLeagueApply.ts
Normal file
104
shared/db/GVGLeagueApply.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { getModelForClass, prop, DocumentType, index, Ref } from '@typegoose/typegoose';
|
||||
import GVGLeague, { GVGLeagueType } from './GVGLeague';
|
||||
import Guild, { GuildType } from './Guild';
|
||||
import { GVG_APPLY_TYPE } from '../consts';
|
||||
|
||||
@index({ leagueCode: 1, guildCode: 1, type: 1 })
|
||||
export default class GVGLeagueApply extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 发起的联军 or 收到申请的联军
|
||||
|
||||
@prop({ required: true })
|
||||
league: Ref<GVGLeague>;
|
||||
|
||||
@prop({ required: true })
|
||||
guildCode: string; // 受邀的军团 or 发出申请的联军
|
||||
|
||||
@prop({ required: true })
|
||||
guild: Ref<Guild>;
|
||||
|
||||
@prop({ required: true })
|
||||
type: number; // 类型 1-邀请 2-申请
|
||||
|
||||
public static async findApplyFromGuild(guildCode: string) {
|
||||
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ guildCode, type: GVG_APPLY_TYPE.APPLY }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async checkApply(leagueCode: string, guildCode: string, type: GVG_APPLY_TYPE) {
|
||||
console.log('####', leagueCode, guildCode, type)
|
||||
const result = await GVGLeagueApplyModel.exists({ guildCode, leagueCode,
|
||||
type: type == GVG_APPLY_TYPE.ALL? { $in: [GVG_APPLY_TYPE.APPLY, GVG_APPLY_TYPE.INVITE] }: type
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async createApply(league: GVGLeagueType, guild: GuildType, type: number) {
|
||||
const result: GVGLeagueApplyType = await GVGLeagueApplyModel.findOneAndUpdate({ leagueCode: league.leagueCode, guildCode: guild.code, type }, { $set: { league: league._id, guild: guild._id, }}, { new: true, upsert: true })
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findApplyFromLeague(leagueCode: string) {
|
||||
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ leagueCode, type: GVG_APPLY_TYPE.APPLY })
|
||||
.select({ _id: 0, guild: 1, guildCode: 1 })
|
||||
.populate({
|
||||
path: 'guild',
|
||||
select: 'code icon name lv memberCnt leader guildCe +serverId',
|
||||
model: 'Guild',
|
||||
populate: {
|
||||
path: 'leader',
|
||||
select: 'roleName',
|
||||
model: 'Role'
|
||||
}
|
||||
})
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findInviteFromLeague(leagueCode: string) {
|
||||
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ leagueCode, type: GVG_APPLY_TYPE.INVITE }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findInviteFromGuild(guildCode: string) {
|
||||
const result: GVGLeagueApplyType[] = await GVGLeagueApplyModel.find({ guildCode, type: GVG_APPLY_TYPE.INVITE })
|
||||
.select({ _id: 0, guild: 1, guildCode: 1 })
|
||||
.populate({
|
||||
path: 'league',
|
||||
// select: 'code icon name lv memberCnt leader guildCe +serverId',
|
||||
model: 'GVGLeague',
|
||||
populate: {
|
||||
path: 'leader',
|
||||
select: 'roleName',
|
||||
model: 'Role'
|
||||
}
|
||||
})
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async deleteApply(guildCode: string, leagueCode: string) {
|
||||
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, leagueCode, type: GVG_APPLY_TYPE.APPLY });
|
||||
return n;
|
||||
}
|
||||
|
||||
public static async deleteAllGuildApply(guildCode: string) {
|
||||
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, type: GVG_APPLY_TYPE.APPLY });
|
||||
return n;
|
||||
}
|
||||
|
||||
public static async deleteInvite(guildCode: string, leagueCode: string) {
|
||||
const n = await GVGLeagueApplyModel.deleteMany({ guildCode, leagueCode, type: GVG_APPLY_TYPE.INVITE });
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGLeagueApplyModel = getModelForClass(GVGLeagueApply);
|
||||
|
||||
export interface GVGLeagueApplyType extends Pick<DocumentType<GVGLeagueApply>, keyof GVGLeagueApply> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGLeagueApplyUpdate = Partial<GVGLeagueApplyType>; // 将所有字段变成可选项
|
||||
82
shared/db/GVGLeaguePrepare.ts
Normal file
82
shared/db/GVGLeaguePrepare.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
|
||||
class Tech {
|
||||
@prop({ required: true, default: 0 })
|
||||
id: number;
|
||||
@prop({ required: true, default: 0 })
|
||||
progress: number; // 贡献
|
||||
@prop({ required: true, default: 0 })
|
||||
status: number; // 0-已解锁 1-已激活
|
||||
}
|
||||
|
||||
class DonateRec {
|
||||
@prop({ required: true, default: 0 })
|
||||
roleId: string;
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number;
|
||||
@prop({ required: true, default: 0 })
|
||||
count: number;
|
||||
}
|
||||
|
||||
class Resource {
|
||||
@prop({ required: true, default: 0 })
|
||||
food: number; // 粮食
|
||||
@prop({ required: true, default: 0 })
|
||||
mineral: number; // 矿物
|
||||
@prop({ required: true, default: 0 })
|
||||
wood: number; // 木堆
|
||||
}
|
||||
|
||||
@index({ leagueCode: 1, configId: 1 })
|
||||
export default class GVGLeaguePrepare extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
configId: number; // 赛期配置id
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 联军
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
lv: number; // 等级
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
maxMemberCnt: number; // 进入备战期初始玩家人数
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
producerCnt: number; // 选择内政人数
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
fighterCnt: number; // 选择外政人数
|
||||
|
||||
@prop({ required: true, default: [], type: Tech, _id: false })
|
||||
tech: Tech[]; // 千机阁
|
||||
|
||||
@prop({ required: true, default: [], type: DonateRec, _id: false })
|
||||
donateRec: DonateRec[]; // 捐献记录
|
||||
|
||||
@prop({ required: true, default: {food: 0, mineral: 0, wood: 0}, type: Resource, _id: false })
|
||||
resources: Resource
|
||||
|
||||
public static async initData(configId: number, leagueCode: string, maxMemberCnt: number) {
|
||||
const doc = new GVGLeaguePrepareModel();
|
||||
const update = Object.assign(doc.toJSON(), { maxMemberCnt });
|
||||
delete update._id;
|
||||
|
||||
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({ configId, leagueCode }, { $setOnInsert: update }, { upsert: true, new: true })
|
||||
.select({ _id: 0, __v: 0, createdAt: 0, updatedAt: 0 }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findByLeague(configId: number, leagueCode: string) {
|
||||
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOne({ configId, leagueCode }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGLeaguePrepareModel = getModelForClass(GVGLeaguePrepare);
|
||||
|
||||
export interface GVGLeaguePrepareType extends Pick<DocumentType<GVGLeaguePrepare>, keyof GVGLeaguePrepare> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGLeaguePrepareUpdate = Partial<GVGLeaguePrepareType>; // 将所有字段变成可选项
|
||||
41
shared/db/GVGServerGroup.ts
Normal file
41
shared/db/GVGServerGroup.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
|
||||
|
||||
/**
|
||||
* 服务器分战区
|
||||
*/
|
||||
@index({ time: -1, serverId: -1 })
|
||||
export default class GVGServerGroup extends BaseModel {
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
serverId: number; // 服务器id
|
||||
|
||||
@prop({ required: true, default: 1 })
|
||||
groupId: number; // 战区id
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number; // 生效时间
|
||||
|
||||
public static async findByTime(time: number) {
|
||||
const serverGroup: { serverId: number, groupId: number }[] = await GVGServerGroupModel.aggregate([
|
||||
{ $match: { time: { $lte: time } } },
|
||||
{ $sort: { time: -1 } },
|
||||
{ $group: { _id: "$id", serverId: { $first: "$serverId" }, groupId: { $first: "$groupId" }, time: { $first: "$time" }} },
|
||||
{ $sort: { _id: -1 } },
|
||||
{ $project: { _id: 0, id: "$_id", serverId: "$serverId", groupId: "$groupId", time: "$time" } }
|
||||
]);
|
||||
return serverGroup;
|
||||
}
|
||||
|
||||
public static async updateByServerId(serverId: number, groupId: number, time: number) {
|
||||
const result: GVGServerGroupType = await GVGServerGroupModel.findOneAndUpdate({ serverId, time }, { $set: { groupId } }, { new: true, upsert: true }).lean();
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export let GVGServerGroupModel = getModelForClass(GVGServerGroup);
|
||||
|
||||
export interface GVGServerGroupType extends Pick<DocumentType<GVGServerGroup>, keyof GVGServerGroup> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGServerGroupUpdate = Partial<GVGServerGroupType>; // 将所有字段变成可选项
|
||||
81
shared/db/GVGUserData.ts
Normal file
81
shared/db/GVGUserData.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
|
||||
class ActiveRec {
|
||||
@prop({ required: true, default: 1 })
|
||||
id: number; // 1-内政令消耗 2-征战令消耗 3-科技树捐献
|
||||
@prop({ required: true, default: 0 })
|
||||
count: number;
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number;
|
||||
}
|
||||
|
||||
class Box {
|
||||
@prop({ required: true, default: 0 })
|
||||
score: number; // 宝箱积分
|
||||
@prop({ required: true, default: [], type: Number })
|
||||
received: number[]; // 领取记录
|
||||
}
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
|
||||
export default class GVGUserData extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
roleId: string; // 玩家
|
||||
|
||||
@prop({ required: true })
|
||||
configId: number; // 赛季信息
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 所属联军
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
job: number; // 职能 1-贤臣 2-猛将
|
||||
|
||||
// 备战期
|
||||
@prop({ required: true, default: 0 })
|
||||
active: number; // 活跃度
|
||||
|
||||
@prop({ required: true, default: 0, type: ActiveRec, _id: false })
|
||||
activeRec: ActiveRec[]; // 活跃度记录
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
receivedLv: number; // 领取到的等级奖励
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
receiveCurrencyTime: number; // 领取内政令&征战令时间
|
||||
|
||||
@prop({ required: true, default: { score: 0, received: []}, type: Box, _id: false })
|
||||
box: Box;
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
sendFightRewardTime: number; // 发送征战奖励的时间
|
||||
// 激战期
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
battleStatus: number; // 1-被挑战中 0-可被挑战
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
area: number; // 所处区域 1-进攻北站 2-混战 3-据点 4-防守备战
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
protectTime: number; // 保护期
|
||||
|
||||
|
||||
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
|
||||
const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, {}, { new: true, upsert: true}).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findByRoles(configId: number, leagueCode: string, roleIds: string[]) {
|
||||
const result: GVGUserDataType[] = await GVGUserDataModel.find({ configId, leagueCode, roleId: { $in: roleIds } }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserDataModel = getModelForClass(GVGUserData);
|
||||
|
||||
export interface GVGUserDataType extends Pick<DocumentType<GVGUserData>, keyof GVGUserData> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGUserDataUpdate = Partial<GVGUserDataType>; // 将所有字段变成可选项
|
||||
37
shared/db/GVGUserItem.ts
Normal file
37
shared/db/GVGUserItem.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { nowSeconds } from '../pubUtils/timeUtil';
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
|
||||
export default class GVGUserItem extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
roleId: string; // 玩家
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 联军id
|
||||
|
||||
@prop({ required: true })
|
||||
configId: number; // 赛期
|
||||
|
||||
@prop({ required: true })
|
||||
id: number; // 道具: 包括 种子、铲子、斧子
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
count: number; // 数量
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
expireTime: number;
|
||||
|
||||
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
|
||||
const result: GVGUserItemType[] = await GVGUserItemModel.find({ configId, leagueCode, roleId, expireTime: { $gte: nowSeconds() } }, { _id: 0 }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserItemModel = getModelForClass(GVGUserItem);
|
||||
|
||||
export interface GVGUserItemType extends Pick<DocumentType<GVGUserItem>, keyof GVGUserItem> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGUserItemUpdate = Partial<GVGUserItemType>; // 将所有字段变成可选项
|
||||
41
shared/db/GVGUserTask.ts
Normal file
41
shared/db/GVGUserTask.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { getZeroPointD } from '../pubUtils/timeUtil';
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
|
||||
export default class GVGUserTask extends BaseModel {
|
||||
|
||||
@prop({ required: true, default: '' })
|
||||
roleId: string; // 玩家
|
||||
|
||||
@prop({ required: true, default: '' })
|
||||
leagueCode: string; // 联军id
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
configId: number; // 赛期
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
id: number; // 任务id
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
count: number; // 1-已达成
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
status: number; // 1-未领取 2-已领取
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
createTime: number; // 1-未领取 2-已领取
|
||||
|
||||
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
|
||||
let today = getZeroPointD();
|
||||
const result: GVGUserTaskType[] = await GVGUserTaskModel.find({ configId, leagueCode, roleId, createdAt: { $gte: today } }, { _id: 0, id: 1, count: 1, status: 1 }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserTaskModel = getModelForClass(GVGUserTask);
|
||||
|
||||
export interface GVGUserTaskType extends Pick<DocumentType<GVGUserTask>, keyof GVGUserTask> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGUserTaskUpdate = Partial<GVGUserTaskType>; // 将所有字段变成可选项
|
||||
@@ -111,6 +111,9 @@ export default class Guild extends BaseModel {
|
||||
@prop({ required: true })
|
||||
sdkMark: boolean; // 37sdk标记有问题
|
||||
|
||||
@prop({ required: true, default: '' })
|
||||
leagueCode: string; // 参与联军
|
||||
|
||||
public static async createGuild(params: { guildCode: string, name: string, icon: number, notice: string }, role: RoleType, serverId: number) {
|
||||
const doc = new GuildModel();
|
||||
const update = Object.assign(doc.toJSON(), params, { leader: role._id, members: [role.roleId], guildCe: role.ce, serverId, lvUpdateTime: nowSeconds() });
|
||||
@@ -175,7 +178,7 @@ export default class Guild extends BaseModel {
|
||||
if(serverId) condition.serverId = serverId;
|
||||
const result: GuildType = await GuildModel.findOne(condition)
|
||||
.select(select)
|
||||
.populate('leader', {roleId: 1, roleName: 1, frame: 1, head: 1, spine: 1, frames: 1, heads: 1, spines: 1, lv: 1, quitTime: 1, ce: 1, title: 1, _id: 0}, 'Role')
|
||||
.populate('leader', {roleId: 1, roleName: 1, frame: 1, head: 1, spine: 1, frames: 1, heads: 1, spines: 1, lv: 1, quitTime: 1, ce: 1, title: 1}, 'Role')
|
||||
.lean({ getters: true, virtuals: true });
|
||||
return result;
|
||||
}
|
||||
@@ -315,6 +318,41 @@ export default class Guild extends BaseModel {
|
||||
const result = await GuildModel.count(searchObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async joinLeague(guildCode: string, leagueCode: string) {
|
||||
const result: GuildType = await GuildModel.findOneAndUpdate({ code: guildCode }, { $set: { leagueCode } }, { new: true }).lean();
|
||||
return result
|
||||
}
|
||||
|
||||
public static async findGuildsForGVG(page: number, name: string, serverIds: number[]) {
|
||||
let query: any = { status: GUILD_STATUS.RUNNING, lv: { $gte: 3 }, leagueCode: '', serverId: { $in: serverIds } };
|
||||
if(name) {
|
||||
query['name'] = { $regex: new RegExp(name, 'i') }
|
||||
}
|
||||
const result: GuildType[] = await GuildModel.find(query)
|
||||
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
|
||||
.skip((page - 1) * 30).limit(30)
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findByCodes(codes: string[]) {
|
||||
const result: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, code: { $in: codes } })
|
||||
.select('+serverId')
|
||||
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async quitFromLeague(guildCode: string, leagueCode: string, select = null) {
|
||||
const result: GuildType = await GuildModel.findOneAndUpdate({ code: guildCode, leagueCode }, { $set: { leagueCode: '' } }, { new: true }).select(select).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async dissmissLeague(leagueCode: string) {
|
||||
const result: GuildType = await GuildModel.findOneAndUpdate({ leagueCode }, { $set: { leagueCode: '' }}).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GuildModel = getModelForClass(Guild);
|
||||
|
||||
Reference in New Issue
Block a user