import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, Ref } from '@typegoose/typegoose'; import Role, { RoleType } from './Role'; import { GUILD_AUTH, USER_GUILD_STATUS, GUILD_JOB, SHOP_REFRESH_TYPE } from '../consts'; import { getZeroPointD, nowSeconds, isToday } from '../pubUtils/timeUtil'; import { ARMY } from '../pubUtils/dicParam'; class ActiveRecord { @prop({ required: true }) id: number; @prop({ required: true }) count: number; } export class WishGood { @prop({ required: true }) id: string;//随机生成的唯一id @prop({ required: true }) type: number;//1:表示装备池,2:武将池 @prop({ required: true }) goodId: number; @prop({ required: true }) count: number; //许愿次数 @prop({ required: true, default:0 }) receiveCnt: number; //收到次数 @prop({ required: true, default:0 }) drawCnt: number; //可以领取次数 @prop({ required: true, type: String, default: [] }) donateNames: string[]; } class RefineRecord { @prop({ required: true }) quality: number; @prop({ required: true }) count: number; } export class TrainBoxRewardRecord { @prop({ required: true }) hid: number; @prop({ required: true }) guildCode: string; } @index({ roleId: 1 }) @index({ guildCode: 1 }) export default class UserGuild extends BaseModel { @prop({ required: true }) guildCode: string; @prop({ required: true }) roleId: string; @prop({ required: true }) role: Ref; @prop({ required: true, default: GUILD_AUTH.MEMBER, enum: GUILD_AUTH }) auth: number; @prop({ required: true, default: GUILD_JOB.SHIBING, enum: GUILD_JOB }) job: number; @prop({ required: true, default: 0 }) activeWeekly: number; @prop({ required: true, default: 0 }) activeDaily: number; @prop({ required: true, default: nowSeconds() }) activeUpdateTime: number; @prop({ required: true, default: USER_GUILD_STATUS.ON, enum: USER_GUILD_STATUS}) status: number; @prop({ required: true, type: ActiveRecord, default: [], _id: false }) activeRecord: ActiveRecord[]; @prop({ required: true, type: Number, default: [] }) receivedActive: number[]; @prop({ required: true, select: false }) refTimeDaily: Date; //练兵场 @prop({ required: true, default: 0 }) trainCount: number;//每日挑战训练场的次数 @prop({ required: true, default: 0 }) buyTrainCount: number;//每日挑战训练场购买次数 @prop({ required: true, default: 0 }) trainTime: number;//上次刷新挑战训练场次数的时间每天5点 @prop({ required: true, default: [], type: Number }) trainRewards: Array;//领取过的进阶等级 @prop({ required: true, default: [], type: TrainBoxRewardRecord, _id: false }) trainBoxRewards: Array;//领取过的挑战奖励 //捐献所 @prop({ required: true, default: [], type: Number }) receiveBoxs: Array; //今天捐献所领取宝箱id记录, @prop({ required: true, default: 0 }) donateCnt: number;//今天捐献所次数 //许愿池 @prop({ required: true, default: [], type: WishGood, _id: false }) wishGoods: Array; @prop({ required: true, default: [], type: Number }) receivedWishPool: number[]; @prop({ required: true, default: 0 }) wishDntCnt: number;//今天许愿池捐献次数 // 演武台 @prop({ required: true }) refBossTime: Date; @prop({ required: true, default: 0 }) encourageCnt: number; //今天鼓舞次数 @prop({ required: true, default: 0 }) bossChallengeCnt: number;//今天挑战演舞台次数 // 炼器堂 @prop({ required: true, type: RefineRecord }) refineCnt: RefineRecord[]; @prop({ required: true }) refRefineTime: Date; public static async getMyGuild(roleId: string, select?: string) { const myGuild: UserGuildType = await UserGuildModel.findOne({ roleId, status: USER_GUILD_STATUS.ON }) .select(select).lean(); return myGuild; } 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) .populate('role', 'roleId roleName ce head frame spine heads frames spines lv title quitTime', 'Role') .lean({ getters: true, virtuals: true }); return userGuilds; } public static async findTopActive(guildCode: string, select?: string) { const userGuilds: UserGuildType[] = await UserGuildModel.find({ guildCode, status: USER_GUILD_STATUS.ON, auth: { $ne: GUILD_AUTH.LEADER } }) .sort({ activeWeekly: -1, activeUpdateTime: 1 }) .select(select) .populate('role', 'roleId roleName ce head frame spine heads frames spines lv title quitTime', 'Role') .lean({getters: true, virtuals: true }); return userGuilds; } public static async createUserGuild(guildCode: string, role: RoleType, isLeader: boolean) { const lastGuild = await UserGuildModel.findMyLastGuild(role.roleId, '+refTimeDaily'); let { receiveBoxs = [], donateCnt = 0, receivedActive = [], encourageCnt = 0, bossChallengeCnt = 0, receivedWishPool = [], wishGoods = [], wishDntCnt = 0, refTimeDaily, refBossTime, trainCount, buyTrainCount, trainTime, trainRewards = [], refineCnt = [], refRefineTime, trainBoxRewards = [] } = lastGuild||{}; const doc = new UserGuildModel(); 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, receiveBoxs, donateCnt, receivedActive, encourageCnt, bossChallengeCnt, receivedWishPool, wishGoods, wishDntCnt, refTimeDaily, refBossTime, trainCount, buyTrainCount, trainTime, trainRewards, refineCnt, refRefineTime, trainBoxRewards }); // trainRewards: 试炼奖励, 无论在任何情况下都不能被清空(次数可以重置,奖励领过就不能再领了,无论在哪个军团) // 【退出军团】 和 【再加入军团】不在同一天; 此处包含: 首次加入军团(lastGuild == null) if (!isToday(role.quitGuildTime) && lastGuild) { // 之前加入过军团 - 清空之前的数据 update.receiveBoxs = []; update.donateCnt = 0; update.receivedActive = []; update.encourageCnt = 0; update.bossChallengeCnt = 0; update.receivedWishPool = []; update.wishGoods = []; update.wishDntCnt = 0; update.trainCount = 0; update.buyTrainCount = 0; update.trainTime = 0; update.refineCnt = []; } delete update._id; const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId: role.roleId, guildCode, status: USER_GUILD_STATUS.ON }, { $set: update }, { upsert: true, new: true }) .select('activeDaily activeRecord activeWeekly activeUpdateTime job auth receivedActive guildCode trainBoxRewards') .lean(); return result; } public static async findMyLastGuild(roleId: string, select: string) { const userGuild = await UserGuildModel.findOne({ roleId, status: { $ne: USER_GUILD_STATUS.ON } }).select(select).sort({ createdAt: -1 }).lean(); return userGuild; } /** * 查询我今天所有加入过的军团(从上次的刷新时间(5AM)到现在) * * @static * @param {string} roleId * @param {string} select * @return {*} * @memberof UserGuild */ public static async findMyGuildsOfToday(roleId: string, select: string) { const userGuilds = await UserGuildModel.find({ roleId, createdAt: { $gt: getZeroPointD() } }).select(select).lean(); return userGuilds; } public static async dismiss(guildCode: string) { const result = await UserGuildModel.updateMany({ guildCode }, { status: USER_GUILD_STATUS.DISMISSED }); return result; } // 玩家退出公会 public static async quit(guildCode: string, roleId: string) { const result = await UserGuildModel.findOneAndUpdate({ guildCode, roleId, status: USER_GUILD_STATUS.ON }, {status: USER_GUILD_STATUS.QUIT}, {new: true}); return result; } public static async updateInfo(roleId: string, update: UserGuildUpdateParam, incParam: { activeDaily?: number, activeWeekly?: number, trainCount?: number }, select?: string) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $set: update, $inc: incParam }, { 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}, { $push:{trainRewards: trainId} },{new: true}).lean(lean); return result; } /** * 记录玩家领取过的试炼宝箱奖励(每个武将都有一个抽卡奖励) * * @static * @param {string} roleId * @param {number} trainId * @param {boolean} [lean=true] * @return {*} * @memberof UserGuild */ public static async receiveTrainBoxRewards(roleId: string, hid: number, guildCode: string, lean = true) { const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON}, { $push:{trainBoxRewards: {hid, guildCode}} },{new: true}).lean(lean); return result; } public static async addTrainCount(roleId: string, trainCount: number, lean = true) { const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON}, { $inc: { trainCount, buyTrainCount: trainCount } }, {new: true}).lean(lean); return result; } public static async resetTrainUserGuild(guildCode: string) { const result = await UserGuildModel.updateMany({ guildCode }, {$set: { trainCount: ARMY.ARMY_TRAIN_BUYTIMES, buyTrainCount: 0, trainTime: nowSeconds(), trainRewards: [] }}); return result; } /** * 重置上周加入的队员的试炼数据(本周加入的不能重置,否则会多领奖励) * * @static * @param {string} guildCode * @return {*} * @memberof UserGuild */ public static async resetTrainUserGuildLastWeekJoinedIn(guildCode: string) { const result = await UserGuildModel.updateMany({ guildCode, createdAt: {$lt: getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY)} }, {$set: { trainCount: ARMY.ARMY_TRAIN_BUYTIMES, buyTrainCount: 0, trainTime: nowSeconds(), trainRewards: [], trainBoxRewards: [] }}); return result; } public static async donateFund(roleId: string, donateCnt: number, lean = true) { const result = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON}, {$inc: { donateCnt }}, {new: true}).lean(lean); return result; } public static async getWishPoolGoods(guildCode: string, select?: string, lean = true) { const userGuilds: UserGuildType[] = await UserGuildModel.find({ guildCode, status: USER_GUILD_STATUS.ON, refTimeDaily: { $gte: getZeroPointD() } }) .select(select).lean(lean); return userGuilds; } public static async pushAndUpdate(roleId: string, update: UserGuildUpdateParam, pushData:{wishGoods?: WishGood}, select?: string) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $set: update, $push: pushData }, { new: true }).select(select).lean(); return result; } public static async donateGoods(roleId: string, wishDntCnt: number, select?: string) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $inc: { wishDntCnt } }, { new: true }).select(select).lean(); return result; } public static async donateUpdate(roleId: string, dntRoleName: string, id: string, select?: string) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON, 'wishGoods.id': id }, { $inc: { 'wishGoods.$.receiveCnt': 1, 'wishGoods.$.drawCnt': 1}, $push:{'wishGoods.$.donateNames': dntRoleName} }, { new: true }).select(select).lean(); return result; } public static async resetDailyInfo(roleId: string) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON }, { $set: { receivedActive: [], refTimeDaily: new Date(), activeDaily: 0, activeRecord: [], wishGoods: [], receivedWishPool: [], receiveBoxs: [], wishDntCnt: 0, donateCnt: 0 } }, { new: true }).lean(); return result; } public static async resetDailyInfoByRefTimeDaily(roleId: string, refTimeDaily: Date | null) { const result: UserGuildType = await UserGuildModel.findOneAndUpdate({ roleId, status: USER_GUILD_STATUS.ON, refTimeDaily }, { $set: { receivedActive: [], refTimeDaily: new Date(), activeDaily: 0, activeRecord: [], wishGoods: [], receivedWishPool: [], receiveBoxs: [], wishDntCnt: 0, donateCnt: 0 } }, { new: true }).lean(); return result; } } export const UserGuildModel = getModelForClass(UserGuild); export interface UserGuildType extends Pick, keyof UserGuild> { }; export type UserGuildUpdateParam = Partial; // 将所有字段变成可选项