import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, mongoose } from '@typegoose/typegoose'; import { RoleType } from './Role'; import { getZeroPoint } from '../pubUtils/timeUtil'; import { Combo } from '../domain/battleField/pvp'; export class Lineup { @prop({ required: true }) actorId: number; // 武将 @prop({ required: true }) dataId: number; // 出兵表上所占位置 @prop({ required: true }) order: number; // 行动顺序 @prop({ required: true }) ce: number; // 战力 @prop({ required: true }) correspondingVar?: number; @prop({ required: true }) subHid: number; // 战力 } @index({ day: 1, groupKey: 1, vestigeId: 1, rank: 1 }) @index({ roleId: 1 }) export default class GVGVestigeRank extends BaseModel { @prop({ required: true }) configId: number; // 赛期 @prop({ required: true }) day: number; // 每天5点 @prop({ required: true }) groupKey: string; // 战区 @prop({ required: true }) vestigeId: number; // 遗迹id @prop({ required: true }) roleId: string; // 玩家 @prop({ required: true }) leagueCode: string; // 联军 @prop({ required: true }) name: string; // 联军名字 @prop({ required: true, default: 0 }) rank: number; // 排名 @prop({ required: true, default: 0 }) oldRank: number; // 交换前排名 @prop({ required: true, default: 0 }) historyRank: number; // 历史最高排名 @prop({ required: true, default: false }) hasDefense: boolean; // 是否调整过阵容,首次挑战自动保存阵容 @prop({ required: true, type: Lineup, default: [], _id: false }) lineup: Lineup[]; // 阵容 @prop({ required: true, type: () => Combo, default: [], _id: false }) combo: Combo[]; // 阵容 @prop({ required: true, type: Number, default: [], _id: false }) oppRanks: number[]; // 对手的排名 @prop({ required: true, default: 0 }) refreshCnt: number; // 刷新次数 public static async findAllByRole(roleId: string) { let today = getZeroPoint(); let result: GVGVestigeRankType[] = await GVGVestigeRankModel.find({ day: today, roleId }).lean(); return result; } public static async findByRole(vestigeId: number, roleId: string) { let today = getZeroPoint(); let result: GVGVestigeRankType = await GVGVestigeRankModel.findOne({ day: today, vestigeId, roleId }).lean(); return result; } public static async findByRank(configId: number, groupKey: string, vestigeId: number, rank: number) { let today = getZeroPoint(); let result: GVGVestigeRankType = await GVGVestigeRankModel.findOne({ configId, groupKey, day: today, vestigeId, rank }).lean(); return result; } public static async initRank(configId: number, vestigeId: number, groupKey: string, role: RoleType, leagueCode: string, name: string, oppRanks: number[]) { let today = getZeroPoint(); let doc = new GVGVestigeRankModel(); let update = Object.assign(doc.toJSON(), { role: role._id, configId, groupKey, oppRanks, leagueCode, name }); let result: GVGVestigeRankType = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId: role.roleId }, { $setOnInsert: update }, { new: true, upsert: true }).lean(); return result; } public static async updateByRoleId(vestigeId: number, roleId: string, update: GVGVestigeRankUpdate) { let today = getZeroPoint(); let result: GVGVestigeRankType = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId }, { $set: update }, { new: true, upsert: true }).lean(); return result; } public static async findByRanks(groupKey: string, vestigeId: number, ranks: number[]) { let today = getZeroPoint(); let result: GVGVestigeRankType[] = await GVGVestigeRankModel.find({ day: today, vestigeId, groupKey, rank: { $in: ranks } }) .lean(); return result; } public static async updateCe(roleId: string, hid: number, ce: number) { let today = getZeroPoint(); await GVGVestigeRankModel.updateMany({ day: today, hasDefense: true, roleId, 'lineup.actorId': hid }, { $set: { 'lineup.$.ce': ce } }); } public static async changeRank(isSuccess: boolean, vestigeId: number, attackInfo: { roleId: string }, defenseInfo: { isRobot: boolean, roleId: string, oldRank: number }): Promise<{ isChange: boolean, atkData?: GVGVestigeRankType, defData?: GVGVestigeRankType, oldAtkData?: GVGVestigeRankType, endTime: number }> { let today = getZeroPoint(); const session = await mongoose.connection.startSession(); session.startTransaction() try { let newAtkData: GVGVestigeRankType, newDefData: GVGVestigeRankType, atkData: GVGVestigeRankType, isChange = false, endTime = Date.now(); if(defenseInfo.isRobot) { atkData = await GVGVestigeRankModel.findOne({ day: today, vestigeId, roleId: attackInfo.roleId }).lean(); if(isSuccess && atkData && (atkData.rank == 0 || atkData.rank > defenseInfo.oldRank)) { newAtkData = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId: attackInfo.roleId }, { $set: { rank: defenseInfo.oldRank, oldRank: atkData.rank } }, { new: true, session }).lean(); isChange = true; endTime = Date.now(); } else { newAtkData = atkData; } } else { atkData = await GVGVestigeRankModel.findOne({ day: today, vestigeId, roleId: attackInfo.roleId }).lean(); let defData = await GVGVestigeRankModel.findOne({ day: today, vestigeId, roleId: defenseInfo.roleId }).lean(); if(isSuccess && atkData && defData && (atkData.rank == 0 || atkData.rank > defData.rank)) { newAtkData = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId: attackInfo.roleId }, { $set: { rank: defData.rank, oldRank: atkData.rank } }, { new: true, session }).lean(); newDefData = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId: defenseInfo.roleId }, { $set: { rank: atkData.rank, oldRank: defData.rank } }, { new: true, session }).lean(); isChange = true; endTime = Date.now(); } else { newAtkData = atkData; newDefData = defData; } } await session.commitTransaction() return { isChange, atkData: newAtkData, defData: newDefData, oldAtkData: atkData, endTime } } finally { session.endSession() } } public static async refreshOpp(roleId: string, vestigeId: number, oppRanks: number[]) { let today = getZeroPoint(); let result: GVGVestigeRankType = await GVGVestigeRankModel.findOneAndUpdate({ day: today, vestigeId, roleId }, { $set: { oppRanks }, $inc: { refreshCnt: 1 } }, { new: true, upsert: true }).lean(); return result; } public static async findRank(): Promise<{ _id: { groupKey: string, vestigeId: number }, arr: { roleId: string, rank: number }[], roleIds: string[] }[]> { let today = getZeroPoint(); let ranks = await GVGVestigeRankModel.aggregate([ { $match: { day: today } }, { $group: { _id: { groupKey: "$groupKey", vestigeId: "$vestigeId" }, arr: { $push: { roleId: "$roleId", rank: "$rank" } }, roleIds: { $addToSet: "$roleId" } }}, ]); return ranks; } public static async findRankByVestige(groupKey: string, vestigeId: number) { let today = getZeroPoint(); let result: GVGVestigeRankType[] = await GVGVestigeRankModel.find({ day: today, vestigeId, groupKey, rank: { $gt: 0 } }).sort({ rank: 1 }).select('roleId rank lineup').lean(); return result; } public static async removeBySub(roleId: string, subHid: number) { await GVGVestigeRankModel.updateMany({ roleId, hasDefense: true }, { $pull: { lineup: { actorId: subHid } } }); } } export const GVGVestigeRankModel = getModelForClass(GVGVestigeRank); export interface GVGVestigeRankType extends Pick, keyof GVGVestigeRank> {}; export type GVGVestigeRankUpdate = Partial; // 将所有字段变成可选项