Files
ZYZ/shared/db/PvpDefense.ts

200 lines
9.9 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 { PVP } from '../pubUtils/dicParam';
@index({ roleId: 1 })
@index({ serverId: 1, score: 1 })
@index({ serverId: 1, seasonNum: 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 })
hasDefense: boolean;
@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: 0 })
seasonWinNum: number; // 本赛季胜利次数
@prop({ required: true, default: 1 })
rankSeasonNum: number;
@prop({ required: true, default: 0 })
defenseScoreCnt: number;
@prop({ required: true })
refDefenseScore: Date;
@prop({required: true, default : 0})
buyChallengeCnt:number; // 每日已购买次数
@prop({ required: true, default: 0 })
buyChallengeTime: number; // 上一次购买时间
public static async findByRoleId(roleId: string, getters = false) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean({ getters});
return result;
}
public static async createPvpDefense(seasonNum: number, params: pvpUpdateInter) {
const doc = new PvpDefenseModel();
const update = Object.assign(doc.toJSON(), params, { rankSeasonNum: 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, ce: number, lean = true) {
const rec: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId, 'lineupCe.hid': hid }, { $set: { 'lineupCe.$.ce': ce } }).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', 'serverId head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr title')
.populate('heroes.hero')
.populate('oppPlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes warId buff combo')
.populate('oppBeforePlayers.oppDef', 'oppRoleId pos roleName head frame spine heads frames spines rankLv title lv pLv defCe heroes warId buff combo').lean({ getters: true, virtuals: true });
return result;
}
public static async findByTeamLv(serverIds: number[], seasonNum: number, min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ serverId: {$in: serverIds}, seasonNum, hasDefense: true, 'defense.pLv': { $gte: min, $lte: max } })
.populate('role', '_id serverId head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr title')
.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 findNeighborByScore(seasonNum: number, score: number) {
const beforeData: PvpDefenseType[] = await PvpDefenseModel.find({
seasonNum, hasDefense: true, score: { $lt: score }
}).sort({ score: -1 }).limit(10)
.populate('role', '_id serverId head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr title')
.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 });
const afterData: PvpDefenseType[] = await PvpDefenseModel.find({
seasonNum, hasDefense: true, score: { $gt: score }
}).sort({ score: 1 }).limit(10)
.populate('role', '_id serverId head frame spine heads frames spines topLineupCe roleId roleName lv globalCeAttr title')
.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 [...beforeData, ...afterData];
}
public static async updateInfoAndInclude(roleId: string, update: pvpUpdateInter) {
delete update._id;
let result: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({roleId}, {$set:update}, {new: true})
.populate('role', 'serverId head frame spine heads frames spines topLineupCe roleId roleName lv title')
.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(serverIds: number[], seasonNum: number, page = 1, limit = 1000) {
let sortBy = { score: -1, updatedAt: 1 };
const ranks: PvpDefenseType[] = await PvpDefenseModel.find({ serverId: {$in: serverIds}, rankSeasonNum: seasonNum, score: { $gt: 0 }}).select('serverId roleId role score updatedAt')
.populate('role', 'serverId 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 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;
}
public static async resetDefense() {
await PvpDefenseModel.updateMany({}, { $set: { hasDefense: false, defense: null } });
}
public static async removeBySub(roleId: string, subHid: number) {
await PvpDefenseModel.updateMany({ roleId, hasDefense: true }, { $pull: { 'defense.heroes': { actorId: subHid } } });
await PvpDefenseModel.updateMany({ roleId, 'attack.heroes': { $exists: true } }, { $pull: { 'attack.heroes': { actorId: subHid } } });
}
}
export const PvpDefenseModel = getModelForClass(PvpDefense);
export interface PvpDefenseType extends Pick<DocumentType<PvpDefense>, keyof PvpDefense> { };
export type pvpUpdateInter = Partial<PvpDefenseType>;