巅峰演武:赛季优化修改

This commit is contained in:
luying
2022-10-17 14:42:40 +08:00
parent ddff18eb20
commit 08ca06d7ac
30 changed files with 590 additions and 272 deletions

115
shared/db/PvpConfig.ts Normal file
View File

@@ -0,0 +1,115 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
@index({ isCurrent: 1 })
@index({ seasonNum: 1 })
export default class PVPConfig extends BaseModel {
@prop({ required: true, default: 1 })
seasonNum: number; // 赛季
@prop({ required: true })
seasonStartTime: number; // 赛季开始时间
@prop({ required: true })
seasonRewardTime: number; // 结算奖励时间
@prop({ required: true })
seasonEndTime: number; // 赛季结束的时间
@prop({ required: true })
hasSettleReward: boolean; // 是否发放奖励
@prop({ required: true, type: Number })
warIds: number[]; // 关卡id
@prop({ required: true })
isCurrent: boolean; // 是否是当前赛季
public static async findCurPVPConfig() {
let result: PVPConfigType = await PVPConfigModel.findOne({ isCurrent: true }).lean();
if(!result) {
result = await PVPConfigModel.findOneAndUpdate({ seasonStartTime: { $lte: nowSeconds() } }, { $set: { isCurrent: true }}, { new: true }).sort({ seasonStartTime: -1 }).lean();
}
return result;
}
public static async findPVPConfig(seasonNum: number) {
const result: PVPConfigType = await PVPConfigModel.findOne({ seasonNum }).lean(true);
return result;
}
public static async createPVPConfig(seasonNum: number|'new', params: PVPConfigUpdate, uid: number) {
if(seasonNum == 'new') {
seasonNum = await CounterModel.getNewCounter(COUNTER.PVP_SEASON_NUM);
}
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { $set: { ...params, updatedBy: uid }, $setOnInsert: { hasSettleReward: false, isCurrent: false, createdBy: uid } }, { upsert: true, new: true }).lean(true);
return result;
}
public static async getSettledConfig() {
const result: PVPConfigType = await PVPConfigModel.findOne({ hasSettleReward: true }).sort({ seasonNum: -1}).lean();
return result;
}
public static async checkTime(seasonNum: number|'new', seasonStartTime: number, seasonRewardTime: number) {
if(seasonNum == 'new') {
return await PVPConfigModel.exists({ seasonRewardTime: { $gt: seasonStartTime } })
} else {
return await PVPConfigModel.exists({
seasonNum: { $ne: seasonNum },
$or: [
{ seasonNum: { $lt: seasonNum }, seasonRewardTime: { $gt: seasonStartTime } },
{ seasonNum: { $gt: seasonNum }, seasonStartTime: { $lt: seasonRewardTime } }
]
})
}
}
public static async setReward(seasonNum: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { hasSettleReward: true }, { new: true }).lean(true);
return result;
}
public static async setCurrentPvp() {
await PVPConfigModel.updateMany({ isCurrent: true }, { $set: { isCurrent: false } });
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonStartTime: { $lte: nowSeconds() } }, { $set: { isCurrent: true }}, {new: true}).sort({ seasonStartTime: -1 }).lean(true);
return result;
}
public static async setNextPvp(seasonNum: number) {
await PVPConfigModel.updateMany({ isCurrent: true }, { $set: { isCurrent: false } });
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { $set: { isCurrent: true }}, {new: true}).sort({ seasonStartTime: -1 }).lean(true);
return result;
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'seasonNum', sortOrder: string = 'descend') {
let sort = {};
if (sortField && sortOrder) {
if (sortOrder == 'ascend') {
sort[sortField] = 1;
} else if (sortOrder == 'descend') {
sort[sortField] = -1;
}
}
const result: PVPConfigType[] = await PVPConfigModel.find().limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition() {
const result = await PVPConfigModel.count({});
return result;
}
}
export const PVPConfigModel = getModelForClass(PVPConfig);
export interface PVPConfigType extends Pick<DocumentType<PVPConfig>, keyof PVPConfig> {
id: number;
};
export type PVPConfigUpdate = Partial<PVPConfigType>; // 将所有字段变成可选项

