Files
ZYZ/shared/db/PvpDefense.ts
2022-03-21 19:50:46 +08:00

175 lines
8.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import Role, { } from './Role';
import { Defense, Attack, LineupCe, OppPlayer, HeroScore, } from '../domain/battleField/pvp';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { PVP } from '../pubUtils/dicParam';
@index({ roleId: 1 })
export default class PvpDefense extends BaseModel {
@prop({ required: true })
serverId: number; // 区 id
@prop({ required: true })
roleId: string; // 角色 id
@prop({ required: true })
roleName: string; // 角色名称
@prop({ ref: 'Role', type: mongoose.Schema.Types.ObjectId })
role: Ref<Role>;
@prop({ required: true, default: null, _id: false })
defense: Defense;
@prop({ required: true, default: null, _id: false })
attack: Attack;
@prop({ required: true, type: () => LineupCe, default: [], _id: false })
lineupCe: LineupCe[];
@prop({ required: true, type: () => OppPlayer, default: [], _id: false })
oppPlayers: OppPlayer[];
@prop({ required: true, type: () => OppPlayer, default: [], _id: false })
oppBeforePlayers: OppPlayer[];
@prop({ required: true, type: () => HeroScore, default: [], _id: false })
heroScores: HeroScore[];
@prop({ required: true, default: 0 })
score: number;
@prop({ required: true, default: 0 })
hisScore: number; //历史最高积分
@prop({ required: true, default: 0 })
winStreakNum: number; //连胜次数
@prop({ required: true, default: 0 })
hisWinStreakNum: number; //历史最高连胜次数
@prop({ required: true, default: () => { return new Date() } })
refDaily: Date; // 每日刷新控制refOppCnt和setAttackCnt
@prop({ required: true, default: 0 })
refOppCnt: number; // 刷新对手总次数,消耗可根据消耗表算出
@prop({ required: true, default: 0 })
setAttackCnt: number; // 设置挑战阵容次数
@prop({ required: true, default: 0 })
buyAttackCnt: number; // 购买挑战阵容次数
@prop({ required: true, default: 0 })
challengeCnt: number; // 可挑战次数每2小时回复一次
@prop({ required: true, default: 0 })
challengeRefTime: number; // 上一次刷新的时间
@prop({ required: true, type: Number, default: [] })
receivedBox: Array<number>;
@prop({ required: true, default: 0 })
seasonNum: number;
@prop({ required: true, default: true })
isFirstEntry: boolean;
public static async findByRoleId(roleId: string, getters = false) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean({ getters});
return result;
}
public static async findByScale(roleId: string, min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ roleId: { $ne: roleId }, defCe: { $lte: max, $gte: min } })
.populate('role', 'head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr')
.populate('heroes.hero')
.sort({ updatedAt: -1 }).limit(100).lean({ getters: true, virtuals: true });
return result;
}
public static async createPvpDefense(params: pvpUpdateInter) {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const doc = new PvpDefenseModel();
const update = Object.assign(doc.toJSON(), params, { seasonNum, challengeCnt: PVP.PVP_CHALLENGE_COUNTS });
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: params.roleId }, update, { upsert: true, new: true })
.populate('role')
.lean();
return defense;
}
public static async addHeroToDefense(roleId: string, heroInfo: any, defCe: number, lean = true) {
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: roleId }, {
$inc: { defCe },
$push: { heroes: heroInfo }
}, { upsert: true, new: true }).lean(lean);
return defense;
}
public static async removeHeroFromDefense(roleId: string, hid: number, defCe: number, lean = true) {
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: roleId }, {
$inc: { defCe: -1 * defCe },
$pull: { heroes: { actorId: hid } }
}, { upsert: true, new: true }).lean(lean);
return defense;
}
public static async updateCe(roleId: string, hid: number, incCe: number, lean = true) {
const rec: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId, 'lineupCe.hid': hid }, { $inc: { 'lineupCe.$.ce': incCe } }).lean(lean);
return rec
}
public static async deleteAccount(roleId: string) {
let result = await PvpDefenseModel.deleteMany({ roleId });
return result;
}
public static async findByRoleIdIncludeAll(roleId: string) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId })
.populate('role', 'head frame spine topLineupCe roleId roleName lv globalCeAttr')
.populate('heroes.hero')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes warId buff')
.populate('oppBeforePlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes warId buff').lean({ getters: true, virtuals: true });
return result;
}
public static async findByTeamLv(seasonNum: number, min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ seasonNum, 'defense.pLv': { $gte: min, $lte: max } })
.populate('role', '_id head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr')
.populate('heroes.hero')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes warId buff')
.lean({ getters: true, virtuals: true });
return result;
}
public static async updateInfoAndInclude(roleId: string, update: pvpUpdateInter) {
delete update._id;
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true})
.populate('role', 'head frame spine heads frames spines topLineupCe roleId roleName lv')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes warId buff').lean({ getters: true, virtuals: true });
return result;
}
public static async updateInfo(roleId: string, update: pvpUpdateInter, lean = true) {
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true}).lean(lean);
return result;
}
public static async getPvpDef(limit: number, page: number, lean = true) {
let result: Array<PvpDefenseType> = await PvpDefenseModel.find().sort({ score: -1 }).limit(limit).skip((page) * limit).lean(lean);
return result;
}
public static async getRank(seasonNum: number, page = 1, limit = 1000) {
let sortBy = { score: -1, updatedAt: 1 };
const ranks: PvpDefenseType[] = await PvpDefenseModel.find({seasonNum, score: { $gt: 0 }}).select('roleId role score updatedAt')
.populate('role', 'roleId roleName head frame spine heads frames spines title lv vLv updatedAt')
.sort(sortBy).limit(limit).skip((page - 1) * limit).lean({ getters: true, virtuals: true });
return ranks;
}
public static async resetScores(roleId: string, newSeasonNum: number, newScore: number, newHeroScores: HeroScore[]) {
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set: { seasonNum: newSeasonNum, score: newScore, heroScores: newHeroScores, challengeCnt: PVP.PVP_CHALLENGE_COUNTS, challengeRefTime: 0, winStreakNum: 0 }}, {new: true})
.populate('role', 'roleId roleName head frame spine heads frames spines title lv vLv')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv pLv title lv defCe heroes warId buff').lean({ getters: true, virtuals: true })
.lean();
return result;
}
public static async deleteHero(roleId: string, hid: number) {
let result:PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$pull:{lineupCe: {hid}, heroScores: {hid}}, $set: {defense: null, attack: null}}, {new: true}).lean();
return result;
}
}
export const PvpDefenseModel = getModelForClass(PvpDefense);
export interface PvpDefenseType extends Pick<DocumentType<PvpDefense>, keyof PvpDefense> { };
export type pvpUpdateInter = Partial<PvpDefenseType>;