✨ feat(gvg): 准备期:千机阁以及获取物品
This commit is contained in:
@@ -9,6 +9,8 @@ class Member {
|
||||
@prop({ required: true })
|
||||
roleId: string;
|
||||
@prop({ required: true })
|
||||
guildCode: string;
|
||||
@prop({ required: true })
|
||||
auth: number;
|
||||
}
|
||||
|
||||
@@ -69,7 +71,7 @@ export default class GVGLeague extends BaseModel {
|
||||
const doc = new GVGLeagueModel();
|
||||
const leagueCode = genCode(6);
|
||||
let _leader = <RoleType>leader;
|
||||
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.LEADER: LEAGUE_AUTH.MEMBER }));
|
||||
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.LEADER: LEAGUE_AUTH.MEMBER, guildCode: code }));
|
||||
const update = Object.assign(doc.toJSON(), { guildCodes: [code], name: `${name}联军`, guildCnt: 1, memberCnt, isAuto: true, leagueCe: guildCe, leader: _leader?._id, members: _members, leagueCode }, params);
|
||||
delete update._id;
|
||||
|
||||
@@ -83,6 +85,7 @@ export default class GVGLeague extends BaseModel {
|
||||
public static async findLeagueByGuild(guildCode: string) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOne({ guildCodes: guildCode, status: 1 })
|
||||
.populate('leader', { roleId: 1, roleName: 1, head: 1, frame: 1, spine: 1, lv: 1, quitTime: 1, ce: 1, title: 1, serverId: 1, _id: 0 }, 'Role')
|
||||
.select('+serverId')
|
||||
.lean();
|
||||
return league
|
||||
}
|
||||
@@ -118,7 +121,7 @@ export default class GVGLeague extends BaseModel {
|
||||
public static async joinGuild(leagueCode: string, guild: GuildType) {
|
||||
const { code, memberCnt, leader, guildCe, members } = guild;
|
||||
let _leader = <RoleType>leader;
|
||||
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.SUB_LEADER: LEAGUE_AUTH.MEMBER }));
|
||||
let _members = members.map(roleId => ({ roleId, auth: _leader.roleId == roleId? LEAGUE_AUTH.SUB_LEADER: LEAGUE_AUTH.MEMBER, guildCode: code }));
|
||||
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 },
|
||||
{ $push: { guildCodes: code, members: { $each: _members } }, $inc: { guildCnt: 1, memberCnt: memberCnt, leagueCe: guildCe }
|
||||
@@ -167,8 +170,8 @@ export default class GVGLeague extends BaseModel {
|
||||
return league;
|
||||
}
|
||||
|
||||
public static async joinMember(leagueCode: string, roleId: string, ce: number) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $push: { members: { roleId, auth: LEAGUE_AUTH.MEMBER } }, $inc: { memberCnt: 1, leagueCe: ce } }, { new: true }).lean();
|
||||
public static async joinMember(leagueCode: string, roleId: string, guildCode: string, ce: number) {
|
||||
const league: GVGLeagueType = await GVGLeagueModel.findOneAndUpdate({ leagueCode, status: 1 }, { $push: { members: { roleId, auth: LEAGUE_AUTH.MEMBER, guildCode } }, $inc: { memberCnt: 1, leagueCe: ce } }, { new: true }).lean();
|
||||
return league;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { LEAGUE_JOB } from '../consts';
|
||||
import { GVG } from '../pubUtils/dicParam';
|
||||
|
||||
class Tech {
|
||||
export class Tech {
|
||||
@prop({ required: true, default: 0 })
|
||||
id: number;
|
||||
@prop({ required: true, default: 0 })
|
||||
progress: number; // 贡献
|
||||
@prop({ required: true, default: 0 })
|
||||
status: number; // 0-已解锁 1-已激活
|
||||
maxProgress: number; // 贡献
|
||||
|
||||
constructor(id: number, maxProgress: number) {
|
||||
this.id = id;
|
||||
this.progress = 0;
|
||||
this.maxProgress = maxProgress;
|
||||
}
|
||||
}
|
||||
|
||||
class DonateRec {
|
||||
@@ -29,6 +36,13 @@ class Resource {
|
||||
wood: number; // 木堆
|
||||
}
|
||||
|
||||
class GuildActive {
|
||||
@prop({ required: true, default: '' })
|
||||
guildCode: string; // 军团
|
||||
@prop({ required: true, default: 0 })
|
||||
active: number;
|
||||
}
|
||||
|
||||
@index({ leagueCode: 1, configId: 1 })
|
||||
export default class GVGLeaguePrepare extends BaseModel {
|
||||
|
||||
@@ -50,8 +64,14 @@ export default class GVGLeaguePrepare extends BaseModel {
|
||||
@prop({ required: true, default: 0 })
|
||||
fighterCnt: number; // 选择外政人数
|
||||
|
||||
@prop({ required: true, default: [], type: Number, _id: false })
|
||||
activeTech: number[]; // 已激活完了的
|
||||
|
||||
@prop({ required: true, default: [], type: Tech, _id: false })
|
||||
tech: Tech[]; // 千机阁
|
||||
techQueue: Tech[]; // 千机阁
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
techQueueCnt: number; // 千机阁队列数量
|
||||
|
||||
@prop({ required: true, default: [], type: DonateRec, _id: false })
|
||||
donateRec: DonateRec[]; // 捐献记录
|
||||
@@ -59,6 +79,9 @@ export default class GVGLeaguePrepare extends BaseModel {
|
||||
@prop({ required: true, default: {food: 0, mineral: 0, wood: 0}, type: Resource, _id: false })
|
||||
resources: Resource
|
||||
|
||||
@prop({ required: true, default: [], type: GuildActive, _id: false })
|
||||
guildActive: GuildActive[]; // 军团活跃
|
||||
|
||||
public static async initData(configId: number, leagueCode: string, maxMemberCnt: number) {
|
||||
const doc = new GVGLeaguePrepareModel();
|
||||
const update = Object.assign(doc.toJSON(), { maxMemberCnt });
|
||||
@@ -83,6 +106,24 @@ export default class GVGLeaguePrepare extends BaseModel {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static async unlockTech(configId: number, leagueCode: string, techId: number, maxProgress: number) {
|
||||
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({
|
||||
configId, leagueCode, techQueueCnt: { $lt: GVG.GVG_LEAGUE_TECH_LIST } }, { $push: { techQueue: new Tech(techId, maxProgress) }, $inc: { techQueueCnt: 1 } }, { new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async addProgress(configId: number, leagueCode: string, techId: number, addProgress: number) {
|
||||
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({
|
||||
configId, leagueCode, 'techQueue.id': techId }, { $inc: { 'techQueue.$.progress': addProgress } }, { new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async activate(configId: number, leagueCode: string, techId: number) {
|
||||
const result: GVGLeaguePrepareType = await GVGLeaguePrepareModel.findOneAndUpdate({
|
||||
configId, leagueCode }, { $push: { activeTech: techId}, $pull: { techQueue: { id: techId } } }, { new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGLeaguePrepareModel = getModelForClass(GVGLeaguePrepare);
|
||||
|
||||
62
shared/db/GVGUserDailyData.ts
Normal file
62
shared/db/GVGUserDailyData.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { getZeroPoint } from '../pubUtils/timeUtil';
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, time: 1 })
|
||||
export default class GVGUserDailyData extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
roleId: string; // 玩家
|
||||
|
||||
@prop({ required: true })
|
||||
configId: number; // 赛季信息
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 所属联军
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
job: number; // 职能 1-贤臣 2-猛将
|
||||
|
||||
// 贡献
|
||||
@prop({ required: true, default: 0 })
|
||||
food: number; // 粮食
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
mineral: number; // 矿物
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
wood: number; // 木材
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
score: number; // 据点积分
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number = 0; // 每天0点
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
hasGetTechActive: boolean; // 千机阁激活活跃是否获得
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
hasLogin: boolean; // 每日登录活跃是否获得
|
||||
|
||||
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
|
||||
const result: GVGUserDailyDataType = await GVGUserDailyDataModel.findOne({ configId, leagueCode, roleId, time: getZeroPoint() }).select('food mineral wood score').lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async checkGetTechActive(configId: number, leagueCode: string, roleId: string) {
|
||||
return await GVGUserDailyDataModel.exists({ configId, leagueCode, roleId, time: getZeroPoint(), hasGetTechActive: { $exists: true } });
|
||||
}
|
||||
|
||||
public static async setHasGetTechActive(configId: number, leagueCode: string, roleId: string) {
|
||||
const result: GVGUserDailyDataType = await GVGUserDailyDataModel.findOneAndUpdate({ configId, leagueCode, roleId, time: getZeroPoint() }, { hasGetTechActive: true }, { upsert: true, new: true }).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserDailyDataModel = getModelForClass(GVGUserDailyData);
|
||||
|
||||
export interface GVGUserDailyDataType extends Pick<DocumentType<GVGUserDailyData>, keyof GVGUserDailyData> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGUserDailyDataUpdate = Partial<GVGUserDailyDataType>; // 将所有字段变成可选项
|
||||
@@ -1,47 +0,0 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { nowSeconds } from '../pubUtils/timeUtil';
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, time: 1 })
|
||||
export default class GVGUserDailyDistribute extends BaseModel {
|
||||
|
||||
@prop({ required: true })
|
||||
roleId: string; // 玩家
|
||||
|
||||
@prop({ required: true })
|
||||
configId: number; // 赛季信息
|
||||
|
||||
@prop({ required: true })
|
||||
leagueCode: string; // 所属联军
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
job: number; // 职能 1-贤臣 2-猛将
|
||||
|
||||
// 贡献
|
||||
@prop({ required: true, default: 0 })
|
||||
food: number; // 粮食
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
mineral: number; // 矿物
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
wood: number; // 木材
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
score: number; // 据点积分
|
||||
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number = 0; // 据点积分
|
||||
|
||||
public static async findByRole(configId: number, leagueCode: string, roleId: string) {
|
||||
const result: GVGUserDailyDistributeType = await GVGUserDailyDistributeModel.findOne({ configId, leagueCode, roleId, time: nowSeconds() }).select('food mineral wood score').lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserDailyDistributeModel = getModelForClass(GVGUserDailyDistribute);
|
||||
|
||||
export interface GVGUserDailyDistributeType extends Pick<DocumentType<GVGUserDailyDistribute>, keyof GVGUserDailyDistribute> {
|
||||
id: number;
|
||||
};
|
||||
export type GVGUserDailyDistributeUpdate = Partial<GVGUserDailyDistributeType>; // 将所有字段变成可选项
|
||||
@@ -1,5 +1,6 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { nowSeconds } from '../pubUtils/timeUtil';
|
||||
|
||||
class ActiveRec {
|
||||
@prop({ required: true, default: 1 })
|
||||
@@ -8,6 +9,12 @@ class ActiveRec {
|
||||
count: number;
|
||||
@prop({ required: true, default: 0 })
|
||||
time: number;
|
||||
|
||||
constructor(id: number, count: number) {
|
||||
this.id = id;
|
||||
this.count = count;
|
||||
this.time = nowSeconds();
|
||||
}
|
||||
}
|
||||
|
||||
class Box {
|
||||
@@ -91,6 +98,11 @@ export default class GVGUserData extends BaseModel {
|
||||
const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, { $set: { job } }, { new: true, upsert: true}).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async addActive(configId: number, leagueCode: string, roleId: string, activeType: number, active: number) {
|
||||
const result: GVGUserDataType = await GVGUserDataModel.findOneAndUpdate({ configId, leagueCode, roleId }, { $inc: { active }, $push: { activeRec: new ActiveRec(activeType, active) } }, { new: true, upsert: true}).lean();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserDataModel = getModelForClass(GVGUserData);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import BaseModel from './BaseModel';
|
||||
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
|
||||
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
|
||||
import { nowSeconds } from '../pubUtils/timeUtil';
|
||||
import { RewardInter } from '../pubUtils/interface';
|
||||
|
||||
@index({ leagueCode: 1, roleId: 1, configId: 1, status: 1 })
|
||||
export default class GVGUserItem extends BaseModel {
|
||||
@@ -27,6 +28,26 @@ export default class GVGUserItem extends BaseModel {
|
||||
const result: GVGUserItemType[] = await GVGUserItemModel.find({ configId, leagueCode, roleId, expireTime: { $gte: nowSeconds() } }, { _id: 0 }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async increaseItem(configId: number, leagueCode: string, roleId: string, id: number, inc: number, expireTime: number) {
|
||||
const result: GVGUserItemType = await GVGUserItemModel.findOneAndUpdate({ configId, leagueCode, roleId, id, expireTime }, { $inc: { count: inc } }, { new: true, upsert: true }).lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findByRoleAndIds(configId: number, leagueCode: string, roleId: string, ids: number[]) {
|
||||
const result: GVGUserItemType[] = await GVGUserItemModel.find({ configId, leagueCode, roleId, expireTime: { $gte: nowSeconds() }, id: { $in: ids } }).select('id count').lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async decreaseItem(configId: number, leagueCode: string, roleId: string, items: RewardInter[]) {
|
||||
const result = await GVGUserItemModel.bulkWrite(items.map(({ id, count }) => {
|
||||
let filter = { configId, leagueCode, roleId, id, count: { $gte: count }, expireTime: { $gte: nowSeconds() } }
|
||||
console.log('#### filter', filter, )
|
||||
return { updateOne: { filter, update: { $inc: { count: -1 * count } } } }
|
||||
}));
|
||||
console.log(result.matchedCount, items.length)
|
||||
return result.matchedCount == items.length;
|
||||
}
|
||||
}
|
||||
|
||||
export const GVGUserItemModel = getModelForClass(GVGUserItem);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { GUILD_STRUCTURE, GUILD_STATUS, GUILD_PER_PAGE, GUILD_SELECT, REDIS_KEY,
|
||||
import { getZeroPoint, getZeroPointD, nowSeconds } from '../pubUtils/timeUtil';
|
||||
import { gameData } from '../pubUtils/data';
|
||||
import { SearchGuildParam } from '../domain/backEndField/search';
|
||||
import { GVG } from '../pubUtils/dicParam';
|
||||
|
||||
export class Structure {
|
||||
@prop({ required: true })
|
||||
@@ -325,21 +326,22 @@ export default class Guild extends BaseModel {
|
||||
}
|
||||
|
||||
public static async findGuildsForGVG(page: number, name: string, serverIds: number[]) {
|
||||
let query: any = { status: GUILD_STATUS.RUNNING, lv: { $gte: 3 }, leagueCode: '', serverId: { $in: serverIds } };
|
||||
let query: any = { status: GUILD_STATUS.RUNNING, lv: { $gte: GVG.GVG_ARMY_LEAGUE_TIME }, leagueCode: '', serverId: { $in: serverIds } };
|
||||
if(name) {
|
||||
query['name'] = { $regex: new RegExp(name, 'i') }
|
||||
}
|
||||
const result: GuildType[] = await GuildModel.find(query)
|
||||
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
|
||||
.skip((page - 1) * 30).limit(30)
|
||||
.select('+serverId')
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async findByCodes(codes: string[]) {
|
||||
const result: GuildType[] = await GuildModel.find({ status: GUILD_STATUS.RUNNING, code: { $in: codes } })
|
||||
.select('+serverId')
|
||||
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
|
||||
.select('+serverId')
|
||||
.lean();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export default class LadderMatch extends BaseModel {
|
||||
if(defenseInfo.isRobot) {
|
||||
let atkLadderMatch = await LadderMatchModel.findOne({ roleId: attackInfo.roleId }).lean();
|
||||
if(isSuccess && atkLadderMatch && (atkLadderMatch.rank == 0 || atkLadderMatch.rank > defenseInfo.oldRank)) {
|
||||
newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defenseInfo.oldRank, oldRank: atkLadderMatch.rank } }, { new: true }).lean();
|
||||
newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defenseInfo.oldRank, oldRank: atkLadderMatch.rank } }, { new: true, session }).lean();
|
||||
isChange = true;
|
||||
endTime = Date.now();
|
||||
} else {
|
||||
@@ -129,8 +129,8 @@ export default class LadderMatch extends BaseModel {
|
||||
let atkLadderMatch = await LadderMatchModel.findOne({ roleId: attackInfo.roleId }).lean();
|
||||
let defLadderMatch = await LadderMatchModel.findOne({ roleId: defenseInfo.roleId }).lean();
|
||||
if(isSuccess && atkLadderMatch && defLadderMatch && (atkLadderMatch.rank == 0 || atkLadderMatch.rank > defLadderMatch.rank)) {
|
||||
newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defLadderMatch.rank, oldRank: atkLadderMatch.rank } }, { new: true }).lean();
|
||||
newDefLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defenseInfo.roleId }, { $set: { rank: atkLadderMatch.rank, oldRank: defLadderMatch.rank } }, { new: true }).lean();
|
||||
newAtkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: attackInfo.roleId }, { $set: { rank: defLadderMatch.rank, oldRank: atkLadderMatch.rank } }, { new: true, session }).lean();
|
||||
newDefLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defenseInfo.roleId }, { $set: { rank: atkLadderMatch.rank, oldRank: defLadderMatch.rank } }, { new: true, session }).lean();
|
||||
isChange = true;
|
||||
endTime = Date.now();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user