View File

@@ -7,6 +7,7 @@ import { COUNTER } from '../consts';
import { PVP } from '../pubUtils/dicParam';
@index({ roleId: 1 })
@index({ score: 1 })
export default class PvpDefense extends BaseModel {
@prop({ required: true })
serverId: number; // 区 id
@@ -17,6 +18,8 @@ export default class PvpDefense extends BaseModel {
@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;
@@ -58,8 +61,6 @@ export default class PvpDefense extends BaseModel {
seasonNum: number;
@prop({ required: true, default: 0 })
seasonWinNum: number; // 本赛季胜利次数
@prop({ required: true, default: true })
isFirstEntry: boolean;
@prop({ required: true, default: 0 })
defenseScoreCnt: number;
@@ -129,7 +130,7 @@ export default class PvpDefense extends BaseModel {
}
public static async findByTeamLv(seasonNum: number, min: number, max: number) {
const result: PvpDefenseType[] = await PvpDefenseModel.find({ seasonNum, 'defense.pLv': { $gte: min, $lte: max } })
const result: PvpDefenseType[] = await PvpDefenseModel.find({ seasonNum, hasDefense: true, 'defense.pLv': { $gte: min, $lte: max } })
.populate('role', '_id 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')
@@ -137,6 +138,25 @@ export default class PvpDefense extends BaseModel {
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 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 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})
@@ -162,14 +182,6 @@ export default class PvpDefense extends BaseModel {
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;

36
shared/db/PvpSaveData.ts Normal file
View File

@@ -0,0 +1,36 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { DefenseHeroInSaveData, } from '../domain/battleField/pvp';
@index({ roleId: 1 })
@index({ roleId: 1, warId: 1 })
export default class PvpSaveData extends BaseModel {
@prop({ required: true })
roleId: string; // 角色 id
@prop({ required: true })
warId: number; // 关卡id
@prop({ required: true })
buff: number; // 地图buff
@prop({ required: true, default: [], _id: false, type: DefenseHeroInSaveData })
heroes: DefenseHeroInSaveData[];
public static async createSaveData(roleId: string, warId: number, buff: number, heroes: DefenseHeroInSaveData[]) {
const result: PvpSaveDataType = await PvpSaveDataModel.findOneAndUpdate({ roleId, warId }, { $set: { buff, heroes } }, { new: true, upsert: true }).lean();
return result;
}
public static async findByRoleId(roleId: string) {
const result: PvpSaveDataType[] = await PvpSaveDataModel.find({ roleId }).lean();
return result;
}
}
export const PvpSaveDataModel = getModelForClass(PvpSaveData);
export interface PvpSaveDataType extends Pick<DocumentType<PvpSaveData>, keyof PvpSaveData> { };
export type pvpSaveDataUpdate = Partial<PvpSaveDataType>;

View File

@@ -59,6 +59,10 @@ export default class PvpSeasonResult extends BaseModel {
let result: PvpSeasonResultType = await PvpSeasonResultModel.findOne({ roleId, show: true }).lean();
return result;
}
public static async checkResultBySeasonNum(roleId: string, seasonNum: number) {
return await PvpSeasonResultModel.exists({ roleId, seasonNum });
}
}
export const PvpSeasonResultModel = getModelForClass(PvpSeasonResult);

View File

@@ -1,59 +0,0 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
@index({ id: 1 })
@index({ seasonNum: 1 })
export default class PVPConfig extends BaseModel {
@prop({ required: true, default: 1 })
seasonNum: number; // 赛季
@prop({ required: true })
seasonStartTime: number; // 赛季开始时间
@prop({ required: true })
seasonRewardTime: number; // 结算奖励时间
@prop({ required: true })
seasonEndTime: number; // 赛季结束的时间
@prop({ required: true })
hasSettleReward: boolean; // 赛季结束的时间
public static async findCurPVPConfig() {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const result: PVPConfigType = await PVPConfigModel.findOne({ seasonNum }).lean(true);
return result;
}
public static async findPVPConfig(seasonNum: number) {
const result: PVPConfigType = await PVPConfigModel.findOne({ seasonNum }).lean(true);
return result;
}
public static async createPVPConfig(seasonNum: number, seasonStartTime: number, seasonRewardTime: number, seasonEndTime: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { seasonStartTime, seasonRewardTime, seasonEndTime, hasSettleReward: false }, { upsert: true, new: true }).lean(true);
return result;
}
public static async setReward(seasonNum: number) {
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, { hasSettleReward: true }, { new: true }).lean(true);
return result;
}
public static async setCurPvpConfig(update: PVPConfigUpdate) {
let seasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM);
const result: PVPConfigType = await PVPConfigModel.findOneAndUpdate({ seasonNum }, update).lean(true);
return result;
}
}
export const PVPConfigModel = getModelForClass(PVPConfig);
export interface PVPConfigType extends Pick<DocumentType<PVPConfig>, keyof PVPConfig> {
id: number;
};
export type PVPConfigUpdate = Partial<PVPConfigType>; // 将所有字段变成可选项

