Files
ZYZ/shared/db/PvpDefense.ts
2021-01-08 17:11:31 +08:00

249 lines
8.9 KiB
TypeScript

import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import Hero, { } from './Hero';
import Role, { } from './Role';
import PvpDef, { } from './PvpDefense';
import { PVP_PLAYER_POS, PVP_HERO_POS } from '../consts';
interface pvpUpdateInter {
_id?: string;
oppPlayers?: OppPlayers[];
hisScore?: number;
score?: number;
pLv?:number;
heroScores?: HeroScores[];
winStreakNum?: number;
defCe?:number;
heroes?: Array<Heroes>;
seasonNum?: number;
refOppCnt?:number;
refOppTime?: Date;
challengeCnt?:number;
challengeRefTime?:number;
isFirstEntry?:boolean;
receivedBox?: Array<number>;
seasonEndTime?:number;
}
export class Heroes {
@prop({ required: true })
actorId: number; // 武将id
@prop({ ref: Hero, type: mongoose.Schema.Types.ObjectId })
hero: Ref<Hero>;
@prop({ required: true })
ce: number; // 战斗力
@prop({ required: true })
dataId: number;
@prop({ required: true })
order: number;
}
// 初始化
function getInitialOppPlayers() {
let players = new Array<OppPlayers>();
for(let i = PVP_PLAYER_POS.START; i <= PVP_PLAYER_POS.END; i++) {
let p = new OppPlayers();
p.pos = i;
players.push(p);
}
return players;
}
// 初始化
function getInitialOppHeros() {
let heros = new Array<Heroes>();
for(let i = PVP_HERO_POS.START; i <= PVP_HERO_POS.END; i++) {
let p = new Heroes();
p.dataId = i;
p.order = i;
heros.push(p);
}
return heros;
}
export class Robot {
@prop({ required: true })
roleId: string; // 角色 id
@prop({ required: true })
roleName: string; // 角色名称
@prop({ required: true, default: 19 })
headHid: number;
@prop({ required: true, default: 19 })
sHid: number;
@prop({ required: true })
defCe: number;
@prop({ required: true })
pLv: number;
@prop({ required: true })
warId: number; // 模板的warId
constructor(roleId: string, roleName: string, defCe: number, pLv: number, warId: number) {
this.roleId = roleId;
this.roleName = roleName;
this.defCe = defCe;
this.pLv = pLv;
this.warId = warId;
}
}
export class OppPlayers {
@prop({ required: true })
roleId: string;
@prop({ ref: 'PvpDefense', type: mongoose.Schema.Types.ObjectId })
oppDef: Ref<PvpDef>;
@prop({ required: true })
pos: number;
@prop({ required: true })
isRobot: boolean;
@prop({ required: true, type: Robot, default: null, _id: false })
robot: Robot
}
export class HeroScores {
@prop({ required: true })
hid: number;
@prop({ required: true })
score: number;
}
@index({ roleId: 1 })
export default class PvpDefense extends BaseModel {
@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, type: Heroes, default: getInitialOppHeros(), _id: false })
heroes: Array<Heroes>;
@prop({ required: true, default: 0 })
score: number;
@prop({ required: true, default: 1 })
pLv: number;
@prop({ required: true, default: 0 })
hisScore: number; //历史最高积分
@prop({ required: true, default: 0 })
winStreakNum: number; //连胜次数
@prop({ required: true, default: 0 })
defCe: number; //防守ce
@prop({ required: true, type: OppPlayers, default: getInitialOppPlayers(), _id: false })
oppPlayers: Array<OppPlayers>;
@prop({ required: true, type: HeroScores, default: [], _id: false })
heroScores: Array<HeroScores>;
@prop({ required: true, default: true })
isDefaultHero: boolean;
@prop({ required: true, default: 0 })
refOppCnt: number; // 刷新对手总次数,消耗可根据消耗表算出
@prop({ required: true, default: 0 })
refOppTime: Date; // 刷新对手时间
@prop({ required: true, default: 0 })
challengeCnt: number; // 可挑战次数
@prop({ required: true, default: 0 })
challengeRefTime: number; // 上一次刷新的时间
@prop({ required: true, default: [] })
receivedBox: Array<number>;
@prop({ required: true, default: 0 })
seasonNum: number;
@prop({ required: true, default: 0 })
seasonEndTime: number;
@prop({ required: true, default: true })
isFirstEntry: boolean;
public static async findByRoleId(roleId: string, lean = true) {
const result: PvpDefenseType = await PvpDefenseModel.findOne({ roleId }).lean(lean);
return result;
}
public static async findByScale(roleId: string, min: number, max: number, lean = true) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ roleId: { $ne: roleId }, defCe: { $lte: max, $gte: min } }).sort({ updatedAt: -1 }).limit(100).lean(lean);
return result;
}
public static async createPvpDefense(params: { roleId: string, roleName: string, role: string, heroes: Array<Heroes>, oppPlayers: Array<OppPlayers>, defCe: number, seasonNum: number, seasonEndTime:number, challengeCnt: number }, lean = true) {
const doc = new PvpDefenseModel();
const update = Object.assign(doc.toJSON(), params);
const defense: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId: params.roleId }, update, { upsert: true, new: true }).lean(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, defCe: number, lean = true) {
const rec: PvpDefenseType = await PvpDefenseModel.findOneAndUpdate({ roleId, 'heroes.actorId': hid }, { $set: { defCe } }).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', 'headHid sHid topFiveCe roleId roleName')
.populate('heroes.hero')
.populate({
path: 'oppPlayers.oppDef',
populate: {
path: 'role heroes.hero',
select: 'headHid sHid topFiveCe roleId roleName hid ceAttr globalCeAttr'
}
}).lean();
return result;
}
public static async findByTeamLv(min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ pLv: { $gte: min, $lte: max } }).lean();
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({
path: 'oppPlayers.oppDef',
populate: {
path: 'role',
select: 'headHid sHid topFiveCe roleId roleName'
}
}).lean();
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(limitNum: number, lean = true) {
let result: Array<PvpDefenseType> = await PvpDefenseModel.find().sort({ score: -1 }).limit(limitNum).lean(lean);
return result;
}
public static async getRank(page = 1, limit = 1000, lean = true) {
let sortBy = { score: -1, updatedAt: 1 };
const ranks: PvpDefenseType[] = await PvpDefenseModel.find().limit(limit).skip(page - 1).select('roleId role score updatedAt')
.populate('role', 'roleId roleName headHid sHid title lv vLv')
.sort(sortBy).limit(limit).skip((page - 1) * limit).lean(lean);
return ranks;
}
}
export const PvpDefenseModel = getModelForClass(PvpDefense);
export interface PvpDefenseType extends Pick<DocumentType<PvpDefense>, keyof PvpDefense> { };