Files
ZYZ/shared/db/Role.ts
2022-05-12 18:35:56 +08:00

798 lines
35 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 { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, BLOCK_TYPE } from './../consts';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import User from './User';
import { shouldRefresh } from '../pubUtils/util';
import { nowSeconds, getTimeFunD } from '../pubUtils/timeUtil';
import { Figure } from '../domain/dbGeneral';
import * as dicParam from '../pubUtils/dicParam';
import Hero from './Hero';
import { SearchRoleParam } from '../domain/backEndField/search';
export class TopHero {
@prop({ required: true })
hid: number; // 武将id
@prop({ required: true })
ce: number; // 战力
@prop({ ref: 'Hero', type: mongoose.Schema.Types.ObjectId })
hero: Ref<Hero>;
}
class DungeonHero {
@prop({ required: true })
battleId: number; // 关卡id
@prop({ required: true, type: Number, default: [] })
heroes: Array<number>; // 武将id
}
class PayRecord {
@prop({ required: true })
id: string; // 购买项 product id
@prop({ required: true })
cnt: number; // 购买次数
}
export class WarStar {
@prop({ required: true })
id: number; // 关卡 id
@prop({ required: true })
warType: number; // 关卡类型
@prop({ required: true })
star: number; // 星级
@prop({ required: true, type: Number })
stars: number[]; // 星级
}
export class Teraph {
@prop({ required: true, default: 1 })
id: number; // 神像的id
@prop({ required: true, default: 1 })
grade: number = 1; // 等级
@prop({ required: true, default: 0 })
hp: number = 0;
@prop({ required: true, default: 0 })
atk: number = 0;
@prop({ required: true, default: 0 })
def: number = 0;
@prop({ required: true, default: 0 })
mdef: number = 0;
@prop({ required: true, default: 0 })
count: number = 0; // 次数
@prop({ required: true, default: 0 })
criCount: number = 0; // 暴击次数
constructor(id: number) {
this.id = id;
this.attr = this.getAttr();
}
public get attr() {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, this.hp);
map.set(ABI_TYPE.ABI_ATK, this.atk);
map.set(ABI_TYPE.ABI_DEF, this.def);
map.set(ABI_TYPE.ABI_MDEF, this.mdef);
return map
}
private getAttr() {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, this.hp);
map.set(ABI_TYPE.ABI_ATK, this.atk);
map.set(ABI_TYPE.ABI_DEF, this.def);
map.set(ABI_TYPE.ABI_MDEF, this.mdef);
return map
}
public set attr(value: Map<number, number>) {
value.forEach((val, id) => {
if (id == ABI_TYPE.ABI_HP) this.hp = val;
if (id == ABI_TYPE.ABI_ATK) this.atk = val;
if (id == ABI_TYPE.ABI_DEF) this.def = val;
if (id == ABI_TYPE.ABI_MDEF) this.mdef = val;
});
}
}
/**
* 角色字段接口
*/
@index({ roleId: 1 })
@index({ roleName: 1 })
@index({ serverId: 1, roleId: 1 })
@index({ towerLv: -1, towerUpTime: 1 })
// @index({ userInfo.uid: 1, serverId: 1 })
export default class Role extends BaseModel {
@prop({ required: true })
userInfo: User;
@prop({ required: true })
seqId: number;
@prop({ required: true })
roleId: string; // 角色 id生成编码
@prop({ required: true })
roleName: string; // 角色名
@prop({ required: true })
serverType: string; // 服务器类型
@prop({ required: true })
serverId: number; // 区服 id
@prop({ required: true, default: 0 })
blockType: BLOCK_TYPE; // 封禁类型 1-封言 2-封禁
@prop({ required: true, default: '' })
blockReason: string; // 封禁理由
@prop({ required: true })
code: string; // 邀请码
@prop({ required: true, default: false })
hasInit: boolean; // 是否初始化过
@prop({ required: true, type: Number })
showLineup: number[]; // 展示阵容
@prop({ required: true, type: Figure, default: getDefualtFigure('head'), _id: false })
heads: Figure[]; // 拥有头像列表
@prop({ required: true, type: Figure, default: getDefualtFigure('frame'), _id: false })
frames: Figure[]; // 拥有相框列表
@prop({ required: true, type: Figure, default: getDefualtFigure('spine'), _id: false })
spines: Figure[]; // 拥有的形象
public get head() { // 虚拟字段head 当前头像
let curHead = this.heads?.find(cur => cur.enable && (!cur.time || cur.time > nowSeconds()));
return curHead ? curHead.id : dicParam.EXTERIOR.EXTERIOR_FACE;
}
public get frame() { // 虚拟字段frame 当前相框
let curFrame = this.frames?.find(cur => cur.enable && (!cur.time || cur.time > nowSeconds()));
return curFrame ? curFrame.id : dicParam.EXTERIOR.EXTERIOR_FACECASE;
}
public get spine() { // 虚拟字段spine 当前形象
let curSpine = this.spines?.find(cur => cur.enable && (!cur.time || cur.time > nowSeconds()));
return curSpine ? curSpine.id : dicParam.EXTERIOR.EXTERIOR_APPEARANCE;
}
@prop({ required: true, default: 0 })
exp: number; // 经验值
@prop({ required: true, default: 1 })
lv: number; // 主公等级
@prop({ required: true, default: 0 })
ce: number; // 总战力
@prop({ required: true, default: 0 })
topLineupCe: number; // 最强x人战力
@prop({ required: true, type: TopHero, default: [], _id: false })
topLineup: Array<TopHero>; // 总战力
@prop({ required: true, default: 100 })
gold: number; // 总金币
@prop({ required: true, default: 0 })
paidGold: number; // 支付所得金币
@prop({ required: true, default: 100 })
giftGold: number; // 赠送所得金币
@prop({ required: true, default: 0 })
totalPay: number; // 总支付金额
@prop({ required: true, default: 0 })
totalBuy: number; // 总金币购买
@prop({ required: true, default: 0 })
totalCost: number; // 金币总花费
@prop({ required: true, default: [] })
payRecord: PayRecord[]; // 支付记录
@prop({ required: true, default: 0 })
jewelCount: number; // 装备数量
@prop({ required: true })
equipStarSum: number; // 装备上的星级的数量
@prop({ required: true, default: 0 })
coin: number; // 总铜钱
@prop({ required: true, default: 0 })
frdCnt: number; // 情谊点
@prop({ required: true, type: WarStar, default: [], _id: false })
warStar: WarStar[]; // 关卡星级
@prop({ required: true, default: 1 })
loginCnt: number; // 登录次数
@prop({ required: true, default: nowSeconds })
createTime: number; // 创建时间
@prop({ required: true, default: 0 })
loginTime: number; // 更新 / 登录时间
@prop({ required: true, default: 0 })
quitTime: number; // 更新 / 登录时间
// 月卡相关
@prop({ required: true, default: 0 })
vipStartTime: number; // 永久卡开始时间
@prop({ required: true, default: 0 })
isVip: boolean; // 是否购买了永久月卡
// 天梯相关
@prop({ required: true, default: 1 })
towerLv: number; // 天梯当前层数
@prop({ required: true, default: new Date() })
towerUpTime: Date; // 天梯爬到这一层的时间
@prop({ required: true, default: [], type: Number })
towerReceived: number[]; // 已领取节点
@prop({ required: true, default: 0 })
hangUpSpdUpCnt: number; // 挂机加速次数
@prop({ required: true, default: new Date() })
lastSpdUpTime: Date; // 最后一次挂机加速时间
@prop({ required: true, default: 0 })
towerTaskCnt: number; // 刷新派遣任务的次数向上累加每天8个
@prop({ required: false })
towerTaskRefTime: Date; // 刷新派遣任务的时间
@prop({ required: true, default: 0 })
towerTaskReCnt: number; // 刷新派遣任务刷新次数
// 奇遇事件相关
@prop({ required: true, default: 0 })
eventStatus: number; // 奇遇开启状态, 0-未开启 1-开启了第一场事件 2-完全开启
// 远征相关
@prop({ required: true, default: 0 })
expeditionPoint: number; // 远征点数
@prop({ required: true, default: 0 })
expeditionResetCnt: number; // 远征重置次数
@prop({ required: true, default: new Date() })
expeditionResetRefTime: Date; // 远征重置次数刷新时间
// 秘境相关
@prop({ required: true, default: 0 })
dungeonCnt: number; // 秘境挑战次数
@prop({ required: true, default: 0 })
dungeonBuyCnt: number; // 秘境购买次数
@prop({ required: true, default: new Date() })
dungeonRefTime: Date; // 秘境刷新时间
@prop({ required: true, type: DungeonHero, default: [], _id: false })
dungeonHeroes: DungeonHero[]; // 秘境首通使用的武将
// 全局养成
@prop({ required: true, default: 1 })
title: number; //爵位
//神像
@prop({ required: true, type: Teraph, default: getInitialTeraph(), _id: false })
teraphs: Teraph[];
// 公会
@prop({ required: true, default: false })
hasGuild: boolean; // 是否加入过公会
@prop({ required: true, default: 0 })
quitGuildTime: number; // 上次退出公会的时间
@prop({ required: true, default: "" })
guildCode: string; // 加入的军团code
@prop({ required: true, default: "" })
guildName: string; // 加入的军团名
// 好友
@prop({ required: true, default: 0 })
friendCnt: number; // 好友人数
@prop({ required: true, default: 0 })
blockCnt: number; // 黑名单人数
@prop({ required: true, default: 0 })
recFrdApplyCnt: number; // 玩家收取好友申请数量
@prop({ required: true, default: 0 })
updatedMailAt: number;
// 排行相关
@prop({ required: true, default: 0 })
lvUpdatedAt: number; // 升级时间
@prop({ required: true, default: 0 })
heroNum: number; // 武将数量
@prop({ required: true, default: 0 })
heroNumUpdatedAt: number; // 武将数量更新时间
@prop({ required: true, default: 0 })
dungeonWarId: number; // 秘境通关关卡
@prop({ required: true, default: 0 })
dungeonUpdatedAt: number; // 秘境通关时间
@prop({ required: true, default: 0 })
mainWarId: number; // 主线通关关卡
@prop({ required: true, default: 0 })
mainUpdatedAt: number; // 秘境通关时间
@prop({ required: true, default: 0 })
mainEliteWarId: number; // 精英通关关卡
@prop({ required: true, default: 0 })
mainEliteUpdatedAt: number; // 精英通关时间
@prop({ required: true, default: [], type: Number })
rankReceived: number[]; // 已领取奖励
@prop({ required: true, default: [], type: Number })
guide: number[]; // 引导
@prop({ required: true, default: [], type: Number })
receivedBox: number[]; // 引导
@prop({ required: true, default: false })
gachaHasGuide: boolean; // 是否进行过引导特殊招募
@prop({ required: true })
renameCnt: number; // 改名次数
@prop({ required: true })
sdkMark: boolean; // 37sdk标记有问题
public static async findAllByUid(uid: number, getters = false, virtuals = true) {
const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId head frame spine heads frames spines lv updatedAt').lean({ getters, virtuals });
return role;
}
public static async findByUidAndSetTime(uid: number, serverId: number, select?: string, getters = false) {
const curSec = nowSeconds();
// 为了计算累计登录此处查询new为false
const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, { loginTime: curSec, quitTime: curSec }, { new: false }).select(select).lean({ getters, virtuals: true });
return role;
}
public static async findByUid(uid: number, serverId: number, select?: string, getters = false) {
const role: RoleType = await RoleModel.findOne({ 'userInfo.uid': uid, serverId }).select(select).lean({ getters, virtuals: true });
return role;
}
public static async findByRoleIdAndSetTime(roleId: string, select?: string, getters = false) {
const curSec = nowSeconds();
// 为了计算累计登录此处查询new为false
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { loginTime: curSec, quitTime: curSec }, { new: false }).select(select).lean({ getters, virtuals: true });
return role;
}
/**
* 根据roleId获取一条数据
* @param roleId 玩家id
* @param select 选取字段,来自 selectConst/ROLE
* @param getters 是否使用get方法如ce使用了自动缩小1w倍
*/
public static async findByRoleId(roleId: string, select?: string, getters = false, virtuals = true) {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({ getters, virtuals });
return role;
}
public static async findByRoleIds(roleIds: string[], select?: string, getters = false, virtuals = true) {
const role: RoleType[] = await RoleModel.find({ roleId: { $in: roleIds } }).select(select).lean({ getters, virtuals });
return role;
}
public static async findByRoleName(roleName: string, select?: string, getters = false, virtuals = true) {
const role: RoleType = await RoleModel.findOne({ roleName }).select(select).lean({ getters, virtuals });
return role;
}
public static async createRole(uid: number, serverId: number, roleInfo: { roleId: string; roleName: string; seqId: number; code: string, lv?: number, exp?: number }, lean = true) {
const user = await User.findUserByUid(uid);
if (!user) return null;
const doc = new RoleModel();
const update = Object.assign(doc.toJSON(), roleInfo, { userInfo: user, serverType: user.serverType, serverId });
delete update._id;
const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, update, { upsert: true, new: true }).lean(lean);
return role;
}
public static async setEventStatus(roleId: string, eventStatus: number, lean = true) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { eventStatus }, { new: true }).lean(lean);
return role;
}
public static async towerLvUp(roleId: string, newWarStar: WarStar[] = []) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { towerLv: 1 }, $push: { warStar: { $each: newWarStar }}, towerUpTime: new Date() }, { new: true }).lean({ getters: true, virtuals: true });
return role;
}
public static async receiveTowerBox(roleId: string, ids: number[] = []) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $push: { towerReceived: { $each: ids }} }, { new: true }).lean();
return role;
}
public static async increaseExpeditionPoint(roleId: string, point: number, lean = true) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { expeditionPoint: point } }, { new: true }).lean(lean);
return role;
}
public static async levelup(roleId: string, lv: number, exp: number, lean = true) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $set: { exp, lv } }, { new: true }).lean(lean);
return role;
}
public static async addCoin(roleId: string, cnt: number, lean = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { coin: cnt } }, { "new": true, "upsert": true }).lean(lean);
return result;
}
public static async addGoldFree(roleId: string, cnt: number, lean = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { gold: cnt, giftGold: cnt } }, { "new": true, "upsert": true }).lean(lean);
return result;
}
public static async costCoin(roleId: string, cnt: number, lean = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId, coin: { $gte: cnt } }, { $inc: { coin: -cnt } }, { "new": true }).lean(lean);
return result;
}
public static async costGold(roleId: string, cnt: number, lean = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId, gold: { $gte: cnt } }, { $inc: { gold: -cnt, totalCost: cnt } }, { "new": true }).lean(lean);
return result;
}
public static async increaseGoldAndCoin(roleId: string, gold: {count: number, isPay: boolean}[], coin: number) {
let paidGold = 0, giftGold = 0, addGold = 0;
for(let { count, isPay } of gold) {
addGold += count;
if(isPay) {
paidGold += count;
} else {
giftGold += count;
}
}
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { gold: addGold, paidGold, giftGold, coin } }, { new: true }).lean();
if(result.gold > dicParam.BAG.BAG_GOODS_UPLIMITED) {
result = await RoleModel.findOneAndUpdate({ roleId, gold: { $gte: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { $set: { gold: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { new: true }).lean();
}
if(result.coin > dicParam.BAG.BAG_GOODS_UPLIMITED) {
result = await RoleModel.findOneAndUpdate({ roleId, coin: { $gte: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { $set: { coin: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { new: true }).lean();
}
return result;
}
public static async decreaseGoldAndCoin(roleId: string, gold: {count: number, isPay: boolean}[], coin: number) {
let paidGold = 0, giftGold = 0, addGold = 0;
for(let { count, isPay } of gold) {
addGold += count;
if(isPay) {
paidGold += count;
} else {
giftGold += count;
}
}
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { gold: -1 * addGold, paidGold: -1 * paidGold, giftGold: -1 * giftGold, totalCost: addGold, coin: -1 * coin } }, { new: true }).lean();
if(result.gold > dicParam.BAG.BAG_GOODS_UPLIMITED) {
result = await RoleModel.findOneAndUpdate({ roleId, gold: { $gte: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { $set: { gold: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { new: true }).lean();
}
if(result.coin > dicParam.BAG.BAG_GOODS_UPLIMITED) {
result = await RoleModel.findOneAndUpdate({ roleId, coin: { $gte: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { $set: { coin: dicParam.BAG.BAG_GOODS_UPLIMITED } }, { new: true }).lean();
}
return result;
}
public static async hangUpSpdUp(roleId: string, cnt: number, curTime: Date) {
if (cnt < 0) return null;
const result = await RoleModel.findOne({ roleId }).lean();
const lastSpdUpTime = result?.lastSpdUpTime;
let role: RoleType;
if(!lastSpdUpTime || shouldRefresh(lastSpdUpTime, curTime)) {
role = await RoleModel.findOneAndUpdate({ roleId }, { hangUpSpdUpCnt: cnt, lastSpdUpTime: curTime }, { new: true }).lean();
} else {
role = await RoleModel.findOneAndUpdate({ roleId, hangUpSpdUpCnt: { $lte: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - cnt } }, { $inc: { hangUpSpdUpCnt: cnt }, lastSpdUpTime: curTime }, { new: true }).lean();
}
return role;
}
// 重置派遣次数
public static async resetTowerCnt(roleId: string, curTime: Date, lean = true) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { towerTaskCnt: 0, towerTaskRefTime: curTime, towerTaskReCnt: 0 }, { new: true }).lean(lean);
return role;
}
// 刷新派遣任务次数增长
public static async increaseTowerCnt(roleId: string, num: number, lean = true) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { towerTaskCnt: num } }, { new: true }).lean(lean);
return role;
}
// 派遣任务增加刷新次数
public static async increaseTowerRefCnt(roleId: string, num: number, lean = true) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { towerTaskReCnt: num } }, { new: true }).lean(lean);
return role;
}
// 刷新远征重置次数
public static async increaseExpeditionResetCnt(roleId: string, needRefresh: boolean, curTime: Date, lean = true) {
let role: RoleType;
if (needRefresh) {
role = await RoleModel.findOneAndUpdate({ roleId }, { expeditionResetCnt: 1, expeditionResetRefTime: curTime }, { new: true }).lean(lean);
} else {
role = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { expeditionResetCnt: 1 } }, { new: true }).lean(lean);
}
return role;
}
// 购买次数
public static async buyCnt(roleId: string, needRefresh: boolean, inc: number, curTime: Date, lean = true) {
let role: RoleType;
if (needRefresh) {
role = await RoleModel.findOneAndUpdate({ roleId }, { dungeonCnt: 0, dungeonRefTime: curTime, dungeonBuyCnt: inc }, { new: true }).lean(lean);
} else {
role = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { dungeonBuyCnt: inc } }, { new: true }).lean(lean);
}
return role;
}
// 增加次数
public static async increaseDungeonCnt(roleId: string, needRefresh: boolean, inc: number, curTime: Date, lean = true) {
let role: RoleType;
if (needRefresh) {
role = await RoleModel.findOneAndUpdate({ roleId }, { dungeonCnt: inc, dungeonRefTime: curTime, dungeonBuyCnt: 0 }, { new: true }).lean(lean);
} else {
role = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { dungeonCnt: inc } }, { new: true }).lean(lean);
}
return role;
}
// 获取排行榜
public static async getRank(type: string, serverId: number, select?: string, page = 1, limit = 200) {
let sortBy = {};
let condition = {};
switch (type) {
case 'tower':
sortBy = { towerLv: -1, towerUpTime: 1 }; condition = { towerLv: { $gt: 0 } }; break;
case 'topLineup':
sortBy = { topLineupCe: -1, updatedAt: 1 }; condition = { topLineupCe: { $gt: 0 } }; break;
case 'heroNum':
sortBy = { heroNum: -1, heroNumUpdatedAt: 1 }; condition = { heroNum: { $gt: 0 } }; break;
case 'lv':
sortBy = { lv: -1, updatedAt: 1 }; condition = { lv: { $gt: 0 } }; break;
case 'ce':
sortBy = { ce: -1, updatedAt: 1 }; condition = { ce: { $gt: 0 } }; break;
case 'dungeon':
sortBy = { dungeonWarId: -1, dungeonUpdatedAt: 1 }; condition = { dungeonWarId: { $gt: 0 } }; break;
case 'main':
sortBy = { mainWarId: -1, mainUpdatedAt: 1 }; condition = { mainWarId: { $gt: 0 } }; break;
case 'mainElite':
sortBy = { mainEliteWarId: -1, mainEliteUpdatedAt: 1 }; condition = { mainEliteWarId: { $gt: 0 } }; break;
default:
sortBy = {}; break;
}
const ranks: RoleType[] = await RoleModel.find({ serverId, ...condition }).select(select).sort(sortBy).limit(limit).skip((page - 1) * limit).lean({ virtuals: true, getters: true });
return ranks;
}
// 保存秘境首通队伍
public static async saveDungeonHero(roleId: string, battleId: number, heroes: number[], isSuccess: boolean) {
if (isSuccess) {
let role = await Role.findByRoleId(roleId);
let dungeonHeroes = role && role.dungeonHeroes;
let hasHero = dungeonHeroes && dungeonHeroes.find(cur => cur.battleId == battleId);
if (!dungeonHeroes || !hasHero) {
role = await RoleModel.findOneAndUpdate({ roleId }, { $push: { dungeonHeroes: { battleId, heroes } }, $set: { dungeonWarId: battleId, dungeonUpdatedAt: nowSeconds() } }, { new: true });
}
return role;
}
}
public static async updateRoleInfo(roleId: string, roleUpdate: RoleUpdate, getters = false, virtuals = true) {
delete roleUpdate._id;
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $set: roleUpdate }, { new: true }).lean({ getters, virtuals });
return result;
}
public static async incRoleInfo(roleId: string, inc: RoleInc, set: RoleUpdate, getters = false, virtuals = true) {
delete set._id;
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: inc, $set: set }, { new: true }).lean({ getters, virtuals });
return result;
}
public static async updateMainWarId(roleId: string, mainWarId: number, mainUpdatedAt: number, getters = false, virtuals = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId, mainWarId: { $lt: mainWarId } }, { $set: { mainWarId, mainUpdatedAt } }, { new: true }).lean({ getters, virtuals });
return result;
}
public static async updateMainEliteWarId(roleId: string, mainEliteWarId: number, mainEliteUpdatedAt: number, getters = false, virtuals = true) {
let result: RoleType = await RoleModel.findOneAndUpdate({ roleId, mainEliteWarId: { $lt: mainEliteWarId } }, { $set: { mainEliteWarId, mainEliteUpdatedAt } }, { new: true }).lean({ getters, virtuals });
return result;
}
// 记录加入公会
public static async joinGuild(roleId: string, guildCode: string, guildName: string) {
const result = await RoleModel.findOneAndUpdate({ roleId, hasGuild: false }, { hasGuild: true, guildCode, guildName }, { new: true }).lean();
return result;
}
/**
* 获取未加入公会且登录时间在三天内的人
* @param time
* @param serverId
* @param invitedMembers 当天已邀请过的人
*/
public static async getInviteList(time: number, serverId: number) {
const result: RoleType[] = await RoleModel.find({ loginTime: { $gt: time }, hasGuild: false, serverId, hasInit: true })
.select({ roleId: 1, roleName: 1, ce: 1, head: 1, frame: 1, lv: 1, title: 1, job: 1, quitTime: 1, _id: 0 })
.sort({ quitTime: -1, lv: -1, ce: -1 })
.limit(100).lean({ getters: true, virtuals: true });
return result;
}
// 获取好友推荐列表
public static async getRecommedList(minLv: number, maxLv: number, time: number) {
const result: RoleType[] = await RoleModel.find({ loginTime: { $gt: time }, lv: { $gte: minLv, $lte: maxLv }, hasInit: true }, { _id: 0 })
.select(ROLE_SELECT.SHOW_FRIEND_APPLY_LIST)
.sort({ quitTime: -1, lv: -1, ce: -1 })
.limit(200).lean({ getters: true, virtuals: true });
return result;
}
// 查询玩家
public static async searchByNameOrId(value: string) {
const result: RoleType[] = await RoleModel.find({
$or: [
{ roleName: { $regex: new RegExp(value.toString(), 'i') } },
{ roleId: value }
]
}, { _id: 0 })
.select(ROLE_SELECT.SHOW_FRIEND_APPLY_LIST)
.sort({ quitTime: -1, lv: -1, ce: -1 })
.limit(200).lean({ getters: true, virtuals: true });
return result;
}
// 公会解散
public static async dissmissGuild(members: string[]) {
const result = await RoleModel.updateMany({ roleId: { $in: members } }, { hasGuild: false, guildCode: "", guildName: "" }).lean();
return result;
}
public static async updateGuildName(guildCode: string, guildName: string) {
const result = await RoleModel.updateMany({ guildCode }, { $set: { guildName } }).lean();
return result;
}
// 退出公会
public static async quitGuild(roleId: string, now: number) {
const result: RoleType = await RoleModel.findOneAndUpdate({ roleId, hasGuild: true }, { hasGuild: false, guildCode: "", guildName: "", quitGuildTime: now }, { new: true }).lean();
return result;
}
// 增加好友数量
public static async increaseFriendCnt(roleId: string, inc: number, max?: number) {
let condition = { roleId };
if (max) {
condition['friendCnt'] = { $lte: max - inc };
}
const result: RoleType = await RoleModel.findOneAndUpdate(condition, { $inc: { friendCnt: inc } }, { new: true }).lean({ getters: true, virtuals: true });
return result;
}
// 增加好友申请数量
public static async increaseFriendApplyCnt(roleId: string, inc: number, max: number) {
const result: RoleType = await RoleModel.findOneAndUpdate({ roleId, recFrdApplyCnt: { $lte: max - inc } }, { $inc: { recFrdApplyCnt: inc } }, { new: true }).lean({ getters: true, virtuals: true });
return result;
}
// 增加黑名单数量
public static async increaseBlockCnt(roleId: string, blockCnt: number, friendCnt: number, maxBlockCnt: number) {
const result: RoleType = await RoleModel.findOneAndUpdate({ roleId, blockCnt: { $lte: maxBlockCnt - blockCnt } }, { $inc: { blockCnt, friendCnt } }, { new: true }).lean({ getters: true, virtuals: true });
return result;
}
public static async updatedRoleMailAt(roleId: string, updatedMailAt: number, lean = true) {
const result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $set: { updatedMailAt } }, { new: true }).lean(lean);
return result;
}
public static async addFigure(roleId: string, id: number, figure: Figure) {
const result: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $pull: { heads: { id: id }, $push: { heads: figure } } }, { new: true }).lean();
return result
}
public static async checkName(roleName: string, serverId: number) {
if(!roleName) return true; // 不可起空字符串
const res = await RoleModel.exists({ roleName, serverId });
return res;
}
// 获取战力在中位数的玩家
public static async getActivePlayers(serverId: number) {
let yesterday = <Date>getTimeFunD().getBeforeDayWithHour(1);
const roles: RoleType[] = await RoleModel.find({ serverId, updatedAt: { $gte: yesterday } })
.select('roleId ce topLineup topLineupCe guildCode hasGuild')
.sort({ ce: -1 }).lean();
return roles
}
public static async receiveRankReward(roleId: string, ids: number[]) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $push: { rankReceived: { $each: ids } } }, { new: true }).lean();
return role;
}
// 装备上限
public static async increaseJewel(roleId: string, count: number) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { jewelCount: count } }, { new: true }).lean();
return role;
}
// 支付记录
public static async increaseTotalPay(roleId: string, price: number) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $inc: { totalPay: price } }, { new: true }).lean();
return role;
}
// 保存新手引导记录
public static async saveGuide(roleId: string, ids: number[]) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $addToSet: { guide: { $each: ids } } }, { new: true }).lean();
return role;
}
// 用于远征匹配
public static async findByCeScale(min: number, max: number) {
const result: RoleType[] = await RoleModel.find({ topLineupCe: { $lte: max, $gte: min } })
.populate('topLineup.hero')
.sort({ updatedAt: -1 }).limit(100).lean({ getters: true, virtuals: true });
return result;
}
public static async findByUidAndSetMark(uid: number, serverId: number, select?: string, getters = false) {
const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, { $set: { sdkMark: true } }, { new: true }).select(select).lean({ getters, virtuals: true });
return role;
}
// 购买永久月卡
public static async buyForeverTicket(roleId: string) {
const role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $set: { vipStartTime: Date.now(), isVip: true } }, { new: true }).lean();
return role;
}
private static getSearchObj(form: SearchRoleParam) {
let searchObj = {};
if(form.uid) searchObj['userInfo.uid'] = form.uid;
if(form.roleId) searchObj['roleId'] = form.roleId;
if(form.roleName) searchObj['roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
if(form.tel) searchObj['userInfo.tel'] = form.tel;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchRoleParam = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
if(sortField && sortOrder) {
if(sortOrder == 'ascend') {
sort[sortField] = 1;
} else if (sortOrder == 'descend') {
sort[sortField] = -1;
}
}
const result: RoleType[] = await RoleModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchRoleParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await RoleModel.count(searchObj);
return result;
}
public static async receivedBox(roleId: string, ids: number[]) {
let rec: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { $push: { receivedBox: { $each: ids } } }, { new: true }).lean();
return rec;
}
}
export const RoleModel = getModelForClass(Role);
export interface RoleType extends Pick<DocumentType<Role>, keyof Role> { };
export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项
export type RoleInc = Partial<Pick<DocumentType<Role>, 'heroNum' | 'blockCnt' | 'friendCnt' | 'gold' | 'coin' | 'ce' | 'renameCnt'>>;
// 初始化
function getInitialTeraph() {
let teraphs = new Array<Teraph>();
for (let i = ROLE_TERAPH.START; i <= ROLE_TERAPH.END; i++) {
let p = new Teraph(i);
teraphs.push(p);
}
return teraphs;
}
function getDefualtFigure(type: string) {
let figures = new Array<Figure>();
if (type == 'head') {
let figure = new Figure(dicParam.EXTERIOR.EXTERIOR_FACE, true, null, true);
figures.push(figure);
} else if (type == 'frame') {
let figure = new Figure(dicParam.EXTERIOR.EXTERIOR_FACECASE, true, null, true);
figures.push(figure);
} else if (type == 'spine') {
let figure = new Figure(dicParam.EXTERIOR.EXTERIOR_APPEARANCE, true, null, true);
figures.push(figure);
}
return figures;
}