View File

@@ -44,7 +44,10 @@ export default class UserShop extends BaseModel {
@prop({ required: true })
count: number; // 数量
private static getRefreshCondition() {
@prop({ required: true })
seasonNum: number; // 赛季id
private static getRefreshCondition(seasonNum: number) {
let today = getZeroPointD();
let cutWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
let curMonth = getZeroPointD(SHOP_REFRESH_TYPE.MONTHLY);
@@ -54,38 +57,39 @@ export default class UserShop extends BaseModel {
{ createdAt: { $gte: cutWeek }, refreshType: SHOP_REFRESH_TYPE.WEEKLY },
{ createdAt: { $gte: curMonth }, refreshType: SHOP_REFRESH_TYPE.MONTHLY },
{ refreshType: SHOP_REFRESH_TYPE.FOREVER },
{ refreshType: SHOP_REFRESH_TYPE.PVP, seasonNum },
]
}
public static async findByShopType(roleId: string, shop: number, type: number) {
let timeCondition = this.getRefreshCondition();
public static async findByShopType(roleId: string, shop: number, type: number, seasonNum: number) {
let timeCondition = this.getRefreshCondition(seasonNum);
let rec: UserShopType[] = await UserShopModel.find({ shop, type, roleId, $or: timeCondition }).lean();
return rec;
}
public static async findByRoleId(roleId: string) {
let timeCondition = this.getRefreshCondition();
public static async findByRoleId(roleId: string, seasonNum: number) {
let timeCondition = this.getRefreshCondition(seasonNum);
let rec: UserShopType[] = await UserShopModel.find({ roleId, $or: timeCondition }).lean();
return rec;
}
public static async findByRoleAndItem(roleId: string, activityId: number, dicShopItem: { id: number, shop: number, type: number, createTime?: number }) {
let timeCondition = this.getRefreshCondition();
public static async findByRoleAndItem(roleId: string, activityId: number, dicShopItem: { id: number, shop: number, type: number, createTime?: number }, seasonNum: number) {
let timeCondition = this.getRefreshCondition(seasonNum);
let { id, shop, type, createTime = 0 } = dicShopItem;
let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId: id, shop, type, activityId, createTime, $or: timeCondition }).lean();
return rec;
}
public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }, inc: number) {
public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }, inc: number, seasonNum: number) {
let code = genCode(8);
let timeCondition = this.getRefreshCondition();
let timeCondition = this.getRefreshCondition(seasonNum);
let { id, goodId, refreshType, shop, type, createTime = 0 } = dicShopItem;
let rec: UserShopType = await UserShopModel.findOneAndUpdate(
{ roleId, itemId: id, $or: timeCondition, activityId, shop, type, createTime },
{ $setOnInsert: { roleName, code, goodId, refreshType }, $inc: { count: inc } },
{ $setOnInsert: { roleName, code, goodId, refreshType, seasonNum }, $inc: { count: inc } },
{ new: true, upsert: true }
).lean();
return rec;