import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; import { TASK_FUN_TYPE } from '../consts'; import { genCode } from '../pubUtils/util'; import { getZeroPointD } from '../pubUtils/timeUtil'; import { UpdateTaskParam } from '../domain/roleField/task'; /** * 玩家任务记录表 **/ @modelOptions({ schemaOptions: { id: false } }) @index({ code: 1 }) @index({ roleId: 1, type: 1, taskType: 1, group: 1 }) export default class UserTaskRec extends BaseModel { @prop({ required: true }) code: string; // 该记录唯一标识 @prop({ required: true }) roleId: string; // 玩家id @prop({ required: true, enum: TASK_FUN_TYPE }) type: number; // 任务类型 @prop({ required: true }) taskType: number; // 行为类型 @prop({ required: true }) group: string; // 行为类型下的分组 @prop({ required: true }) count: number; // 达成次数 @prop({ required: true, type: Number, default: [] }) received: number[]; // 是否已领取 @prop({ required: true, type: String, default: [] }) records: string[]; // 历史记录 private static getRefreshCondition(type: number) { let today = getZeroPointD(); if(type == TASK_FUN_TYPE.DAILY || type == TASK_FUN_TYPE.PVP) { return { type, createdAt: { $gte: today } }; } else { return { type }; } } public static async setTaskRec(roleId: string, type: number, taskType: number, group: string, count: number, record?: string) { let condition = this.getRefreshCondition(type); let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, group, taskType, ...condition }, { $setOnInsert: { code: genCode(8), received: [] }, $set: { count }, $addToSet: { records: record||'' } }, { new: true, upsert: true }).lean(); return rec; } public static async incTaskRec(roleId: string, type: number, taskType: number, group: string, count: number, record?: string) { let condition = this.getRefreshCondition(type); let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, group, taskType, ...condition }, { $setOnInsert: { code: genCode(8), received: [] }, $inc: { count }, $addToSet: { records: record||'' } }, { new: true, upsert: true }).lean(); return rec; } /** * 检查是否可以更新任务并更新 * @param roleId 玩家id * @param type 任务大类型,日常、成就、每日 * @param taskType 任务类型 * @param group 活动组 * @param param 更新参数 * @returns */ public static async checkAndUpdateTask(roleId: string, type: TASK_FUN_TYPE, taskType: number, group: string, param: UpdateTaskParam) { let canSet = true; if(param.record || param.max || param.min) { let rec = await this.findByRoleAndGroup(roleId, type, taskType, group); if(rec) { if(param.record && rec.records.indexOf(param.record) != -1) { canSet = false; } else if (param.max && rec.count >= param.max) { canSet = false; } else if (param.min && rec.count <= param.min) { canSet = false; } } } if(canSet) { return await this.setOrIncTask(roleId, type, taskType, group, param); } } public static async setOrIncTask(roleId: string, type: number, taskType: number, group: string, param: UpdateTaskParam) { if(param.set) { return await this.setTaskRec(roleId, type, taskType, group, param.set, param.record); } else if (param.inc) { return await this.incTaskRec(roleId, type, taskType, group, param.inc, param.record); } } public static async checkHistoryAndSetTaskRec(roleId: string, type: number, taskType: number, group: string, count: number) { let rec: UserTaskRecType = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); if(rec) { if(rec.count < count) { rec = await UserTaskRecModel.setTaskRec(roleId, type, taskType, group, count); } } else { rec = await UserTaskRecModel.setTaskRec(roleId, type, taskType, group, count); } return rec; } public static async checkRecordAndIncTaskRec(roleId: string, type: number, taskType: number, group: string, count: number, record: string) { let rec: UserTaskRecType = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); if(!rec || rec.records.indexOf(record) == -1) { let condition = this.getRefreshCondition(type); rec = await UserTaskRecModel.findOneAndUpdate({ roleId, group, taskType, ...condition }, { $setOnInsert: { code: genCode(8), received: [] }, $inc: { count }, $push: { records: record } }, { new: true, upsert: true }).lean(); } return rec; } public static async findByRoleAndType(roleId: string, type: number) { let condition = this.getRefreshCondition(type); let rec: UserTaskRecType[] = await UserTaskRecModel.find({ roleId, ...condition }).lean(); let map = new Map>(); // taskType => group => userTask for(let userTaskRec of rec) { let { taskType, group } = userTaskRec; if(!map.has(taskType)) { map.set(taskType, new Map()); } map.get(taskType).set(group, userTaskRec); } return map; } public static async findByRoleAndGroup(roleId: string, type: number, taskType: number, group: string) { let condition = this.getRefreshCondition(type); let rec: UserTaskRecType = await UserTaskRecModel.findOne({ roleId, taskType, group, ...condition }).lean(); return rec; } public static async receiveTask(roleId: string, type: number, taskType: number, group: string, id: number) { let condition = this.getRefreshCondition(type); let rec: UserTaskRecType = await UserTaskRecModel.findOneAndUpdate({ roleId, taskType, group, ...condition }, { $push: { received: id } }, { new: true }).lean(); return rec; } public static async getReceiveRec(roleId: string, type: number) { let condition = this.getRefreshCondition(type); let rec = await UserTaskRecModel.find({ roleId, ...condition }).lean(); return rec } public static async getHistoryRec(roleId: string, type: number, today?: Date) { if(!today) today = getZeroPointD(); let rec: UserTaskRecType[] = await UserTaskRecModel.find({ roleId, type, createdAt: { $lt: today } }).lean(); return rec } public static async deleteHistory(history: UserTaskRecType[]) { let codes = history.map(cur => cur.code); let result = await UserTaskRecModel.deleteMany({ code: { $in: codes } }); return result; } } export const UserTaskRecModel = getModelForClass(UserTaskRec); export interface UserTaskRecType extends Pick, keyof UserTaskRec> { } export type UserTaskRecParam = Partial;