// 征战中原对手锁 import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; import { OppPlayerInfo, OppPlayerHeroInfo } from '../domain/gvgField/gvgDb'; import { genCode } from '../pubUtils/util'; import { getTimeFunD } from '../pubUtils/timeUtil'; class LeagueGood { @prop({ required: true }) itemType: number; @prop({ required: true }) id: number; @prop({ required: true }) count: number } @index({ battleCode: 1 }) @index({ groupKey: 1, vestigeId: 1, rank: 1 }) @index({ attackRoleId: 1 }) @index({ defenseRoleId: 1 }) export default class GVGVestigeRec extends BaseModel { @prop({ required: true }) battleCode: string; // 唯一code @prop({ required: true }) warId: number; // 关卡id @prop({ required: true }) attackRoleId: string; // 攻方玩家id @prop({ required: true }) defenseRoleId: string; // 守方玩家id @prop({ required: true }) configId: number; // 赛期 @prop({ required: true }) groupKey: string; // 战区id @prop({ required: true }) vestigeId: number; // 遗迹id @prop({ required: true }) cancel: boolean; // 是否取消了 @prop({ required: true }) checkTime: number; // 开始出兵的时间,13位时间戳 @prop({ required: true }) battleTime: number; // 开始挑战的时间,13位时间 @prop({ required: true }) endTime: number; // 结束时间,13位时间戳 @prop({ required: true, type: () => OppPlayerInfo, default: {}, _id: false }) attackInfo: OppPlayerInfo; // 攻方信息 @prop({ required: true, type: () => OppPlayerInfo, default: {}, _id: false }) defenseInfo: OppPlayerInfo; // 守方信息 @prop({ required: true, type: () => LeagueGood, default: [], _id: false }) leagueGoods: LeagueGood[]; // 奖励 @prop({ required: true, default: false }) hasRpl: boolean; // 是否存在对应录像 @prop({ required: true, default: false }) remoteUrl: string; // 录像文件 public static async createRec(configId: number, vestigeId: number, groupKey: string, warId: number, attackInfo: OppPlayerInfo, defenseInfo: OppPlayerInfo, leagueGoods: LeagueGood[]) { const battleCode = genCode(10); const result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ battleCode }, { $set: { configId, vestigeId, groupKey, attackRoleId: attackInfo.roleId, defenseRoleId: defenseInfo.roleId, warId, checkTime: Date.now(), attackInfo, defenseInfo, leagueGoods } }, { new: true, upsert: true }).lean(); return result; } public static async findByBattleCode(battleCode: string, select = '') { const result: GVGVestigeRecType = await GVGVestigeRecModel.findOne({ battleCode }).select(select).lean(); return result; } public static async startBattle(battleCode: string, attackHeroes: OppPlayerHeroInfo[], ce: number) { const result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ battleCode }, { $set: { battleTime: Date.now(), 'attackInfo.heroes': attackHeroes, 'attackInfo.ce': ce } }, { new: true }).lean(); return result; } public static async battleEnd(battleCode: string, isSuccess: boolean, endTime: number, atkNewRank?: number, defNewRank?: number) { // console.log('battleEnd', battleCode, isSuccess, endTime, atkNewRank, defNewRank) let update: GVGVestigeRecUpdate = { endTime }; if(isSuccess) { update['attackInfo.isSuccess'] = true; update['defenseInfo.isSuccess'] = false; } if(atkNewRank != undefined && defNewRank != undefined) { update['attackInfo.newRank'] = atkNewRank; update['defenseInfo.newRank'] = defNewRank; update['attackInfo.oldRank'] = isSuccess? defNewRank: atkNewRank; update['defenseInfo.oldRank'] = isSuccess? atkNewRank: defNewRank; } const result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ battleCode }, { $set: update }, { new: true }).lean(); return result; } public static async giveup(roleId: string, battleCode: string) { const result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ attackRoleId: roleId, battleCode }, { $set: { cancel: true, endTime: Date.now() }}, { new: true }).lean(); return result; } public static async updateRplStatus(battleCode: string, hasRpl: boolean, remoteUrl: string) { let result: GVGVestigeRecType = await GVGVestigeRecModel.findOneAndUpdate({ battleCode }, { hasRpl, remoteUrl }, { new: true }).lean(); return result; } public static async findRec(roleId: string, vestigeId: number) { let recs: GVGVestigeRecType[] = await GVGVestigeRecModel.find({ vestigeId, $or: [{attackRoleId: roleId}, { defenseRoleId: roleId }], createdAt: { $gte: getTimeFunD().getBeforeDayWithHour(3) }, }).select({ battleCode: 1, attackRoleId: 1, defenseRoleId: 1, _id: 0, endTime: 1, attackInfo: 1, defenseInfo: 1, hasRpl: 1, remoteUrl: 1 }).limit(1000).lean(); return recs; } public static async findRecCurDay(roleId: string, startMs:number) { const pipeline = [ { $match: {endTime: { $gt: startMs }, $or: [{ attackRoleId: roleId }, { defenseRoleId: roleId }]} }, { $sort: { endTime: -1 } }, // { $limit: 1000 }, ]; let result:GVGVestigeRecType[] = [] const recs: GVGVestigeRecType[] = await GVGVestigeRecModel.aggregate(pipeline); if (recs.length > 0) { for(const obj of recs){ if(obj.defenseRoleId == roleId && (!obj.defenseInfo.isSuccess) && obj.defenseInfo.newRank > obj.defenseInfo.oldRank ) result.push(obj); } } return result; } } export const GVGVestigeRecModel = getModelForClass(GVGVestigeRec); export interface GVGVestigeRecType extends Pick, keyof GVGVestigeRec> {}; export type GVGVestigeRecUpdate = Partial; // 将所有字段变成可选项