feat(稷下学宫): ff931afe4到7421822f6

This commit is contained in:
luying
2023-08-30 11:02:52 +08:00
parent 59a334d673
commit 05cbe318e9
102 changed files with 147876 additions and 715 deletions
+36 -4
View File
@@ -1,6 +1,7 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { LineupParam } from '../domain/rank';
import { Card } from './RougelikeChara';
/**
* 战斗记录接口
@@ -17,6 +18,31 @@ class DamageRecord {
underDamage: number;
}
class RougeCharaRecord {
@prop({ required: false, default: '' })
charaCode?: string; // 角色卡id
@prop({ required: false, default: 0 })
charaId?: number; // 角色卡id
@prop({ required: false, type: Card, default: [] })
cards?: Card[];
@prop({ required: false, default: 0 })
hp?: number; // 当前hp
@prop({ required: false, default: 0 })
ap?: number; // 当前怒气
@prop({ required: false, default: 0 })
roundSkill?: number; // 玩家选择的回合技能卡
@prop({ required: false, default: 0 })
apSkill?: number; // 玩家选择的怒气技能卡
@prop({ required: false, default: 0 })
shield?: number
@prop({ required: false })
damage?: number;
@prop({ required: false })
heal?: number;
@prop({ required: false })
underDamage?: number;
}
class Record {
@prop({ required: true, type: Number })
heroes?: Array<number>; // 武将id
@@ -29,11 +55,11 @@ class Record {
@prop({ required: false })
pos?: number; // pvp位置
@prop({ required: false })
trainId?:number;
trainId?: number;
@prop({ required: false })
trainLv?:number;
trainLv?: number;
@prop({ required: false })
hid?:number;
hid?: number;
@prop({ required: false })
guildCode?: string;
@prop({ required: false })
@@ -53,6 +79,11 @@ class Record {
damageRecord?: DamageRecord[];
@prop({ required: false })
round?: number;
@prop({ required: false, type: RougeCharaRecord })
rougeOriginal?: RougeCharaRecord[];
@prop({ required: false, type: RougeCharaRecord })
rougeDamage?: RougeCharaRecord[];
}
@index({ roleId: 1, battleId: 1 })
@@ -107,13 +138,14 @@ export default class BattleRecord extends BaseModel {
return result;
}
public static async deleteAccount(roleId: string) {
let result = await BattleRecordModel.deleteMany({ roleId });
return result || {};
}
public static async incBossDamage(battleCode: string, damage: number, bossHp: number) {
if(bossHp < 0) { // 最后一击,被扣到负了
if (bossHp < 0) { // 最后一击,被扣到负了
damage += bossHp;
}
let result: BattleRecordType = await BattleRecordModel.findOneAndUpdate({ battleCode }, { $inc: { 'record.bossDamage': damage } }, { new: true }).lean();
+9
View File
@@ -22,6 +22,15 @@ export default class Counter extends BaseModel {
return counter?.seq;
}
public static async getNewCounterNum(param:{name: string, def: number}, inc = 1) {
let {name, def:defaultVal} = param;
let counter: CounterType = await CounterModel.findOneAndUpdate({ name }, { $inc: { seq: inc } }, { new: true, upsert: true }).lean();
if(!counter || (counter&&counter.seq == 1) && defaultVal != 1) {
counter = await CounterModel.findOneAndUpdate({ name }, { $set: { seq: defaultVal } }, { new: true, upsert: true }).lean();
}
return counter?.seq;
}
public static async getCounter(param:{name: string, def: number}, lean = true) {
let {name} = param;
let counter: CounterType = await CounterModel.findOne({ name }).lean(lean);
+89
View File
@@ -0,0 +1,89 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
/**
* 每场获得的圣物&特性卡
*/
@index({ roleId: 1 })
@index({ gameCode: 1 })
@index({ gameCode: 1, cardCode: 1 })
@index({ gameCode: 1, type: 1 })
export default class RougelikeCard extends BaseModel {
@prop({ required: true })
roleId: string; // 角色id
@prop({ required: true, default: '' })
gameCode: string; // 场次唯一code
@prop({ required: true, default: '' })
cardCode: string; // 卡唯一code
@prop({ required: true, default: 0 })
cardId: number; // 卡id
@prop({ required: true, default: 0 })
type: number; // 卡类型
@prop({ required: true, default: 0 })
charaId: number; // 装备在哪个角色上,没有装备为0
@prop({ required: true, default: 0 })
lv: number; // 特性卡的等级
@prop({ required: true, default: 0 })
getLayer: number; // 在哪一层获得的
@prop({ required: true, default: 0 })
getWay: number; // 在做什么的时候获得的
@prop({ required: true, default: 0 })
useCount?: number // 可使用次数
public static async updateByCode(gameCode: string, cardCode: string, params: { $set?: RougelikeCardPara, $inc?: { lv?: number } }, lean = true) {
const result: RougelikeCardType = await RougelikeCardModel.findOneAndUpdate({ gameCode, cardCode }, params, { new: true, upsert: true }).lean(lean);
return result;
}
public static async findByGameCode(gameCode: string, lean = true) {
const result: RougelikeCardType[] = await RougelikeCardModel.find({ gameCode }).lean(lean);
return result;
}
public static async findByCode(gameCode: string, cardCode: string, lean = true) {
const result: RougelikeCardType = await RougelikeCardModel.findOne({ gameCode, cardCode }).lean(lean);
return result;
}
public static async findByGameCodeAndType(gameCode: string, type: number, lean = true) {
const result: RougelikeCardType[] = await RougelikeCardModel.find({ gameCode, type: { $eq: type }, }).lean(lean);
return result;
}
public static async findByGameCodeAndCardCodes(gameCode: string, cardCodes: string[], lean = true) {
const result: RougelikeCardType[] = await RougelikeCardModel.find({ gameCode, cardCode: { $in: cardCodes } }).lean(lean);
return result;
}
// public static async bulkWriteUpdate(updateArr: { gameCode: string, cardCode: string, charaId: number }[]) {
// if (updateArr.length == 0) return;
// await RougelikeCardModel.bulkWrite(updateArr.map(({ gameCode, cardCode, charaId }) => {
// return { updateOne: { filter: { gameCode, cardCode }, update: { $set: { charaId } }, upsert: true } }
// }))
// }
public static async bulkWriteUpdate(updateArr: RougelikeCardPara[]) {
if (updateArr.length == 0) return;
await RougelikeCardModel.bulkWrite(updateArr.map((param) => {
const { gameCode, cardCode } = param
return { updateOne: { filter: { gameCode, cardCode }, update: { $set: { ...param } }, upsert: true } }
}))
}
};
export const RougelikeCardModel = getModelForClass(RougelikeCard);
export interface RougelikeCardType extends Pick<DocumentType<RougelikeCard>, keyof RougelikeCard> { };
export type RougelikeCardPara = Partial<RougelikeCardType>; // 将所有字段变成可选项
+126
View File
@@ -0,0 +1,126 @@
import { COUNTER, ROUGELIKE_SKILLTYPE } from '../consts';
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
export class Card {
@prop({ required: false })
index: number; // 卡槽,没有那个index表示没有解锁
@prop({ required: false })
cardCode: string; //卡唯一code,为空串表示没安装
@prop({ required: false })
cardId: number; // 当为0的时候表示没有装入卡片
}
/**
* 每场获得角色(普通角色和高级角色)
*/
@index({ roleId: 1 })
@index({ gameCode: 1 })
@index({ gameCode: 1, charaCode: 1 })
export default class RougelikeChara extends BaseModel {
@prop({ required: true })
roleId: string; // 角色id
@prop({ required: true, default: '' })
gameCode: string; // 场次唯一code
@prop({ required: true, default: 0 })
seqId: number; // 角色卡排序
@prop({ required: true, default: '' })
charaCode: string; // 角色卡唯一id
@prop({ required: true, default: 0 })
charaId: number; // 角色卡id
@prop({ required: true, type: Card, default: [] })
cards: Card[];
@prop({ required: true, default: 0 })
hp: number; // 当前hp
@prop({ required: true, default: 0 })
maxHp: number; // 最大hp
@prop({ required: true, default: 0 })
ap: number; // 当前怒气
@prop({ required: true, default: 0 })
shield: number; // 盾
@prop({ required: true, default: 0 })
roundSkill: number; // 玩家选择的回合技能卡
@prop({ required: true, default: 0 })
apSkill: number; // 玩家选择的怒气技能卡
@prop({ required: true, default: 0 })
getLayer: number; // 在哪一层获得的
@prop({ required: true, default: 0 })
getWay: number; // 在做什么的时候获得的
public static async createCharas(updateArr: RougelikeCharaPara[]) {
if (updateArr.length == 0) return [];
let num = await CounterModel.getNewCounterNum(COUNTER.ROUGE_CHARA, updateArr.length);
let resultArr: RougelikeCharaType[] = [];
for(let index = 0; index < updateArr.length; index++) {
let param = updateArr[index];
let seqId = num - updateArr.length + index + 1;
const { gameCode, charaCode } = param;
let data = await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode }, { $set: { ...param, seqId }}, { new: true, upsert: true }).lean();
if(data) resultArr.push(data)
}
return resultArr
}
public static async updateByCode(gameCode: string, charaCode: string, params: { $set: RougelikeCharaPara }, lean = true) {
const result: RougelikeCharaType = await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode }, params, { new: true }).lean(lean);
return result;
}
public static async findByGameCode(gameCode: string, lean = true) {
const result: RougelikeCharaType[] = await RougelikeCharaModel.find({ gameCode }).lean(lean);
return result;
}
public static async findByCode(gameCode: string, charaCode: string, lean = true) {
const result: RougelikeCharaType = await RougelikeCharaModel.findOne({ gameCode, charaCode }).lean(lean);
return result;
}
public static async findByCodes(gameCode: string, charaCodes: string[], lean = true) {
const result: RougelikeCharaType[] = await RougelikeCharaModel.find({ gameCode, charaCode: { $in: charaCodes } }).lean(lean);
return result;
}
public static async putOnOrOffSkillCard(gameCode: string, charaCode: string, skillType: ROUGELIKE_SKILLTYPE, id: number) {
if (skillType == ROUGELIKE_SKILLTYPE.AP) {
const result: RougelikeCharaType = await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode }, { $set: { apSkill: id } }, { new: true }).lean();
return result;
} else {
const result: RougelikeCharaType = await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode }, { $set: { roundSkill: id } }, { new: true }).lean();
return result;
}
}
public static async bulkWriteUpdate(updateArr: RougelikeCharaPara[]) {
if (updateArr.length == 0) return;
await RougelikeCharaModel.bulkWrite(updateArr.map((param) => {
delete param._id;
const { gameCode, charaCode } = param
return { updateOne: { filter: { gameCode, charaCode }, update: { $set: { ...param } } } }
}))
}
};
export const RougelikeCharaModel = getModelForClass(RougelikeChara);
export interface RougelikeCharaType extends Pick<DocumentType<RougelikeChara>, keyof RougelikeChara> { };
export type RougelikeCharaPara = Partial<RougelikeCharaType>; // 将所有字段变成可选项
+54
View File
@@ -0,0 +1,54 @@
import { COLLECTION_TYPE } from '../consts';
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
@index({ roleId: 1, type: 1, id: 1 })
export default class RougelikeCollection extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, default: 0 })
type: number;
@prop({ required: true, default: 0 })
id: number;
@prop({ required: true, default: 0 })
num: number;
@prop({ required: true, default: '' })
gameCode: string;
@prop({ required: true, type: Number, default: false })
received: number[]; // 是否领取奖励
public static async addRec(roleId: string, type: number, id: number, gameCode: string, addNum = 1) {
const result: RougelikeCollectionType = await RougelikeCollectionModel.findOneAndUpdate({ roleId, type, id }, { $setOnInsert: { received: [] }, $inc: { num: addNum }, $set: { gameCode } }, { new: true, upsert: true }).lean();
return result;
}
public static async findByRoleId(roleId: string, lean = true) {
const result: RougelikeCollectionType[] = await RougelikeCollectionModel.find({ roleId }).lean(lean);
return result;
}
public static async findByRoleAndId(roleId: string, type: number, id: number) {
const result: RougelikeCollectionType = await RougelikeCollectionModel.findOne({ roleId, type, id: type == COLLECTION_TYPE.PASSIVE_CARD_SUM? 0: id }).lean();
return result;
}
public static async receive(roleId: string, type: number, id: number, num = 1) {
if(type == COLLECTION_TYPE.PASSIVE_CARD_SUM) {
const result: RougelikeCollectionType = await RougelikeCollectionModel.findOneAndUpdate({ roleId, type, id: 0, num: { $gte: num } }, { $push: { received: id } }, { new: true }).lean();
return result;
} else {
const result: RougelikeCollectionType = await RougelikeCollectionModel.findOneAndUpdate({ roleId, type, id }, { $push: { received: id } }, { new: true }).lean();
return result;
}
}
}
export const RougelikeCollectionModel = getModelForClass(RougelikeCollection);
export interface RougelikeCollectionType extends Pick<DocumentType<RougelikeCollection>, keyof RougelikeCollection> { };
export type RougelikeCollectionPara = Partial<RougelikeCollectionType>; // 将所有字段变成可选项
+50
View File
@@ -0,0 +1,50 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
@index({ roleId: 1, limitId: 1 })
export class RewardInter {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
@prop({ required: true })
expireTime?: number;
}
export default class RougelikeExtend extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, default: 0 })
limitId: number; // 前置试炼id,只会是已通关
@prop({ required: true, type: RewardInter, default: 0 })
firstReward: RewardInter[]; //首通奖励
@prop({ required: true, default: '' })
gameCode: string;
public static async update(roleId: string, limitId: number, firstReward: RewardInter[], gameCode: string, lean = true) {
const result: RougelikeExtendType = await RougelikeExtendModel.findOneAndUpdate({ roleId, limitId }, { firstReward, gameCode }, { new: true, upsert: true }).lean(lean);
return result;
}
public static async findByRoleId(roleId: string, lean = true) {
const result: RougelikeExtendType[] = await RougelikeExtendModel.find({ roleId }).lean(lean);
return result;
}
public static async findByRoleIdAndLimitId(roleId: string, limitId: number, lean = true) {
const result: RougelikeExtendType = await RougelikeExtendModel.findOne({ roleId, limitId }).lean(lean);
return result;
}
}
export const RougelikeExtendModel = getModelForClass(RougelikeExtend);
export interface RougelikeExtendType extends Pick<DocumentType<RougelikeExtend>, keyof RougelikeExtend> { };
export type RougelikeExtendPara = Partial<RougelikeExtendType>; // 将所有字段变成可选项
+91
View File
@@ -0,0 +1,91 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
export class Node {
@prop({ required: true, default: '' })
detailCode: string;
@prop({ required: true, default: 0 })
index: number; // 索引
@prop({ required: true, default: 0 })
nodeId: number; // 关卡id
@prop({ required: true, type: Number, default: [] })
preNodeIndexs: number[]; // 连线的关卡,填上一层节点的索引
@prop({ required: true, default: 0 })
type: number; // 类型
@prop({ required: true, default: 0 })
isChoose: number; // 玩家选择 0-未选择,1-选择
}
/**
* 每场的每层数据
*/
@index({ roleId: 1 })
@index({ gameCode: 1 })
@index({ gameCode: 1, layer: 1 })
@index({ gameCode: 1, hasPass: 1 })
export default class RougelikeLayer extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, default: '' })
gameCode: string; // 每场唯一code
@prop({ required: true, default: 0 })
layer: number; // 第几层
@prop({ required: true, type: Node, default: [], _id: false })
layerNodes: Node[]; // 地图随机到的各种关卡,用于画图
@prop({ required: true, default: false })
hasPass: boolean;
public static async updateByGameCode(gameCode: string, layer: number, params: { $set: RougelikeLayerPara }, lean = true) {
const result: RougelikeLayerType[] = await RougelikeLayerModel.findOneAndUpdate({ gameCode, layer }, params, { new: true, upsert: true }).lean(lean);
return result;
}
public static async updateByGameCodeAndLayer(gameCode: string, layer: number, detailCode: string, isChoose: number, params?: { $set?: RougelikeLayerPara }, lean = true) {
const result: RougelikeLayerType[] = await RougelikeLayerModel.findOneAndUpdate({ gameCode, layer, 'layerNodes.detailCode': detailCode }, { ...params, 'layerNodes.$.isChoose': isChoose }, { new: true, upsert: true }).lean(lean);
return result;
}
public static async bulkWriteUpdate(updateArr: { gameCode: string, roleId: string, layer: number, layerNodes: Node[] }[]) {
if (updateArr.length == 0) return;
await RougelikeLayerModel.bulkWrite(updateArr.map(({ gameCode, roleId, layer, layerNodes }) => {
return { updateOne: { filter: { gameCode, roleId, layer }, update: { $set: { layerNodes } }, upsert: true } }
}))
}
public static async findByGameCode(gameCode: string, lean = true) {
const result: RougelikeLayerType[] = await RougelikeLayerModel.find({ gameCode }).lean(lean);
return result;
}
public static async findByGameCodeAndLayer(gameCode: string, layer: number, lean = true) {
const result: RougelikeLayerType = await RougelikeLayerModel.findOne({ gameCode, layer }).lean(lean);
return result;
}
public static async findByGameCodeAndLayers(gameCode: string, layers: number[], lean = true) {
const result: RougelikeLayerType[] = await RougelikeLayerModel.find({ gameCode, layer: { $in: layers } }).lean(lean);
return result;
}
public static async findByGameCodeAndHasPass(gameCode: string, hasPass: boolean, lean = true) {
const result: RougelikeLayerType[] = await RougelikeLayerModel.find({ gameCode, hasPass }).lean(lean);
return result;
}
};
export const RougelikeLayerModel = getModelForClass(RougelikeLayer);
export interface RougelikeLayerType extends Pick<DocumentType<RougelikeLayer>, keyof RougelikeLayer> { };
export type RougelikeLayerPara = Partial<RougelikeLayerType>; // 将所有字段变成可选项
+109
View File
@@ -0,0 +1,109 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
export class RewardInter {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
@prop({ required: true })
expireTime?: number;
}
/**
* 每场获得的圣物&特性卡
*/
@index({ roleId: 1 })
@index({ gameCode: 1 })
@index({ roleId: 1, status: 1 })
export default class RougelikeRecord extends BaseModel {
@prop({ required: true })
roleId: string; // 角色id
@prop({ required: true, default: '' })
gameCode: string; // 每场唯一code
@prop({ required: true, default: 0 })
grade: number; // 难度
@prop({ required: true, default: 0 })
type: number; // 试炼类型
@prop({ required: true, default: 0 })
authorType: number; // 流派类型
@prop({ required: true, default: 0 })
maxLayer: number; // 总共多少层
@prop({ required: true, default: 0 })
curLayer: number; // 当前在第几层
@prop({ required: true, default: 0 })
status: number; // 0-选角色卡, 1-进行中 2-已达成
@prop({ required: true, default: 0 })
score: number; // 本场获得的积分
@prop({ required: true, type: RewardInter, default: [] })
takeoutReward: RewardInter[]; // 本场获得了的奖励(灵石,记录一下)id&count
@prop({ required: true, default: false })
hasReceivedTakeout: boolean; // 是否已带出
@prop({ required: true, default: 0 })
coin: number; // 试炼币
@prop({ required: true, default: 0 })
coinTotal: number; // 试炼币累计值
@prop({ required: true, default: 0 })
techScore: number; // 科技分
// public static async updateByGameCode(gameCode: string, params: { $set: RougelikeRecordPara, $inc?: { coin?: number, score?: number, techScore?: number } }, lean = true) {
// let doc = new RougelikeRecordModel();
// let insert = Object.assign(doc);
// for (let key in params.$inc) {
// if (insert[key] != undefined) delete insert[key];
// }
// for (let key in params.$set) {
// if (insert[key] != undefined) delete insert[key];
// }
// const result: RougelikeRecordType = await RougelikeRecordModel.findOneAndUpdate({ gameCode }, { $setOnInsert: insert, ...params }, { new: true, upsert: true }).lean(lean);
// return result;
// }
public static async updateByGameCode(gameCode: string, params: { $set?: RougelikeRecordPara, $inc?: { coin?: number, coinTotal?: number, score?: number, techScore?: number } }, lean = true) {
const result: RougelikeRecordType = await RougelikeRecordModel.findOneAndUpdate({ gameCode }, params, { new: true, upsert: true }).lean(lean);
return result;
}
public static async findByGameCode(gameCode: string, lean = true) {
const result: RougelikeRecordType = await RougelikeRecordModel.findOne({ gameCode }).lean(lean);
return result;
}
public static async findByRoleIdAndStatus(roleId: string, status: number, lean = true) {
const result: RougelikeRecordType = await RougelikeRecordModel.findOne({ roleId, status: { $lt: status } }).lean(lean);
return result;
}
public static async takeout(gameCode: string) {
const result: RougelikeRecordType = await RougelikeRecordModel.findOneAndUpdate({ gameCode }, { $set: { hasReceivedTakeout: true } }, { new: true }).lean();
return result;
}
public static async costCoin(gameCode: string, costCoin: number) {
const result: RougelikeRecordType = await RougelikeRecordModel.findOneAndUpdate({ gameCode, coin: { $gte: costCoin } }, { $inc: { coin: -costCoin } }, { new: true }).lean();
return result;
}
};
export const RougelikeRecordModel = getModelForClass(RougelikeRecord);
export interface RougelikeRecordType extends Pick<DocumentType<RougelikeRecord>, keyof RougelikeRecord> { };
export type RougelikeRecordPara = Partial<RougelikeRecordType>; // 将所有字段变成可选项
+254
View File
@@ -0,0 +1,254 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
export class RewardInter {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
@prop({ required: true })
expireTime?: number;
}
export class Quest {
@prop({ required: true, default: 0 })
randomEventId: number; //问号点:随机事件id
@prop({ required: true, type: Number, default: [] })
EventOptions: number[]; // 问号点用:随机事件的选项
}
export class RecoveryChara {
@prop({ required: true, default: '' })
charaCode: string
@prop({ required: true, default: 0 })
charaId: number; // 恢复的武将
@prop({ required: true, default: 0 })
beforeHp: number; // 恢复前的hp
@prop({ required: true, default: 0 })
afterHp: number; // 恢复后的hp
}
export class Recruit {
@prop({ required: true, default: 0 })
index: number; // 索引
@prop({ required: true, default: 0 })
charaId: number; // 角色卡id
@prop({ required: true, default: 0 })
status: number; // 0-未领取 1-已领取
};
export class TrainCard {
@prop({ required: true, default: '' })
cardCode: string;
@prop({ required: true, default: 0 })
cardId: number; // 特训的卡牌
@prop({ required: true, default: 0 })
beforeLv: number; // 特训前等级
@prop({ required: true, default: 0 })
afterLv: number; // 特训后等级
};
export class RestPoint {
@prop({ required: true })
restType: number; // 休整点用:玩家选择的类型
@prop({ required: false })
recoveryCnt?: number; // 恢复的次数
@prop({ required: false, type: RecoveryChara })
recoveryCharas?: RecoveryChara[];//恢复的数据
// @prop({ required: false, type: Recruit })
// recruits: Recruit[]; // 休整点:提供的随机可供招募的武将
@prop({ required: false })
trainCardCnt?: number; //休整点:特训 特训次数
@prop({ required: false, type: TrainCard })
trainCards?: TrainCard[]; //特训卡
}
export class Challenge {
@prop({ required: true, default: 0 })
challengeId: number; // 挑战id
@prop({ required: true, default: 0 })
status: number; // 0-未选择 1-已选择 2-已达成 3-已领取
@prop({ required: true, default: 0 })
progress: number; // 挑战进度
};
export class Shop {
@prop({ required: true, default: 0 })
optionIndex: number; //商店物品索引
@prop({ required: true, default: 0 })
rewardType: number; //特性卡、圣物类型
@prop({ required: true, default: 0 })
rewardId: number; // 特性卡、圣物id
@prop({ required: true, default: 0 })
optionStatus: number; // 0-未领取 1-已领取
@prop({ required: true, default: 0 })
price: number; // 原价
@prop({ required: true, default: 0 })
discountPrice: number; //购买时折扣价格
}
export class WeightRecord {
@prop({ required: false, default: 0 })
originalWight?: number;
@prop({ required: false, default: 0 })
passiveRedWight?: number;
@prop({ required: false, default: 0 })
holyRedWight?: number;
@prop({ required: false, default: 0 })
authorAddWeight?: number;
@prop({ required: false, default: 0 })
passiveLableNum?: number;
@prop({ required: false, default: 0 })
passiveLableNumAddWeight?: number;
@prop({ required: false, default: 0 })
holyLableNum?: number;
@prop({ required: false, default: 0 })
holyLableNumAddWeight?: number;
@prop({ required: false, default: 0 })
finalWeight?: number;
}
export class Option {
@prop({ required: true, default: 0 })
optionIndex: number;
@prop({ required: true, default: 0 })
rewardId: number; // 角色卡、特性卡、圣物id
@prop({ required: true, default: 0 })
optionStatus: number; // 0-未领取 1-已领取
@prop({ required: false, type: Number, default: [] })
passiveCardIds?: number[]; //高级学员自带特性卡
@prop({ required: false, type: WeightRecord, default: {} })
weightRecord?: WeightRecord //用于测试权重记录
}
export class RewardIn {
@prop({ required: true, default: 0 })
groupIndex: number; // 组index
@prop({ required: true, default: 0 })
rewardType: number; // 奖励类型
@prop({ required: false, type: Option })
options?: Option[]; // 组内随机的奖励
@prop({ required: true, default: 0 })
groupStatus: number; // 组选择 0-未选择 1-已选择
@prop({ required: true, default: 0 })
chooseNum: number; // 这一组总共能选的数量3选2
}
/**
* 每场的每层选择的关卡的数据
*/
@index({ roleId: 1 })
@index({ gameCode: 1 })
@index({ gameCode: 1, detailCode: 1 })
@index({ gameCode: 1, layer: 1, nodeId: 1 })
export default class RougelikeRecordDetail extends BaseModel {
@prop({ required: true })
roleId: string; //角色id
@prop({ required: true, default: '' })
gameCode: string; // 每场唯一code
@prop({ required: true, default: '' })
detailCode: string; // 层+关卡id唯一code
@prop({ required: true, default: 0 })
layer: number; // 层
@prop({ required: true, default: 0 })
nodeId: number; // 关卡id
@prop({ required: true, default: 0 })
nodeType: number; // 关卡类型 普通关、精英关、挑战关、试炼商店、休整点、问号点、boss
@prop({ required: false })
warId?: number; // 关卡id //【普通关、精英关、boss关】
@prop({ required: false })
battleCode?: string; // battleRecord的code
@prop({ required: true, default: 0 })
status: number; // 关卡状态 0-默认值 1-成功 2-失败
@prop({ required: false, type: Quest, default: [] })
question?: Quest; // 问好点随机事件
@prop({ required: false, default: 0 })
questType?: number; // 问好点随机type
@prop({ required: false, type: RestPoint, default: [] })
restPoints?: RestPoint[];
@prop({ required: false, type: Challenge, default: {} })
challenge?: Challenge; // 【挑战点】
@prop({ required: false, type: Shop, default: [] })
shops?: Shop[]; // 商店内的随机商品
@prop({ required: false, type: RewardIn, default: [] })
rewards?: RewardIn[]; // 通用过关后的奖励,挑战后的奖励
@prop({ required: false, default: 0 })
reRandRewardCnt: number; // 重新随机奖励
public static async updateByCode(gameCode: string, detailCode: string, params: { $set: RougelikeRecordDetailPara, $inc?: { reRandRewardCnt: 1 } }, lean = true) {
const result: RougelikeRecordDetailType = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode }, params, { new: true, upsert: true }).lean(lean);
return result;
}
public static async updateRewardByGroupIndex(gameCode: string, detailCode: string, groupIndex: number, groupStatus: number, options: Option[], params?: { $set: RougelikeRecordDetailPara }, lean = true) {
const result: RougelikeRecordDetailType = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.groupIndex': groupIndex }, { ...params, 'rewards.$.options': options, 'rewards.$.groupStatus': groupStatus, }, { new: true, upsert: true }).lean(lean);
return result;
}
public static async updateShopByCode(gameCode: string, detailCode: string, optionIndex: number, optionStatus: number, params?: { $set: RougelikeRecordDetailPara }, lean = true) {
const result: RougelikeRecordDetailType = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'shops.optionIndex': optionIndex }, { ...params, 'shops.$.optionStatus': optionStatus }, { new: true, upsert: true }).lean(lean);
return result;
}
public static async findByGameCode(gameCode: string, lean = true) {
const result: RougelikeRecordDetailType[] = await RougelikeRecordDetailModel.find({ gameCode }).lean(lean);
return result;
}
public static async findByCode(gameCode: string, detailCode: string, lean = true) {
const result: RougelikeRecordDetailType = await RougelikeRecordDetailModel.findOne({ gameCode, detailCode }).lean(lean);
return result;
}
public static async findByGameCodeAndLtLayer(gameCode: string, layer: number, lean = true) {
const result: RougelikeRecordDetailType[] = await RougelikeRecordDetailModel.find({ gameCode, layer: { $lt: layer } }).lean(lean);
return result;
}
public static async findByGameCodeAndLayer(gameCode: string, layer: number, lean = true) {
const result: RougelikeRecordDetailType = await RougelikeRecordDetailModel.findOne({ gameCode, layer }).lean(lean);
return result;
}
public static async bulkWriteUpdate(updateArr: RougelikeRecordDetailPara[]) {
if (updateArr.length == 0) return;
await RougelikeRecordDetailModel.bulkWrite(updateArr.map((param) => {
const { gameCode, detailCode } = param
return { updateOne: { filter: { gameCode, detailCode }, update: { $set: { ...param } }, upsert: true } }
}))
}
};
export const RougelikeRecordDetailModel = getModelForClass(RougelikeRecordDetail);
export interface RougelikeRecordDetailType extends Pick<DocumentType<RougelikeRecordDetail>, keyof RougelikeRecordDetail> { };
export type RougelikeRecordDetailPara = Partial<RougelikeRecordDetailType>; // 将所有字段变成可选项
+66
View File
@@ -0,0 +1,66 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
import { getZeroPointD } from '../pubUtils/timeUtil';
import { SHOP_REFRESH_TYPE } from '../consts';
@index({ roleId: 1, refTime: 1 })
@index({ refTime: 1, receiveNum: 1 })
export default class RougelikeScore extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, default: new Date() })
refTime: Date; // 每周刷新奖励
@prop({ required: true, default: 0 })
score: number; // 积分
@prop({ required: true, type: Number, default: [] })
received: number[]; // 已领取的id
@prop({ required: true, default: 0 })
receiveNum: number; // 已领取的id
@prop({ required: true, default: 0 })
takeoutRewardCnt: number; // 额外奖励已领取的次数
public static async findByRoleId(roleId: string) {
let refTime = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
let result: RougelikeScoreType = await RougelikeScoreModel.findOne({ roleId, refTime }).lean();
return result;
}
public static async incScore(roleId: string, score: number) {
let refTime = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
let result: RougelikeScoreType = await RougelikeScoreModel.findOneAndUpdate({ roleId, refTime }, { $inc: { score }, $setOnInsert: { received: [], receiveNum: 0, takeoutRewardCnt: 0 } }, { new: true, upsert: true }).lean();
return result;
}
public static async receive(roleId: string, targetScore: number, index: number) {
let refTime = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
let result: RougelikeScoreType = await RougelikeScoreModel.findOneAndUpdate({ roleId, refTime, score: { $gte: targetScore } }, { $push: { received: index }, $inc: { receiveNum: 1 } }, { new: true }).lean();
return result;
}
public static async findByReceiveNum(refTime: Date, maxNum: number) {
let result: RougelikeScoreType[] = await RougelikeScoreModel.find({ refTime, receiveNum: { $lt: maxNum } }).lean();
return result;
}
public static async receiveAll(_ids: string[], maxNum: number) {
await RougelikeScoreModel.updateMany({ _id: { $in: _ids } }, { $set: { receiveNum: maxNum } });
}
public static async receiveTakeoutReward(roleId: string, maxNum: number) {
let refTime = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
await RougelikeScoreModel.findOneAndUpdate({ roleId, refTime }, { $setOnInsert: { score: 0, received: [], receiveNum: 0, takeoutRewardCnt: 0 } }, { upsert: true });
let result: RougelikeScoreType = await RougelikeScoreModel.findOneAndUpdate({ roleId, refTime, takeoutRewardCnt: { $lt: maxNum } }, { $inc: { takeoutRewardCnt: 1 } }, { new: true }).lean();
return result;
}
}
export const RougelikeScoreModel = getModelForClass(RougelikeScore);
export interface RougelikeScoreType extends Pick<DocumentType<RougelikeScore>, keyof RougelikeScore> { };
export type RougelikeScorePara = Partial<RougelikeScoreType>; // 将所有字段变成可选项
+95
View File
@@ -0,0 +1,95 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, index } from '@typegoose/typegoose';
export class Circle {
@prop({ required: true, default: 0 })
techId: number; // 科技点
@prop({ required: true, default: 0 })
circleId: number; // 法阵的索引
@prop({ required: true, default: 0 })
hid: number; // 玩家放上的武将
@prop({ required: true, default: 0 })
ce: number; // 武将的战力
constructor(techId: number, circleId: number) {
this.techId = techId;
this.circleId = circleId;
this.hid = 0;
this.ce = 0;
}
}
@index({ roleId: 1 })
export default class RougelikeTech extends BaseModel {
@prop({ required: true })
roleId: string;
@prop({ required: true, default: 0 })
techScore: number; // 获得了的总科技点
@prop({ required: true, type: Number, default: [] })
unlockedTech: number[]; // 科技点id
@prop({ required: true, type: Circle, _id: false, default: [] })
circles: Circle[] // 法阵
@prop({ required: true, type: Number, default: [] })
effectIds: number[]; // 科技点id
// 查询
public static async findByRoleId(roleId: string, select = '') {
const result: RougelikeTechType = await RougelikeTechModel.findOne({ roleId }).select(select).lean();
return result;
}
// 增加
public static async increaseScore(roleId: string, techScore: number) {
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId }, { $setOnInsert: { unlockedTech: [], circles: [] }, $inc: { techScore } }, { new: true, upsert: true }).lean();
return result;
}
// 解锁科技点
public static async unlockTech(roleId: string, techId: number, circleIds: number[]) {
let circles = circleIds.map(circleId => new Circle(techId, circleId));
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId }, { $push: { unlockedTech: techId, circles: { $each: circles } } }, { new: true, upsert: true }).lean();
return result;
}
// 法阵放武将
public static async putOnCircle(roleId: string, circleId: number, hid: number, ce: number) {
if(hid > 0) await this.putOffCircle(roleId, hid);
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId, 'circles.circleId': circleId }, { $set: { 'circles.$.hid': hid, 'circles.$.ce': ce } }, { new: true }).lean();
return result;
}
// 法阵撤下
public static async putOffCircle(roleId: string, hid: number) {
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId, 'circles.hid': hid }, { $set: { 'circles.$.hid': 0, 'circles.$.ce': 0 } }, { new: true }).lean();
return result;
}
public static async updateEffectId(roleId: string, effectIds: number[]) {
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId }, { $set: { effectIds } }, { new: true }).lean();
return result;
}
// 更新武将战力
public static async updateCircle(roleId: string, circles: Circle[], effectIds: number[]) {
let result: RougelikeTechType = await RougelikeTechModel.findOneAndUpdate({ roleId }, { $set: { circles, effectIds } }, { new: true }).lean();
return result;
}
// 清空科技树
public static async clearTech(roleId: string) {
await RougelikeTechModel.deleteMany({ roleId });
}
}
export const RougelikeTechModel = getModelForClass(RougelikeTech);
export interface RougelikeTechType extends Pick<DocumentType<RougelikeTech>, keyof RougelikeTech> { };
export type RougelikeTechPara = Partial<RougelikeTechType>; // 将所有字段变成可选项