diff --git a/README.md b/README.md index 9f3a882e7..2c45cb9c1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ `cd game-server && node tsrun.js` ## 运行 web-server -`cd web-server && node app` +`cd web-server && node dev` cd 到 web-server下面 `npm run stop && npm run tsc && npm run start` @@ -28,3 +28,12 @@ cd 到 web-server下面 `pm2 start ./dist/app.js --name="activity-server-2" -x -- env=dev id=activity-server-2 host=172.26.145.171 port=9061 serverType=activity` `pm2 start ./dist/app.js --name="connector-server-4" -x -- env=alpha id=connector-server-4 host=172.26.145.171 port=9062 clientHost=121.89.211.172 clientPort=3050 serverType=connector frontend=true` 8.主机部分的server.ts内的server如果需要做rpc remote,host需要从127.0.0.1改为私网地址 + + +--- + +web-server + +`cd web-server` + +`HOME=/root node node_modules/.bin/egg-bin dev` \ No newline at end of file diff --git a/game-server/app.ts b/game-server/app.ts index 480807e49..c70501370 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -1,7 +1,7 @@ require('xprofiler').start({ log_dir: '/zyz_logs/xprofiler', }); -import { COM_TEAM_STATUS, STATUS } from './app/consts'; +import { COM_TEAM_STATUS, STATUS } from '@consts'; import { createTcpAcceptor, createTcpMailBox, @@ -19,17 +19,17 @@ import { preload } from './preload'; import { globalFilter } from'./app/servers/connector/filter/global'; import { guildAuthFilter } from'./app/servers/guild/filter/guildAuthFilter'; import { tokenFilter } from'./app/servers/gm/filter/tokenFilter'; -import { connectRedis } from './app/pubUtils/redis'; +import { connectRedis } from '@pubUtils/redis'; import * as timeTaskService from './app/services/timeTaskService'; import * as redlockCacheService from './app/services/redlockCacheService'; import * as redLockService from './app/services/redLockService'; // TODO 需要整理。 import _pinus = require('pinus'); import { updateTeamStatus } from './app/services/battle/comBattleService'; -import { resResult, genCode } from './app/pubUtils/util'; +import { resResult, genCode } from '@pubUtils/util'; import { errlogger, infologger, loadLogger } from './app/util/logger'; import { connectThinkingData, getTire } from './app/services/sdkService'; -import { loadSubDb, loadGmDb } from './app/db'; +import { loadSubDb, loadGmDb } from '@db'; import { loadActivities } from './app/services/memoryCache/activityData'; import { checkAndSetApiIsClose } from './app/services/chatService'; import { initGuildActivityIndexInPinus, resetJoinWoodenHorse } from './app/services/guildActivity/guildActivityService'; @@ -307,6 +307,7 @@ function setupFilters(app: _pinus.Application) { app.filter(new pinus.filters.time()); app.filter(new pinus.filters.timeout()); + // @ts-ignore app.filter(globalFilter(app)); app.globalAfter((err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, cb: HandlerCallback) => { if (err) infologger.debug(err); diff --git a/game-server/app/components/EvalComponent.ts b/game-server/app/components/EvalComponent.ts index 2099f155e..3923fb192 100644 --- a/game-server/app/components/EvalComponent.ts +++ b/game-server/app/components/EvalComponent.ts @@ -1,43 +1,43 @@ -import { Application, IComponent } from "pinus"; - -export class EvalComponent implements IComponent { - name = "EvalComponent"; - app: Application; - - constructor(app: Application) { - this.app = app; - this.app.set(this.name, this); - } - - start(cb: () => void) { - console.log("EvalComponent start", this.app.getServerId()); - cb(); - } - - stop(force: boolean, cb: () => void) { - console.log("EvalComponent stop", force, this.app.getServerId()); - cb(); - } - - eval(script: string, cb: (err, res?) => void) { - try { - // 检查 script 的开头是否由 MagicCode 开头 - const MagicCode = "BantuYJZ23:"; - if (!script.startsWith(MagicCode)) { - // 没有权限 - cb("auth failed"); - return; - } - // 去掉 MagicCode,substr 已经不被支持 - const code = script.slice(MagicCode.length); - - // ! 执行代码 - const result = eval(code); - cb(null, result); - } catch (error) { - console.log("EvalComponent eval", this.app.getServerId(), error) - cb(error); - return; - } - } -} +import { Application, IComponent } from "pinus"; + +export class EvalComponent implements IComponent { + name = "EvalComponent"; + app: Application; + + constructor(app: Application) { + this.app = app; + this.app.set(this.name, this); + } + + start(cb: () => void) { + console.log("EvalComponent start", this.app.getServerId()); + cb(); + } + + stop(force: boolean, cb: () => void) { + console.log("EvalComponent stop", force, this.app.getServerId()); + cb(); + } + + eval(script: string, cb: (err, res?) => void) { + try { + // 检查 script 的开头是否由 MagicCode 开头 + const MagicCode = "BantuYJZ23:"; + if (!script.startsWith(MagicCode)) { + // 没有权限 + cb("auth failed"); + return; + } + // 去掉 MagicCode,substr 已经不被支持 + const code = script.slice(MagicCode.length); + + // ! 执行代码 + const result = eval(code); + cb(null, result); + } catch (error) { + console.log("EvalComponent eval", this.app.getServerId(), error) + cb(error); + return; + } + } +} diff --git a/game-server/app/components/UpdateComponent.ts b/game-server/app/components/UpdateComponent.ts index 254492598..e9a15b5b3 100644 --- a/game-server/app/components/UpdateComponent.ts +++ b/game-server/app/components/UpdateComponent.ts @@ -1,49 +1,49 @@ -import { Application, IComponent, manualReloadCrons, manualReloadHandlers, manualReloadRemoters } from "pinus"; - -export class UpdateComponent implements IComponent { - name = "UpdateComponent"; - app: Application; - - constructor(app: Application) { - this.app = app; - this.app.set(this.name, this); - } - - start(cb: () => void) { - console.log("UpdateComponent start", this.app.getServerId()); - cb(); - } - - stop(force: boolean, cb: () => void) { - console.log("UpdateComponent stop", force, this.app.getServerId()); - cb(); - } - - hotupdate(files: string, cb: (err, res?) => void) { - try { - const filelist = files.split(","); - for (let i = 0; i < filelist.length; i++) { - const file = this.app.getBase() + filelist[i]; - if (!file || !require.cache[file]) { - console.log("UpdateComponent hotupdate", this.app.getServerId(), "file not exist", file); - cb("file not exist"); - return; - } - } - for (let i = 0; i < filelist.length; i++) { - const file = this.app.getBase() + filelist[i]; - delete require.cache[file]; - console.log("UpdateComponent hotupdate", this.app.getServerId(), file) - } - manualReloadHandlers(this.app); - manualReloadRemoters(this.app); - manualReloadCrons(this.app); - cb(null, "success"); - } catch (error) { - console.log("UpdateComponent hotupdate", this.app.getServerId(), error) - cb(error); - return; - } - - } -} \ No newline at end of file +import { Application, IComponent, manualReloadCrons, manualReloadHandlers, manualReloadRemoters } from "pinus"; + +export class UpdateComponent implements IComponent { + name = "UpdateComponent"; + app: Application; + + constructor(app: Application) { + this.app = app; + this.app.set(this.name, this); + } + + start(cb: () => void) { + console.log("UpdateComponent start", this.app.getServerId()); + cb(); + } + + stop(force: boolean, cb: () => void) { + console.log("UpdateComponent stop", force, this.app.getServerId()); + cb(); + } + + hotupdate(files: string, cb: (err, res?) => void) { + try { + const filelist = files.split(","); + for (let i = 0; i < filelist.length; i++) { + const file = this.app.getBase() + filelist[i]; + if (!file || !require.cache[file]) { + console.log("UpdateComponent hotupdate", this.app.getServerId(), "file not exist", file); + cb("file not exist"); + return; + } + } + for (let i = 0; i < filelist.length; i++) { + const file = this.app.getBase() + filelist[i]; + delete require.cache[file]; + console.log("UpdateComponent hotupdate", this.app.getServerId(), file) + } + manualReloadHandlers(this.app); + manualReloadRemoters(this.app); + manualReloadCrons(this.app); + cb(null, "success"); + } catch (error) { + console.log("UpdateComponent hotupdate", this.app.getServerId(), error) + cb(error); + return; + } + + } +} diff --git a/game-server/app/modules/UsrAdmin.ts b/game-server/app/modules/UsrAdmin.ts index 6fac3f860..b91d27431 100644 --- a/game-server/app/modules/UsrAdmin.ts +++ b/game-server/app/modules/UsrAdmin.ts @@ -1,76 +1,76 @@ -import { Application, IModule, MonitorCallback, MasterCallback, MonitorAgent, MasterAgent } from "pinus"; - - -export class UsrAdminModule implements IModule { - app: Application; - root: string; - - static moduleId = 'UsrAdmin'; - - constructor(opts: { app: Application, path: string }) { - this.app = opts.app; - this.root = opts.path; - } - - masterHandler(agent: MasterAgent, msg: any, cb: MasterCallback) { - console.log("enter masterHandler", msg); - } - - monitorHandler(agent: MonitorAgent, msg: { action: string, script: string, serverId: string }, cb: MonitorCallback) { - console.log("enter monitorHandler", msg); - if (['master'].includes(this.app.getServerType())) { - console.log('scripts module can not be loaded on master'); - return; - } - - switch (msg.action) { - case 'hotupdate': - this.app.get('UpdateComponent').hotupdate(msg.script, (err, res) => { - if (err) { - console.log("hotupdate error", err); - cb(err); - return; - } - console.log("hotupdate success", res); - cb(null, res); - }); - break; - case 'eval': - this.app.get('EvalComponent').eval(msg.script, (err, res) => { - if (err) { - console.log("eval error", err); - cb(err); - return; - } - console.log("eval success", res); - cb(null, res); - }); - break; - default: - break; - } - } - - clientHandler(agent: MasterAgent, msg: { action: string, script: string, serverId: string }, cb: MasterCallback) { - const { action, serverId } = msg; - switch (action) { - case 'hotupdate': - agent.notifyAll(UsrAdminModule.moduleId, msg); - cb(null, 'success notifyAll servers'); - break; - case 'eval': - agent.request(serverId, UsrAdminModule.moduleId, msg, (err, res) => { - if (err) { - console.log("eval error", err); - cb(err, res); - return; - } - console.log("eval success", res); - cb(null, res); - }); - break; - default: - break; - } - } -} +import { Application, IModule, MonitorCallback, MasterCallback, MonitorAgent, MasterAgent } from "pinus"; + + +export class UsrAdminModule implements IModule { + app: Application; + root: string; + + static moduleId = 'UsrAdmin'; + + constructor(opts: { app: Application, path: string }) { + this.app = opts.app; + this.root = opts.path; + } + + masterHandler(agent: MasterAgent, msg: any, cb: MasterCallback) { + console.log("enter masterHandler", msg); + } + + monitorHandler(agent: MonitorAgent, msg: { action: string, script: string, serverId: string }, cb: MonitorCallback) { + console.log("enter monitorHandler", msg); + if (['master'].includes(this.app.getServerType())) { + console.log('scripts module can not be loaded on master'); + return; + } + + switch (msg.action) { + case 'hotupdate': + this.app.get('UpdateComponent').hotupdate(msg.script, (err, res) => { + if (err) { + console.log("hotupdate error", err); + cb(err); + return; + } + console.log("hotupdate success", res); + cb(null, res); + }); + break; + case 'eval': + this.app.get('EvalComponent').eval(msg.script, (err, res) => { + if (err) { + console.log("eval error", err); + cb(err); + return; + } + console.log("eval success", res); + cb(null, res); + }); + break; + default: + break; + } + } + + clientHandler(agent: MasterAgent, msg: { action: string, script: string, serverId: string }, cb: MasterCallback) { + const { action, serverId } = msg; + switch (action) { + case 'hotupdate': + agent.notifyAll(UsrAdminModule.moduleId, msg); + cb(null, 'success notifyAll servers'); + break; + case 'eval': + agent.request(serverId, UsrAdminModule.moduleId, msg, (err, res) => { + if (err) { + console.log("eval error", err); + cb(err, res); + return; + } + console.log("eval success", res); + cb(null, res); + }); + break; + default: + break; + } + } +} diff --git a/game-server/app/servers/activity/handler/activityHandler.ts b/game-server/app/servers/activity/handler/activityHandler.ts index 1eccd4134..0a3211db8 100644 --- a/game-server/app/servers/activity/handler/activityHandler.ts +++ b/game-server/app/servers/activity/handler/activityHandler.ts @@ -1,118 +1,119 @@ -import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ENCRYPT_IV, ENCRYPT_KEY, STATUS, TASK_TYPE } from '../../../consts'; -import { ActivityGroupModel } from '../../../db/ActivityGroup'; -import { getActivitiesWithOrder, getActivity, getActivityById, getActivityByServerId, shouldReplace } from '../../../services/activity/activityService'; -import { ActivityModelType } from '../../../db/Activity'; -import { UserOrderModel } from '../../../db/UserOrder'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ActivityHandler(app); -} - -export class ActivityHandler { - constructor(private app: Application) { - } - - - /** - * @description 活动是否开启总接口 - * @param {{ }} msg - * @param {BackendSession} session - * @memberof ActivityHandler - */ - async getAllOpenActivity(msg: {}, session: BackendSession) { - - const { } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const uid: number = session.get('userid'); - const sid: string = session.get('sid'); - - let originActivities = await getActivityByServerId(serverId); - let maxIdByType = new Map(); // type => max - let activityById = new Map(); // id => activity - - for(let activity of originActivities) { - let playerActivityData = await getActivity(serverId, roleId, uid, guildCode, activity.activityId, activity.type); - if(!playerActivityData) continue; - - let shouldPush = true; - if(shouldReplace(playerActivityData.type)) { // 该类型只能有一个id,选最大的那个 - let max = maxIdByType.get(playerActivityData.type)||0; - if(playerActivityData.activityId > max) { - activityById.delete(max); - maxIdByType.set(playerActivityData.type, playerActivityData.activityId); - } else { - shouldPush = false; - } - } - if(shouldPush) activityById.set(activity.activityId, playerActivityData); - } - - let groups = await ActivityGroupModel.findByServerId(serverId); - let playerGroupArray = []; - for (let groupData of groups) { - let playerGroupActivityArray = []; - for (let activityId of groupData.activities) { - let playerActivityData = activityById.get(activityId); - if(playerActivityData) { - playerGroupActivityArray.push(playerActivityData); - } - } - if(playerGroupActivityArray.length > 0) - playerGroupArray.push({ - id: groupData.groupId, - type: groupData.type, - activities: playerGroupActivityArray - }); - console.log(`${roleId} 活动合集 groupId:${groupData.groupId}, 合集类型${groupData.type}, 一共${playerGroupActivityArray.length}个`) - } - - return resResult(STATUS.SUCCESS, { playerActivityArray: [], playerGroupArray }); - } - - async getActivitiesByOrder(msg: { localOrderID: string }, session: BackendSession) { - - const { localOrderID } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const uid = session.get('userid'); - - let orderInfo = await UserOrderModel.findOrder(localOrderID); - if (!orderInfo || orderInfo.roleId != roleId) { - return resResult(STATUS.NO_ORDER); - } - let activities: ActivityModelType[] = await getActivitiesWithOrder(orderInfo); - let result = []; - for(let activityData of activities) { - if (!activityData) continue; - - let playerActivityData = await getActivity(serverId, roleId, uid, guildCode, activityData.activityId, activityData.type); - if(playerActivityData) { - result.push(playerActivityData); - } - } - return resResult(STATUS.SUCCESS, { activities: result }); - } - - async debugActivityMemory(msg: {}, session: BackendSession) { - const { } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid: string = session.get('sid'); - - let activities = pinus.app.get('activities'); - let activityByType = pinus.app.get('activityByType'); - let activityByServer = pinus.app.get('activityByServer'); - let groupToServer = pinus.app.get('groupToServer'); - console.log('****** activities', activities); - console.log('****** activityByType', activityByType); - console.log('****** activityByServer', activityByServer); - console.log('****** groupToServer', groupToServer); - return resResult(STATUS.SUCCESS, { activities: [...activities], activityByType: [...activityByType], activityByServer: [...activityByServer], groupToServer: [...groupToServer] }); - } -} +import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ENCRYPT_IV, ENCRYPT_KEY, STATUS, TASK_TYPE } from '../../../consts'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { getActivitiesWithOrder, getActivity, getActivityById, getActivityByServerId, shouldReplace } from '../../../services/activity/activityService'; +import { ActivityModelType } from '@db/Activity'; +import { UserOrderModel } from '@db/UserOrder'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ActivityHandler(app); +} + +export class ActivityHandler { + constructor(private app: Application) { + } + + + /** + * @description 活动是否开启总接口 + * @param {{ }} msg + * @param {BackendSession} session + * @memberof ActivityHandler + */ + async getAllOpenActivity(msg: {}, session: BackendSession) { + + const { } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const uid: number = session.get('userid'); + const sid: string = session.get('sid'); + + let originActivities = await getActivityByServerId(serverId); + let maxIdByType = new Map(); // type => max + let activityById = new Map(); // id => activity + + for(let activity of originActivities) { + let playerActivityData = await getActivity(serverId, roleId, uid, guildCode, activity.activityId, activity.type); + if(!playerActivityData) continue; + + let shouldPush = true; + if(shouldReplace(playerActivityData.type)) { // 该类型只能有一个id,选最大的那个 + let max = maxIdByType.get(playerActivityData.type)||0; + if(playerActivityData.activityId > max) { + activityById.delete(max); + maxIdByType.set(playerActivityData.type, playerActivityData.activityId); + } else { + shouldPush = false; + } + } + if(shouldPush) activityById.set(activity.activityId, playerActivityData); + } + + let groups = await ActivityGroupModel.findByServerId(serverId); + let playerGroupArray = []; + for (let groupData of groups) { + let playerGroupActivityArray = []; + for (let activityId of groupData.activities) { + let playerActivityData = activityById.get(activityId); + if(playerActivityData) { + playerGroupActivityArray.push(playerActivityData); + } + } + if(playerGroupActivityArray.length > 0) + playerGroupArray.push({ + id: groupData.groupId, + type: groupData.type, + activities: playerGroupActivityArray + }); + console.log(`${roleId} 活动合集 groupId:${groupData.groupId}, 合集类型${groupData.type}, 一共${playerGroupActivityArray.length}个`) + } + + return resResult(STATUS.SUCCESS, { playerActivityArray: [], playerGroupArray }); + } + + async getActivitiesByOrder(msg: { localOrderID: string }, session: BackendSession) { + + const { localOrderID } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const uid = session.get('userid'); + + let orderInfo = await UserOrderModel.findOrder(localOrderID); + if (!orderInfo || orderInfo.roleId != roleId) { + return resResult(STATUS.NO_ORDER); + } + let activities: ActivityModelType[] = await getActivitiesWithOrder(orderInfo); + let result = []; + for(let activityData of activities) { + if (!activityData) continue; + + let playerActivityData = await getActivity(serverId, roleId, uid, guildCode, activityData.activityId, activityData.type); + if(playerActivityData) { + result.push(playerActivityData); + } + } + return resResult(STATUS.SUCCESS, { activities: result }); + } + + async debugActivityMemory(msg: {}, session: BackendSession) { + const { } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid: string = session.get('sid'); + + let activities = pinus.app.get('activities'); + let activityByType = pinus.app.get('activityByType'); + let activityByServer = pinus.app.get('activityByServer'); + let groupToServer = pinus.app.get('groupToServer'); + console.log('****** activities', activities); + console.log('****** activityByType', activityByType); + console.log('****** activityByServer', activityByServer); + console.log('****** groupToServer', groupToServer); + return resResult(STATUS.SUCCESS, { activities: [...activities], activityByType: [...activityByType], activityByServer: [...activityByServer], groupToServer: [...groupToServer] }); + } +} + diff --git a/game-server/app/servers/activity/handler/activityMonopolyHandler.ts b/game-server/app/servers/activity/handler/activityMonopolyHandler.ts index fe409cf0f..d6fd43dcc 100644 --- a/game-server/app/servers/activity/handler/activityMonopolyHandler.ts +++ b/game-server/app/servers/activity/handler/activityMonopolyHandler.ts @@ -1,251 +1,252 @@ -import { Application, BackendSession, HandlerService } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { LAND_TYPE, STATUS, CURRENCY_TYPE, CURRENCY_BY_TYPE, BANK_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; -import { ActivityMonopolyModel, ActivityMonopolyModelType } from '../../../db/ActivityMonopoly'; -import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '../../../db/ActivityMonopolyLand'; -import { getPlayerMonopolyData, nextPosition } from '../../../services/activity/monopolyService'; -import { random } from 'underscore'; -import { handleCost } from '../../../services/role/rewardService'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getPlayerRefreshShopDataByRoundIndex } from '../../../services/activity/refreshShopService'; -import { ActivityRefreshShopModel } from '../../../db/ActivityRefreshShop'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ActivityMonopolyHandler(app); -} - -export class ActivityMonopolyHandler { - constructor(private app: Application) { - } - - - /** - * @description 获取大富翁活动数据 - * @param {{activityId: number }} msg - * @param {BackendSession} session - * @memberof ActivityMonopolyHandler - */ - async getMonopolyActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid: string = session.get('sid'); - - - let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - - /** - * @description 移动 - * @param {{activityId: number }} msg - * @param {BackendSession} session - * @memberof ActivityMonopolyHandler - */ - async move(msg: { activityId: number, step: number }, session: BackendSession) { - const { activityId, step } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid: string = session.get('sid'); - - const roleName = session.get('roleName'); - - let moveStep = 0; - if (step >= 1 && step <= 6) {//指定,天机骰子 - //检查资源 - let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.SPECIAL_DICE), count: 1 }], ITEM_CHANGE_REASON.MONOPOLY_MOVE); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - moveStep = step; - } else {//普通骰子 - //检查资源 - let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.NORMAL_DICE), count: 1 }], ITEM_CHANGE_REASON.MONOPOLY_MOVE); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - moveStep = random(5) + 1; - } - let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) - - let oldPosition = playerData.curPosition; - let newPosition = nextPosition(oldPosition, moveStep, playerData.list.length); - await ActivityMonopolyModel.updatePosition(serverId, activityId, roleId, newPosition, 1) - - let landData = playerData.findMonopolyItem(newPosition); - let landReward = null;//土地奖励 - let bankReward = null;//银行奖励 - if (landData && landData.landType == LAND_TYPE.BANK_NORMAL) { - //土地奖励 - if (landData.rewards.length > landData.stopCount) { - let reward = landData.rewards[landData.level - 1]; - let rewardArray = stringToRewardParam(reward) - landReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); - } - - //土地升级 - if (landData.rewards.length > landData.level) { - let newLevel = landData.level + 1; - await ActivityMonopolyLandModel.updateLevel(serverId, activityId, roleId, newPosition, newLevel) - landData.level = newLevel; - } - - //取钱 - if (landData.record.length > 0) { - let records = landData.record.filter(obj => { return obj.type == BANK_TYPE.OUT }); - if (records.length < landData.takeOutMax) { - let resource = landData.record[0].resource; - let rewardArray = stringToRewardParam(resource) - bankReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); - let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, newPosition, BANK_TYPE.OUT, resource); - landData.record = recordResult.record; - } - } - } else if (landData && ((landData.landType == LAND_TYPE.BANK_COIN) || (landData.landType == LAND_TYPE.BANK_GOLD))) { - //取钱 - if (landData.record.length > 0) { - let records = landData.record.filter(obj => { return obj.type == BANK_TYPE.OUT }); - if (records.length < landData.takeOutMax) { - let resource = landData.record[0].resource; - let rewardArray = stringToRewardParam(resource) - bankReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); - let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, newPosition, BANK_TYPE.OUT, resource); - landData.record = recordResult.record; - } - } - } - await ActivityMonopolyLandModel.updateStopCount(serverId, activityId, roleId, newPosition); - landData.stopCount += 1; - return resResult(STATUS.SUCCESS, { landReward, bankReward, landData, moveStep, newPosition, roundIndex: playerData.roundIndex + 1, }); - } - - /** - * @description 存钱 - * @param {{activityId: number ,addCount: number}} msg - * @param {BackendSession} session - * @memberof ActivityMonopolyHandler - */ - async bank(msg: { activityId: number, addCount: number }, session: BackendSession) { - const { activityId, addCount } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) - let curPosition = playerData.curPosition; - if (curPosition == 0) { - return resResult(STATUS.MONOPOLY_LAND_TYPE_ERROR); - } - let landData = playerData.findMonopolyItem(curPosition); - if (landData.landType != LAND_TYPE.BANK_NORMAL - && landData.landType != LAND_TYPE.BANK_COIN - && landData.landType != LAND_TYPE.BANK_GOLD) { - return resResult(STATUS.MONOPOLY_LAND_TYPE_ERROR); - } - if (landData.record.length != 0) { - return resResult(STATUS.MONOPOLY_BANK); - } - if (addCount > landData.saveMax) { - return resResult(STATUS.MONOPOLY_BANK_SAVE_MAX); - } - - let resrouseStr = ''; - if (landData.landType == LAND_TYPE.BANK_COIN - || landData.landType == LAND_TYPE.BANK_NORMAL) { - resrouseStr = `${ACTIVITY_RESOURCES_TYPE.GOODS}&${CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN)}&${addCount}` - //检查资源 - let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: addCount }], ITEM_CHANGE_REASON.MONOPOLY_BANK); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - } else if (landData.landType == LAND_TYPE.BANK_GOLD) { - resrouseStr = `${ACTIVITY_RESOURCES_TYPE.GOODS}&${CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD)}&${addCount}` - //检查资源 - let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: addCount }], ITEM_CHANGE_REASON.MONOPOLY_BANK); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - } - - let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, curPosition, BANK_TYPE.IN, resrouseStr); - landData.record = recordResult.record; - return resResult(STATUS.SUCCESS, { landData }); - - } - - - /** - * @description 获取商店数据 - * @param {{ activityId:number, shopActivityId:number}} msg - * @param {BackendSession} session - * @memberof RefreshShopHandler - */ - async getRefreshShopActivity(msg: { activityId: number, shopActivityId: number }, session: BackendSession) { - const { activityId, shopActivityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityId, roleId); - let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(serverId, activityId, roleId, playerMonopolyData.curPosition); - let playerShopData = await getPlayerRefreshShopDataByRoundIndex(shopActivityId, serverId, roleId, playerLandData.stopCount); - if (!playerShopData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - return resResult(STATUS.SUCCESS, { playerShopData }); - } - - - /** - * @description 购买非RMB商品 - * @param {{ monopolyActivityId:number, shopActivityId: number, roundIndex: number, id: number, pageIndex: number}} msg - * @param {BackendSession} session - * @memberof RefreshShopHandler - */ - async buyGood(msg: { monopolyActivityId, shopActivityId: number, roundIndex: number, id: number, pageIndex: number }, session: BackendSession) { - const { monopolyActivityId, shopActivityId, roundIndex, id, pageIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, monopolyActivityId, roleId); - let playerData = await getPlayerMonopolyData(monopolyActivityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let landItem = playerData.findMonopolyItem(playerMonopolyData.curPosition) - if (landItem.stopCount > landItem.shoppingCountMax) { - return resResult(STATUS.SHOP_CLOSED); - } - let playerShopData = await getPlayerRefreshShopDataByRoundIndex(shopActivityId, serverId, roleId, landItem.stopCount); - if (!playerShopData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - if (playerShopData.roundIndex != roundIndex) { - return resResult(STATUS.ACTIVITY_EXPIRE); - } - - let item = playerShopData.findItem(id, pageIndex); - if (!item) { - return resResult(STATUS.ACTIVITY_ID_ERROR); - } - if (item.countMax > 0 && item.buyCount >= item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (item.price > 0) { - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - - //检查资源 - let consume = stringToConsumeParam(item.consume) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.MONOPOLY_BUY_GOODS); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let rewardArray = stringToRewardParam(item.reward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_BUY_GOODS); - - await ActivityRefreshShopModel.addRecord(shopActivityId, roleId, roundIndex, pageIndex, id, 1); - - item.buyCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { shopActivityId, monopolyActivityId, roundIndex, id }, - item: item - })); - } -} +import { Application, BackendSession, HandlerService } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { LAND_TYPE, STATUS, CURRENCY_TYPE, CURRENCY_BY_TYPE, BANK_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; +import { ActivityMonopolyModel, ActivityMonopolyModelType } from '@db/ActivityMonopoly'; +import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '@db/ActivityMonopolyLand'; +import { getPlayerMonopolyData, nextPosition } from '../../../services/activity/monopolyService'; +import { random } from 'underscore'; +import { handleCost } from '../../../services/role/rewardService'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getPlayerRefreshShopDataByRoundIndex } from '../../../services/activity/refreshShopService'; +import { ActivityRefreshShopModel } from '@db/ActivityRefreshShop'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ActivityMonopolyHandler(app); +} + +export class ActivityMonopolyHandler { + constructor(private app: Application) { + } + + + /** + * @description 获取大富翁活动数据 + * @param {{activityId: number }} msg + * @param {BackendSession} session + * @memberof ActivityMonopolyHandler + */ + async getMonopolyActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid: string = session.get('sid'); + + + let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + + /** + * @description 移动 + * @param {{activityId: number }} msg + * @param {BackendSession} session + * @memberof ActivityMonopolyHandler + */ + async move(msg: { activityId: number, step: number }, session: BackendSession) { + const { activityId, step } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid: string = session.get('sid'); + + const roleName = session.get('roleName'); + + let moveStep = 0; + if (step >= 1 && step <= 6) {//指定,天机骰子 + //检查资源 + let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.SPECIAL_DICE), count: 1 }], ITEM_CHANGE_REASON.MONOPOLY_MOVE); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + moveStep = step; + } else {//普通骰子 + //检查资源 + let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.NORMAL_DICE), count: 1 }], ITEM_CHANGE_REASON.MONOPOLY_MOVE); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + moveStep = random(5) + 1; + } + let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) + + let oldPosition = playerData.curPosition; + let newPosition = nextPosition(oldPosition, moveStep, playerData.list.length); + await ActivityMonopolyModel.updatePosition(serverId, activityId, roleId, newPosition, 1) + + let landData = playerData.findMonopolyItem(newPosition); + let landReward = null;//土地奖励 + let bankReward = null;//银行奖励 + if (landData && landData.landType == LAND_TYPE.BANK_NORMAL) { + //土地奖励 + if (landData.rewards.length > landData.stopCount) { + let reward = landData.rewards[landData.level - 1]; + let rewardArray = stringToRewardParam(reward) + landReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); + } + + //土地升级 + if (landData.rewards.length > landData.level) { + let newLevel = landData.level + 1; + await ActivityMonopolyLandModel.updateLevel(serverId, activityId, roleId, newPosition, newLevel) + landData.level = newLevel; + } + + //取钱 + if (landData.record.length > 0) { + let records = landData.record.filter(obj => { return obj.type == BANK_TYPE.OUT }); + if (records.length < landData.takeOutMax) { + let resource = landData.record[0].resource; + let rewardArray = stringToRewardParam(resource) + bankReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); + let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, newPosition, BANK_TYPE.OUT, resource); + landData.record = recordResult.record; + } + } + } else if (landData && ((landData.landType == LAND_TYPE.BANK_COIN) || (landData.landType == LAND_TYPE.BANK_GOLD))) { + //取钱 + if (landData.record.length > 0) { + let records = landData.record.filter(obj => { return obj.type == BANK_TYPE.OUT }); + if (records.length < landData.takeOutMax) { + let resource = landData.record[0].resource; + let rewardArray = stringToRewardParam(resource) + bankReward = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_MOVE); + let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, newPosition, BANK_TYPE.OUT, resource); + landData.record = recordResult.record; + } + } + } + await ActivityMonopolyLandModel.updateStopCount(serverId, activityId, roleId, newPosition); + landData.stopCount += 1; + return resResult(STATUS.SUCCESS, { landReward, bankReward, landData, moveStep, newPosition, roundIndex: playerData.roundIndex + 1, }); + } + + /** + * @description 存钱 + * @param {{activityId: number ,addCount: number}} msg + * @param {BackendSession} session + * @memberof ActivityMonopolyHandler + */ + async bank(msg: { activityId: number, addCount: number }, session: BackendSession) { + const { activityId, addCount } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerMonopolyData(activityId, serverId, roleId) + let curPosition = playerData.curPosition; + if (curPosition == 0) { + return resResult(STATUS.MONOPOLY_LAND_TYPE_ERROR); + } + let landData = playerData.findMonopolyItem(curPosition); + if (landData.landType != LAND_TYPE.BANK_NORMAL + && landData.landType != LAND_TYPE.BANK_COIN + && landData.landType != LAND_TYPE.BANK_GOLD) { + return resResult(STATUS.MONOPOLY_LAND_TYPE_ERROR); + } + if (landData.record.length != 0) { + return resResult(STATUS.MONOPOLY_BANK); + } + if (addCount > landData.saveMax) { + return resResult(STATUS.MONOPOLY_BANK_SAVE_MAX); + } + + let resrouseStr = ''; + if (landData.landType == LAND_TYPE.BANK_COIN + || landData.landType == LAND_TYPE.BANK_NORMAL) { + resrouseStr = `${ACTIVITY_RESOURCES_TYPE.GOODS}&${CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN)}&${addCount}` + //检查资源 + let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: addCount }], ITEM_CHANGE_REASON.MONOPOLY_BANK); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } else if (landData.landType == LAND_TYPE.BANK_GOLD) { + resrouseStr = `${ACTIVITY_RESOURCES_TYPE.GOODS}&${CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD)}&${addCount}` + //检查资源 + let consumeResult = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: addCount }], ITEM_CHANGE_REASON.MONOPOLY_BANK); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } + + let recordResult = await ActivityMonopolyLandModel.addRecord(serverId, activityId, roleId, curPosition, BANK_TYPE.IN, resrouseStr); + landData.record = recordResult.record; + return resResult(STATUS.SUCCESS, { landData }); + + } + + + /** + * @description 获取商店数据 + * @param {{ activityId:number, shopActivityId:number}} msg + * @param {BackendSession} session + * @memberof RefreshShopHandler + */ + async getRefreshShopActivity(msg: { activityId: number, shopActivityId: number }, session: BackendSession) { + const { activityId, shopActivityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityId, roleId); + let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(serverId, activityId, roleId, playerMonopolyData.curPosition); + let playerShopData = await getPlayerRefreshShopDataByRoundIndex(shopActivityId, serverId, roleId, playerLandData.stopCount); + if (!playerShopData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + return resResult(STATUS.SUCCESS, { playerShopData }); + } + + + /** + * @description 购买非RMB商品 + * @param {{ monopolyActivityId:number, shopActivityId: number, roundIndex: number, id: number, pageIndex: number}} msg + * @param {BackendSession} session + * @memberof RefreshShopHandler + */ + async buyGood(msg: { monopolyActivityId, shopActivityId: number, roundIndex: number, id: number, pageIndex: number }, session: BackendSession) { + const { monopolyActivityId, shopActivityId, roundIndex, id, pageIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, monopolyActivityId, roleId); + let playerData = await getPlayerMonopolyData(monopolyActivityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let landItem = playerData.findMonopolyItem(playerMonopolyData.curPosition) + if (landItem.stopCount > landItem.shoppingCountMax) { + return resResult(STATUS.SHOP_CLOSED); + } + let playerShopData = await getPlayerRefreshShopDataByRoundIndex(shopActivityId, serverId, roleId, landItem.stopCount); + if (!playerShopData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + if (playerShopData.roundIndex != roundIndex) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + + let item = playerShopData.findItem(id, pageIndex); + if (!item) { + return resResult(STATUS.ACTIVITY_ID_ERROR); + } + if (item.countMax > 0 && item.buyCount >= item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (item.price > 0) { + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + + //检查资源 + let consume = stringToConsumeParam(item.consume) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.MONOPOLY_BUY_GOODS); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let rewardArray = stringToRewardParam(item.reward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.MONOPOLY_BUY_GOODS); + + await ActivityRefreshShopModel.addRecord(shopActivityId, roleId, roundIndex, pageIndex, id, 1); + + item.buyCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { shopActivityId, monopolyActivityId, roundIndex, id }, + item: item + })); + } +} + diff --git a/game-server/app/servers/activity/handler/authorGachaHandler.ts b/game-server/app/servers/activity/handler/authorGachaHandler.ts index 268dd1669..492dbc09f 100644 --- a/game-server/app/servers/activity/handler/authorGachaHandler.ts +++ b/game-server/app/servers/activity/handler/authorGachaHandler.ts @@ -1,65 +1,66 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { getPlayerAuthorGachaDataShow } from "../../../services/activity/authorGachaService"; -import { parseGoodStrWithType, resResult } from "../../../pubUtils/util"; -import { ITEM_CHANGE_REASON, STATUS } from "../../../consts"; -import { AuthorGachaData } from "../../../domain/activityField/authorGachaField"; -import { addReward } from "../../../services/activity/giftPackageService"; -import { ActivityAuthorGachaRecModel } from "../../../db/AuthorGachaRec"; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new AuthorGachaHandler(app); -} - -export class AuthorGachaHandler { - constructor(private app: Application) { - - } - - /** - * 祈灵获取数据 - * @param msg - * @param session - * @returns - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - - const { activityId } = msg; - let playerData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { ...playerData }); - } - - - /** - * 祈灵获取奖励 - * @param msg - * @param session - * @returns - */ - async receiveBox(msg: { activityId: number, count: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - const { activityId, count } = msg; - let playerData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let box = playerData.box.find(cur => cur.count == count); - if (box == undefined || box.hasReceived) return resResult(STATUS.ACTIVITY_REWARDED); - box.hasReceived = true; - let rewards = parseGoodStrWithType(box.rewards); - - - let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.AUTHOR_GACHA_REWARD); - await ActivityAuthorGachaRecModel.record(serverId, activityId, playerData.roundIndex, roleId, count); - - return resResult(STATUS.SUCCESS, { goods: result.goods, curBox: playerData.box }) - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { getPlayerAuthorGachaDataShow } from "../../../services/activity/authorGachaService"; +import { parseGoodStrWithType, resResult } from "@pubUtils/util"; +import { ITEM_CHANGE_REASON, STATUS } from "../../../consts"; +import { AuthorGachaData } from "@domain/activityField/authorGachaField"; +import { addReward } from "../../../services/activity/giftPackageService"; +import { ActivityAuthorGachaRecModel } from "@db/AuthorGachaRec"; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new AuthorGachaHandler(app); +} + +export class AuthorGachaHandler { + constructor(private app: Application) { + + } + + /** + * 祈灵获取数据 + * @param msg + * @param session + * @returns + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + + const { activityId } = msg; + let playerData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { ...playerData }); + } + + + /** + * 祈灵获取奖励 + * @param msg + * @param session + * @returns + */ + async receiveBox(msg: { activityId: number, count: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + const { activityId, count } = msg; + let playerData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let box = playerData.box.find(cur => cur.count == count); + if (box == undefined || box.hasReceived) return resResult(STATUS.ACTIVITY_REWARDED); + box.hasReceived = true; + let rewards = parseGoodStrWithType(box.rewards); + + + let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.AUTHOR_GACHA_REWARD); + await ActivityAuthorGachaRecModel.record(serverId, activityId, playerData.roundIndex, roleId, count); + + return resResult(STATUS.SUCCESS, { goods: result.goods, curBox: playerData.box }) + } +} + diff --git a/game-server/app/servers/activity/handler/bindPhoneHandler.ts b/game-server/app/servers/activity/handler/bindPhoneHandler.ts index 9d96b932b..4167f9421 100644 --- a/game-server/app/servers/activity/handler/bindPhoneHandler.ts +++ b/game-server/app/servers/activity/handler/bindPhoneHandler.ts @@ -1,156 +1,157 @@ -import { Application, BackendSession, HandlerService } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { BIND_PHONE_STATUS, ITEM_CHANGE_REASON, PUSH_ROUTE, SNS_LINK_TYPE, STATUS } from '../../../consts'; -import { getPlayerDailyChallengesData } from '../../../services/activity/dailyChallengesService'; -import { DailyItem } from '../../../domain/activityField/dailyChallengesField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityDailyChallengesModel } from '../../../db/ActivityDailyChallenges'; -import { getBindPhoneData, getAllSnsLinkDataShow, getPublicAccountData } from '../../../services/activity/bindPhoneService'; -import { ActivityBindPhoneRewardModel } from '../../../db/ActivityBindPhoneReward'; -import { ActivityPublicAccountCodeModel } from '../../../db/ActivityPublicAccountCode'; -import { UserModel } from '../../../db/User'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new BindPhoneHandler(app); -} - -export class BindPhoneHandler { - constructor(private app: Application) { - } - - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const uid = session.get('userid'); - - let playerData = await getAllSnsLinkDataShow(activityId, roleId, serverId, uid); - return resResult(STATUS.SUCCESS, { - playerData - }) - } - - /************************绑定手机****************************/ - - /** - * @description 绑定手机数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof BindPhoneHandler - */ - async bind(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const uid = session.get('userid'); - - let playerData = await getBindPhoneData(activityId, roleId, serverId, uid); - let bindPhoneData = playerData?.bindPhone; - if(!bindPhoneData) return resResult(STATUS.ACTIVITY_ID_ERROR); - if(bindPhoneData.status != BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_HAS_BIND); - - await ActivityBindPhoneRewardModel.addRecord(activityId, uid, BIND_PHONE_STATUS.HAS_BIND, { roleId, roleName, serverId }); - - return resResult(STATUS.SUCCESS, { - activityId, - status: BIND_PHONE_STATUS.HAS_BIND - }); - } - - /** - * @description 领取奖励 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof BindPhoneHandler - */ - async receiveReward(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const uid = session.get('userid'); - - let playerData = await getBindPhoneData(activityId, roleId, serverId, uid); - let bindPhoneData = playerData?.bindPhone; - if(!bindPhoneData) return resResult(STATUS.ACTIVITY_ID_ERROR); - if(bindPhoneData.status == BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_BIND_ERR); - if(bindPhoneData.status == BIND_PHONE_STATUS.RECEIVED) return resResult(STATUS.ACTIVITY_BIND_RECEIVED); - - await ActivityBindPhoneRewardModel.addRecord(activityId, uid, BIND_PHONE_STATUS.RECEIVED, { roleId, roleName, serverId }); - let rewardArray = stringToRewardParam(bindPhoneData.rewards) - let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_BIND_PHONE); - - return resResult(STATUS.SUCCESS, { - activityId, - status: BIND_PHONE_STATUS.RECEIVED, - goods, addHeros - }); - } - - /** - * 领取公众号口令奖励 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof BindPhoneHandler - */ - async receiveGiftCode(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const uid = session.get('userid'); - - let user = await UserModel.findUserByUid(uid); - let playerData = await getPublicAccountData(activityId, roleId, serverId, user); - let data = playerData?.wxPublicAccount; - if(!data) return resResult(STATUS.ACTIVITY_ID_ERROR); - if(data.status == BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_PUBLIC_ACCOUNT_WAIT); - if(data.status == BIND_PHONE_STATUS.RECEIVED) return resResult(STATUS.ACTIVITY_PUBLIC_ACCOUNT_RECEIVED); - - await ActivityPublicAccountCodeModel.receive(activityId, user.channelId); - let rewardArray = stringToRewardParam(data.rewards) - let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_BIND_PHONE); - - return resResult(STATUS.SUCCESS, { - activityId, - status: BIND_PHONE_STATUS.RECEIVED, - goods, addHeros - }); - } - - /** - * 前往论坛,用于前往论坛任务 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof BindPhoneHandler - */ - async skipOutSide(msg: { activityId: number }, session: BackendSession) { - return resResult(STATUS.SUCCESS); - } - - /** - * 公众号设置成可以领取的状态 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof BindPhoneHandler - */ - async debugSetGiftCodeStatus(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const uid = session.get('userid'); - let user = await UserModel.findUserByUid(uid); - await ActivityPublicAccountCodeModel.findOneAndUpdate({ activityId, channelId: user.channelId }, { $set: { serverId, roleId, orderId: 'test', hasReceived: false } }, { new: true, upsert: true }).lean(); - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUBLIC_ACCOUNT_GIFT, { activityId, type: SNS_LINK_TYPE.WX_PUBLIC_ACCOUNT, status: BIND_PHONE_STATUS.HAS_BIND }); - - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { BIND_PHONE_STATUS, ITEM_CHANGE_REASON, PUSH_ROUTE, SNS_LINK_TYPE, STATUS } from '../../../consts'; +import { getPlayerDailyChallengesData } from '../../../services/activity/dailyChallengesService'; +import { DailyItem } from '@domain/activityField/dailyChallengesField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityDailyChallengesModel } from '@db/ActivityDailyChallenges'; +import { getBindPhoneData, getAllSnsLinkDataShow, getPublicAccountData } from '../../../services/activity/bindPhoneService'; +import { ActivityBindPhoneRewardModel } from '@db/ActivityBindPhoneReward'; +import { ActivityPublicAccountCodeModel } from '@db/ActivityPublicAccountCode'; +import { UserModel } from '@db/User'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new BindPhoneHandler(app); +} + +export class BindPhoneHandler { + constructor(private app: Application) { + } + + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const uid = session.get('userid'); + + let playerData = await getAllSnsLinkDataShow(activityId, roleId, serverId, uid); + return resResult(STATUS.SUCCESS, { + playerData + }) + } + + /************************绑定手机****************************/ + + /** + * @description 绑定手机数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof BindPhoneHandler + */ + async bind(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const uid = session.get('userid'); + + let playerData = await getBindPhoneData(activityId, roleId, serverId, uid); + let bindPhoneData = playerData?.bindPhone; + if(!bindPhoneData) return resResult(STATUS.ACTIVITY_ID_ERROR); + if(bindPhoneData.status != BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_HAS_BIND); + + await ActivityBindPhoneRewardModel.addRecord(activityId, uid, BIND_PHONE_STATUS.HAS_BIND, { roleId, roleName, serverId }); + + return resResult(STATUS.SUCCESS, { + activityId, + status: BIND_PHONE_STATUS.HAS_BIND + }); + } + + /** + * @description 领取奖励 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof BindPhoneHandler + */ + async receiveReward(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const uid = session.get('userid'); + + let playerData = await getBindPhoneData(activityId, roleId, serverId, uid); + let bindPhoneData = playerData?.bindPhone; + if(!bindPhoneData) return resResult(STATUS.ACTIVITY_ID_ERROR); + if(bindPhoneData.status == BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_BIND_ERR); + if(bindPhoneData.status == BIND_PHONE_STATUS.RECEIVED) return resResult(STATUS.ACTIVITY_BIND_RECEIVED); + + await ActivityBindPhoneRewardModel.addRecord(activityId, uid, BIND_PHONE_STATUS.RECEIVED, { roleId, roleName, serverId }); + let rewardArray = stringToRewardParam(bindPhoneData.rewards) + let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_BIND_PHONE); + + return resResult(STATUS.SUCCESS, { + activityId, + status: BIND_PHONE_STATUS.RECEIVED, + goods, addHeros + }); + } + + /** + * 领取公众号口令奖励 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof BindPhoneHandler + */ + async receiveGiftCode(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const uid = session.get('userid'); + + let user = await UserModel.findUserByUid(uid); + let playerData = await getPublicAccountData(activityId, roleId, serverId, user); + let data = playerData?.wxPublicAccount; + if(!data) return resResult(STATUS.ACTIVITY_ID_ERROR); + if(data.status == BIND_PHONE_STATUS.WAIT_BIND) return resResult(STATUS.ACTIVITY_PUBLIC_ACCOUNT_WAIT); + if(data.status == BIND_PHONE_STATUS.RECEIVED) return resResult(STATUS.ACTIVITY_PUBLIC_ACCOUNT_RECEIVED); + + await ActivityPublicAccountCodeModel.receive(activityId, user.channelId); + let rewardArray = stringToRewardParam(data.rewards) + let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_BIND_PHONE); + + return resResult(STATUS.SUCCESS, { + activityId, + status: BIND_PHONE_STATUS.RECEIVED, + goods, addHeros + }); + } + + /** + * 前往论坛,用于前往论坛任务 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof BindPhoneHandler + */ + async skipOutSide(msg: { activityId: number }, session: BackendSession) { + return resResult(STATUS.SUCCESS); + } + + /** + * 公众号设置成可以领取的状态 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof BindPhoneHandler + */ + async debugSetGiftCodeStatus(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const uid = session.get('userid'); + let user = await UserModel.findUserByUid(uid); + await ActivityPublicAccountCodeModel.findOneAndUpdate({ activityId, channelId: user.channelId }, { $set: { serverId, roleId, orderId: 'test', hasReceived: false } }, { new: true, upsert: true }).lean(); + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUBLIC_ACCOUNT_GIFT, { activityId, type: SNS_LINK_TYPE.WX_PUBLIC_ACCOUNT, status: BIND_PHONE_STATUS.HAS_BIND }); + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/chongyangHandler.ts b/game-server/app/servers/activity/handler/chongyangHandler.ts index 5e25dce43..b6c0c08f7 100644 --- a/game-server/app/servers/activity/handler/chongyangHandler.ts +++ b/game-server/app/servers/activity/handler/chongyangHandler.ts @@ -1,165 +1,166 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { genCode, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerChongYangData, getPlayerChongYangDataShow } from '../../../services/activity/chongyangService'; -import { ActivityChongYangRecModel, ChongYangGameRecord } from '../../../db/ActivityChongYangRec'; -import { RewardInter } from '../../../pubUtils/interface'; -import { stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { getZeroPoint } from '../../../pubUtils/timeUtil'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new ChongYangHandler(app); -} - -export class ChongYangHandler { - constructor(private app: Application) { - } - - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerChongYangDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - async gameStart(msg: { activityId: number, dayIndex: number }, session: BackendSession) { - const { activityId, dayIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerChongYangData(activityId, serverId, roleId); - if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); - let scene = playerData.sceneMap.get(dayIndex); - if (!scene) return resResult(STATUS.ACTIVITY_MISSING); - - // 检测挑战次数 - if (scene.playCnt >= scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); - // 检测解锁 - if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); - - const gameCode = genCode(10); - await ActivityChongYangRecModel.gameRecords(serverId, activityId, playerData.roundIndex, roleId, [{ - todayIndex: playerData.todayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, dayIndex, isSkip: false - }]); - - return resResult(STATUS.SUCCESS, { activityId, gameCode }); - } - - async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean, dayIndex: number }, session: BackendSession) { - const { activityId, gameCode, isSuccess, dayIndex } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerChongYangData(activityId, serverId, roleId); - if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); - let scene = playerData.sceneMap.get(dayIndex); - if (!scene) return resResult(STATUS.ACTIVITY_MISSING); - - // 检测挑战次数 - if (scene.playCnt >= scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); - // 检测解锁 - if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); - - let curRecord = playerData.gameRecords.find(cur => cur.gameCode == gameCode); - if (!curRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); - if (curRecord.isSuccess) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_USE); - - let playerRecord = await ActivityChongYangRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), scene.rewards); - if (!playerRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); - playerData = await getPlayerChongYangData(activityId, serverId, roleId); - scene = playerData.sceneMap.get(dayIndex); - - let goods: RewardInter[] = []; - if (isSuccess) { - goods = await addItems(roleId, roleName, sid, stringToRewardParam(scene.rewards), ITEM_CHANGE_REASON.CHONGYANG_REWARD) - } - - return resResult(STATUS.SUCCESS, { - activityId, - playCnt: scene.playCnt, - maxPlayCnt: scene.maxPlayCnt, - gameCode, - goods - }); - } - - async buyCnt(msg: { activityId: number, dayIndex: number, count: number }, session: BackendSession) { - const { activityId, dayIndex, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerChongYangData(activityId, serverId, roleId); - if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); - let scene = playerData.sceneMap.get(dayIndex); - if (!scene) return resResult(STATUS.ACTIVITY_MISSING); - - // 检测购买次数 - if (scene.buyCnt + count > scene.dailyBuyCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_BUY_COUNT_OVER); - // 检测解锁 - if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); - - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(scene.buyCost), ITEM_CHANGE_REASON.CHONGYANG_COST); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - // 保存数据 - let playerRecord = await ActivityChongYangRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, { dayIndex, buyCnt: count }, scene.isPushBuyRecord); - if (!playerRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); - - playerData = await getPlayerChongYangData(activityId, serverId, roleId); - scene = playerData.sceneMap.get(dayIndex); - - return resResult(STATUS.SUCCESS, { activityId, dailyBuyCnt: scene.dailyBuyCnt, buyCnt: scene.buyCnt, }); - } - - async gameSweep(msg: { activityId: number, dayIndex: number, count: number }, session: BackendSession) { - const { activityId, dayIndex, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerChongYangData(activityId, serverId, roleId); - if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); - let scene = playerData.sceneMap.get(dayIndex); - if (!scene) return resResult(STATUS.ACTIVITY_MISSING); - - // 检测挑战次数 - if (scene.playCnt + count > scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); - // 检测解锁 - if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); - // 检测通关 - let isHasPass = playerData.gameRecords.find(cur => cur.dayIndex == dayIndex && cur.isSuccess && !cur.isSkip && (getZeroPoint() * 1000 <= cur.time.getTime())); - if (!isHasPass) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMESWEEP_LOCK); - - let rewards: RewardInter[] = []; - let records: ChongYangGameRecord[] = []; - for (let i = 0; i < count; i++) { - records.push({ todayIndex: playerData.todayIndex, gameCode: 'sweep', time: new Date(), rewards: scene.rewards, isSuccess: true, dayIndex, isSkip: true }) - rewards.push(...stringToRewardParam(scene.rewards)); - } - await ActivityChongYangRecModel.gameRecords(serverId, activityId, playerData.roundIndex, roleId, records); - - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.CHONGYANG_REWARD) - - playerData = await getPlayerChongYangData(activityId, serverId, roleId); - scene = playerData.sceneMap.get(dayIndex); - - return resResult(STATUS.SUCCESS, { - activityId, - playCnt: scene.playCnt, - maxPlayCnt: scene.maxPlayCnt, - goods - }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { genCode, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerChongYangData, getPlayerChongYangDataShow } from '../../../services/activity/chongyangService'; +import { ActivityChongYangRecModel, ChongYangGameRecord } from '@db/ActivityChongYangRec'; +import { RewardInter } from '@pubUtils/interface'; +import { stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { getZeroPoint } from '@pubUtils/timeUtil'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new ChongYangHandler(app); +} + +export class ChongYangHandler { + constructor(private app: Application) { + } + + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerChongYangDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + async gameStart(msg: { activityId: number, dayIndex: number }, session: BackendSession) { + const { activityId, dayIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerChongYangData(activityId, serverId, roleId); + if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); + let scene = playerData.sceneMap.get(dayIndex); + if (!scene) return resResult(STATUS.ACTIVITY_MISSING); + + // 检测挑战次数 + if (scene.playCnt >= scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); + // 检测解锁 + if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); + + const gameCode = genCode(10); + await ActivityChongYangRecModel.gameRecords(serverId, activityId, playerData.roundIndex, roleId, [{ + todayIndex: playerData.todayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, dayIndex, isSkip: false + }]); + + return resResult(STATUS.SUCCESS, { activityId, gameCode }); + } + + async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean, dayIndex: number }, session: BackendSession) { + const { activityId, gameCode, isSuccess, dayIndex } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerChongYangData(activityId, serverId, roleId); + if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); + let scene = playerData.sceneMap.get(dayIndex); + if (!scene) return resResult(STATUS.ACTIVITY_MISSING); + + // 检测挑战次数 + if (scene.playCnt >= scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); + // 检测解锁 + if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); + + let curRecord = playerData.gameRecords.find(cur => cur.gameCode == gameCode); + if (!curRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); + if (curRecord.isSuccess) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_USE); + + let playerRecord = await ActivityChongYangRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), scene.rewards); + if (!playerRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); + playerData = await getPlayerChongYangData(activityId, serverId, roleId); + scene = playerData.sceneMap.get(dayIndex); + + let goods: RewardInter[] = []; + if (isSuccess) { + goods = await addItems(roleId, roleName, sid, stringToRewardParam(scene.rewards), ITEM_CHANGE_REASON.CHONGYANG_REWARD) + } + + return resResult(STATUS.SUCCESS, { + activityId, + playCnt: scene.playCnt, + maxPlayCnt: scene.maxPlayCnt, + gameCode, + goods + }); + } + + async buyCnt(msg: { activityId: number, dayIndex: number, count: number }, session: BackendSession) { + const { activityId, dayIndex, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerChongYangData(activityId, serverId, roleId); + if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); + let scene = playerData.sceneMap.get(dayIndex); + if (!scene) return resResult(STATUS.ACTIVITY_MISSING); + + // 检测购买次数 + if (scene.buyCnt + count > scene.dailyBuyCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_BUY_COUNT_OVER); + // 检测解锁 + if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); + + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(scene.buyCost), ITEM_CHANGE_REASON.CHONGYANG_COST); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + // 保存数据 + let playerRecord = await ActivityChongYangRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, { dayIndex, buyCnt: count }, scene.isPushBuyRecord); + if (!playerRecord) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMECODE_NOT_FOUND); + + playerData = await getPlayerChongYangData(activityId, serverId, roleId); + scene = playerData.sceneMap.get(dayIndex); + + return resResult(STATUS.SUCCESS, { activityId, dailyBuyCnt: scene.dailyBuyCnt, buyCnt: scene.buyCnt, }); + } + + async gameSweep(msg: { activityId: number, dayIndex: number, count: number }, session: BackendSession) { + const { activityId, dayIndex, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerChongYangData(activityId, serverId, roleId); + if (!playerData || !playerData.sceneMap) return resResult(STATUS.ACTIVITY_MISSING); + let scene = playerData.sceneMap.get(dayIndex); + if (!scene) return resResult(STATUS.ACTIVITY_MISSING); + + // 检测挑战次数 + if (scene.playCnt + count > scene.maxPlayCnt) return resResult(STATUS.ACTIVITY_CHONGYANG_NO_NUM); + // 检测解锁 + if (dayIndex > playerData.dayIndexUnlock) return resResult(STATUS.ACTIVITY_CHONGYANG_LOCK); + // 检测通关 + let isHasPass = playerData.gameRecords.find(cur => cur.dayIndex == dayIndex && cur.isSuccess && !cur.isSkip && (getZeroPoint() * 1000 <= cur.time.getTime())); + if (!isHasPass) return resResult(STATUS.ACTIVITY_CHONGYANG_GAMESWEEP_LOCK); + + let rewards: RewardInter[] = []; + let records: ChongYangGameRecord[] = []; + for (let i = 0; i < count; i++) { + records.push({ todayIndex: playerData.todayIndex, gameCode: 'sweep', time: new Date(), rewards: scene.rewards, isSuccess: true, dayIndex, isSkip: true }) + rewards.push(...stringToRewardParam(scene.rewards)); + } + await ActivityChongYangRecModel.gameRecords(serverId, activityId, playerData.roundIndex, roleId, records); + + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.CHONGYANG_REWARD) + + playerData = await getPlayerChongYangData(activityId, serverId, roleId); + scene = playerData.sceneMap.get(dayIndex); + + return resResult(STATUS.SUCCESS, { + activityId, + playCnt: scene.playCnt, + maxPlayCnt: scene.maxPlayCnt, + goods + }); + } +} + diff --git a/game-server/app/servers/activity/handler/dailyChallengesHandler.ts b/game-server/app/servers/activity/handler/dailyChallengesHandler.ts index 6e3c77f37..987c8eccc 100644 --- a/game-server/app/servers/activity/handler/dailyChallengesHandler.ts +++ b/game-server/app/servers/activity/handler/dailyChallengesHandler.ts @@ -1,80 +1,81 @@ -import { Application, BackendSession, HandlerService } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerDailyChallengesData } from '../../../services/activity/dailyChallengesService'; -import { DailyItem } from '../../../domain/activityField/dailyChallengesField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityDailyChallengesModel } from '../../../db/ActivityDailyChallenges'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyChallengesHandler(app); -} - -export class DailyChallengesHandler { - constructor(private app: Application) { - } - - /************************今日挑战****************************/ - - /** - * @description 获取今日挑战活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyChallengesHandler - */ - async getDailyChallengesActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyChallengesData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取今日挑战的单个奖励 - * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg - * @param {BackendSession} session - * @memberof DailyChallengesHandler - */ - async getDailyChallengeReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerDailyChallengesData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let dailyItemData: DailyItem = playerData.findDailyChallengesItem(dayIndex, cellIndex, type); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!dailyItemData.isComplete()) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (!dailyItemData.canReceive()) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityDailyChallengesModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_CHALLENGE_REWARD) - - dailyItemData.receiveRewardCount = 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex, type }, - item: dailyItemData, - })); - } - -} +import { Application, BackendSession, HandlerService } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerDailyChallengesData } from '../../../services/activity/dailyChallengesService'; +import { DailyItem } from '@domain/activityField/dailyChallengesField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityDailyChallengesModel } from '@db/ActivityDailyChallenges'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyChallengesHandler(app); +} + +export class DailyChallengesHandler { + constructor(private app: Application) { + } + + /************************今日挑战****************************/ + + /** + * @description 获取今日挑战活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyChallengesHandler + */ + async getDailyChallengesActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyChallengesData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取今日挑战的单个奖励 + * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg + * @param {BackendSession} session + * @memberof DailyChallengesHandler + */ + async getDailyChallengeReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerDailyChallengesData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let dailyItemData: DailyItem = playerData.findDailyChallengesItem(dayIndex, cellIndex, type); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!dailyItemData.isComplete()) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (!dailyItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityDailyChallengesModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_CHALLENGE_REWARD) + + dailyItemData.receiveRewardCount = 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex, type }, + item: dailyItemData, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/dailyCoinHandler.ts b/game-server/app/servers/activity/handler/dailyCoinHandler.ts index 3151bc001..22019cec9 100644 --- a/game-server/app/servers/activity/handler/dailyCoinHandler.ts +++ b/game-server/app/servers/activity/handler/dailyCoinHandler.ts @@ -1,166 +1,167 @@ -import { Application, BackendSession, HandlerService } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ACTIVITY_RESOURCES_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, DAILY_COIN_BOX_STATUS, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { getPlayerDailyCoinData, mergeData } from '../../../services/activity/dailyCoinService'; -import { ConsumeExchangeFormulaItem, CoinRewardFormulaItem } from '../../../domain/activityField/dailyCoinField'; -import { ActivityDailyCoinModel } from '../../../db/ActivityDailyCoin'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ItemInter } from '../../../pubUtils/interface'; -import { RoleModel } from '../../../db/Role'; -import moment = require('moment'); - - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyCoinHandler(app); -} - -export class DailyCoinHandler { - constructor(private app: Application) { - } - - - /************************每日兑换铜币****************************/ - - /** - * @description 获取每日铜币活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyCoinHandler - */ - async getDailyCoinActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 兑换 - * @param {{ activityId: number, count:number}} msg - * @param {BackendSession} session - * @memberof DailyCoinHandler - */ - async exchangeCoin(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let curIndex = playerData.exchangeCount; - if (curIndex + count > playerData.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - let allConsume: Array = [] - let allReward: Array = []; - let role = await RoleModel.findByRoleId(roleId) - let rateArray = [];//暴击记录 - for (let i = 1; i <= count; i++) { - let index = curIndex + i; - if (index > playerData.freeCount) {//消耗资源 - let consumeItem: ConsumeExchangeFormulaItem = playerData.findConsumeExchangeFormulaItem(index); - let times = index; - let consumeCount = eval(consumeItem.consumeFormula) - let consume = getGoldObject(consumeCount) - allConsume = allConsume.concat(consume) - } - let rate = playerData.getRate()//翻几倍 - rateArray.push(rate); - let lv = role.lv;//玩家等级 - let rewardItem: CoinRewardFormulaItem = playerData.findCoinRewardFormulaItem(lv); - if (!rewardItem) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - let coinRewardCount = eval(rewardItem.rewardFormula); - // console.log('******** coinReward', lv, rewardItem.rewardFormula, coinRewardCount) - - let baseRewardParamArr: Array = [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: coinRewardCount, type: ACTIVITY_RESOURCES_TYPE.GOODS }]; - // console.log('第几次抽奖:', index, ' 基础奖励翻倍:', rate, JSON.stringify(baseRewardParamArr),) - for (let reward of baseRewardParamArr) { - reward.count = reward.count * rate; - } - allReward = allReward.concat(baseRewardParamArr); - } - - let newConsume = mergeData(allConsume); - let newReward = mergeData(allReward); - // console.log('所有消耗', JSON.stringify(newConsume)) - // console.log('所有奖励', JSON.stringify(newReward)) - - //检查资源 - let consumeResult = await handleCost(roleId, sid, newConsume, ITEM_CHANGE_REASON.DAILY_COIN_EXCHANGE); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - - let addCoin = 0 - let coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); - for (let obj of newReward) { - if (obj.id === coinId) { - addCoin += obj.count; - } - } - - let consumeGold = 0; - let goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); - for (let obj of newConsume) { - if (obj.id === goldId) { - consumeGold += obj.count; - } - } - - //免费期间 - let time = moment(new Date()).valueOf(); - let result = await addReward(roleId, roleName, sid, serverId, newReward, ITEM_CHANGE_REASON.DAILY_COIN_EXCHANGE); - - let extraReward = playerData.addExchangeCount(count); - await ActivityDailyCoinModel.addExchangeRecord(serverId, activityId, roleId, playerData.roundIndex, count, addCoin, `${count}&${consumeGold}&${addCoin}&${time}`, playerData.hasNotReceivedBox()); - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, count, extraReward }, - item: { exchangeCount: playerData.exchangeCount, recordMsg: `${count}&${consumeGold}&${addCoin}&${time}`, rateArray }, - })); - } - - - /** - * @description 领取宝箱 - * @param {{ activityId: number, cellIndex:number}} msg - * @param {BackendSession} session - * @memberof DailyCoinHandler - */ - async receiveExtraReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { - const { activityId, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let box = await playerData.findBoxByCellIndex(cellIndex); - if(!box) return resResult(STATUS.DAILY_COIN_BOX_NOT_FOUND); - if(box.status != DAILY_COIN_BOX_STATUS.CAN_OPEN) return resResult(STATUS.DAILY_COIN_BOX_CANNOT_RECEIVE); - - let rewardArray = stringToRewardParam(box.reward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_DAILY_COIN_RECEIVE_BOX); - - let item = playerData.receiveBox(cellIndex); - await ActivityDailyCoinModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, cellIndex, playerData.hasNotReceivedBox()); - - return resResult(STATUS.SUCCESS, Object.assign(result, { - item, - param: { activityId }, - })); - } - -} +import { Application, BackendSession, HandlerService } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ACTIVITY_RESOURCES_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, DAILY_COIN_BOX_STATUS, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { getPlayerDailyCoinData, mergeData } from '../../../services/activity/dailyCoinService'; +import { ConsumeExchangeFormulaItem, CoinRewardFormulaItem } from '@domain/activityField/dailyCoinField'; +import { ActivityDailyCoinModel } from '@db/ActivityDailyCoin'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ItemInter } from '@pubUtils/interface'; +import { RoleModel } from '@db/Role'; +import moment = require('moment'); + + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyCoinHandler(app); +} + +export class DailyCoinHandler { + constructor(private app: Application) { + } + + + /************************每日兑换铜币****************************/ + + /** + * @description 获取每日铜币活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyCoinHandler + */ + async getDailyCoinActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 兑换 + * @param {{ activityId: number, count:number}} msg + * @param {BackendSession} session + * @memberof DailyCoinHandler + */ + async exchangeCoin(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let curIndex = playerData.exchangeCount; + if (curIndex + count > playerData.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + let allConsume: Array = [] + let allReward: Array = []; + let role = await RoleModel.findByRoleId(roleId) + let rateArray = [];//暴击记录 + for (let i = 1; i <= count; i++) { + let index = curIndex + i; + if (index > playerData.freeCount) {//消耗资源 + let consumeItem: ConsumeExchangeFormulaItem = playerData.findConsumeExchangeFormulaItem(index); + let times = index; + let consumeCount = eval(consumeItem.consumeFormula) + let consume = getGoldObject(consumeCount) + allConsume = allConsume.concat(consume) + } + let rate = playerData.getRate()//翻几倍 + rateArray.push(rate); + let lv = role.lv;//玩家等级 + let rewardItem: CoinRewardFormulaItem = playerData.findCoinRewardFormulaItem(lv); + if (!rewardItem) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + let coinRewardCount = eval(rewardItem.rewardFormula); + // console.log('******** coinReward', lv, rewardItem.rewardFormula, coinRewardCount) + + let baseRewardParamArr: Array = [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: coinRewardCount, type: ACTIVITY_RESOURCES_TYPE.GOODS }]; + // console.log('第几次抽奖:', index, ' 基础奖励翻倍:', rate, JSON.stringify(baseRewardParamArr),) + for (let reward of baseRewardParamArr) { + reward.count = reward.count * rate; + } + allReward = allReward.concat(baseRewardParamArr); + } + + let newConsume = mergeData(allConsume); + let newReward = mergeData(allReward); + // console.log('所有消耗', JSON.stringify(newConsume)) + // console.log('所有奖励', JSON.stringify(newReward)) + + //检查资源 + let consumeResult = await handleCost(roleId, sid, newConsume, ITEM_CHANGE_REASON.DAILY_COIN_EXCHANGE); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + + let addCoin = 0 + let coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); + for (let obj of newReward) { + if (obj.id === coinId) { + addCoin += obj.count; + } + } + + let consumeGold = 0; + let goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); + for (let obj of newConsume) { + if (obj.id === goldId) { + consumeGold += obj.count; + } + } + + //免费期间 + let time = moment(new Date()).valueOf(); + let result = await addReward(roleId, roleName, sid, serverId, newReward, ITEM_CHANGE_REASON.DAILY_COIN_EXCHANGE); + + let extraReward = playerData.addExchangeCount(count); + await ActivityDailyCoinModel.addExchangeRecord(serverId, activityId, roleId, playerData.roundIndex, count, addCoin, `${count}&${consumeGold}&${addCoin}&${time}`, playerData.hasNotReceivedBox()); + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, count, extraReward }, + item: { exchangeCount: playerData.exchangeCount, recordMsg: `${count}&${consumeGold}&${addCoin}&${time}`, rateArray }, + })); + } + + + /** + * @description 领取宝箱 + * @param {{ activityId: number, cellIndex:number}} msg + * @param {BackendSession} session + * @memberof DailyCoinHandler + */ + async receiveExtraReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { + const { activityId, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerDailyCoinData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let box = await playerData.findBoxByCellIndex(cellIndex); + if(!box) return resResult(STATUS.DAILY_COIN_BOX_NOT_FOUND); + if(box.status != DAILY_COIN_BOX_STATUS.CAN_OPEN) return resResult(STATUS.DAILY_COIN_BOX_CANNOT_RECEIVE); + + let rewardArray = stringToRewardParam(box.reward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_DAILY_COIN_RECEIVE_BOX); + + let item = playerData.receiveBox(cellIndex); + await ActivityDailyCoinModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, cellIndex, playerData.hasNotReceivedBox()); + + return resResult(STATUS.SUCCESS, Object.assign(result, { + item, + param: { activityId }, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/dailyGKHandler.ts b/game-server/app/servers/activity/handler/dailyGKHandler.ts index b35972870..3ff391543 100644 --- a/game-server/app/servers/activity/handler/dailyGKHandler.ts +++ b/game-server/app/servers/activity/handler/dailyGKHandler.ts @@ -1,77 +1,78 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; -import { getPlayerDailyGKData } from '../../../services/activity/dailyGKService'; -import { DailyGKItem } from '../../../domain/activityField/dailyGKField'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyGKHandler(app); -} - -export class DailyGKHandler { - constructor(private app: Application) { - } - - /************************每日关卡;按日开启,每日开启一关****************************/ - - /** - * @description 获取每日关卡活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyGKHandler - */ - async getDailyGKActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyGKData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取今日挑战的单个奖励 - * @param {{ activityId: number, dayIndex: number}} msg - * @param {BackendSession} session - * @memberof DailyGKHandler - */ - async getGK(msg: { activityId: number, dayIndex: number }, session: BackendSession) { - const { activityId, dayIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerDailyGKData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (dayIndex > playerData.todayIndex) { - return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); - } - - let dailyItemData: DailyGKItem = playerData.findDailyGKItem(dayIndex); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - // if (dailyItemData.isSuccess) {//已经达成 - // return resResult(STATUS.ACTIVITY_REWARDED); - // } - - // await ActivityDailyGKModel.addRecord(serverId, activityId, roleId, dayIndex); - - // let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - // let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr) - - // dailyItemData.isSuccess = true; - return resResult(STATUS.SUCCESS, { - gkId: dailyItemData.gk - }); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '../../../consts'; +import { getPlayerDailyGKData } from '../../../services/activity/dailyGKService'; +import { DailyGKItem } from '@domain/activityField/dailyGKField'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyGKHandler(app); +} + +export class DailyGKHandler { + constructor(private app: Application) { + } + + /************************每日关卡;按日开启,每日开启一关****************************/ + + /** + * @description 获取每日关卡活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyGKHandler + */ + async getDailyGKActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyGKData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取今日挑战的单个奖励 + * @param {{ activityId: number, dayIndex: number}} msg + * @param {BackendSession} session + * @memberof DailyGKHandler + */ + async getGK(msg: { activityId: number, dayIndex: number }, session: BackendSession) { + const { activityId, dayIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerDailyGKData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (dayIndex > playerData.todayIndex) { + return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + } + + let dailyItemData: DailyGKItem = playerData.findDailyGKItem(dayIndex); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + // if (dailyItemData.isSuccess) {//已经达成 + // return resResult(STATUS.ACTIVITY_REWARDED); + // } + + // await ActivityDailyGKModel.addRecord(serverId, activityId, roleId, dayIndex); + + // let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + // let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr) + + // dailyItemData.isSuccess = true; + return resResult(STATUS.SUCCESS, { + gkId: dailyItemData.gk + }); + } + +} + diff --git a/game-server/app/servers/activity/handler/dailyGiftsHandler.ts b/game-server/app/servers/activity/handler/dailyGiftsHandler.ts index 14c5c5ea8..7bc69b12b 100644 --- a/game-server/app/servers/activity/handler/dailyGiftsHandler.ts +++ b/game-server/app/servers/activity/handler/dailyGiftsHandler.ts @@ -1,93 +1,94 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; -import { handleCost } from '../../../services/role/rewardService'; -import { getPlayerDailyGiftsData } from '../../../services/activity/dailyGiftsService'; -import { DailyGiftItem } from '../../../domain/activityField/dailyGiftsField'; -import { ActivityDailyGiftsModel } from '../../../db/ActivityDailyGifts'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyGiftsHandler(app); -} - -export class DailyGiftsHandler { - constructor(private app: Application) { - } - - - /************************每日特惠礼包****************************/ - - /** - * @description 获取每日特惠礼包活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyGiftsHandler - */ - async getDailyGiftsActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyGiftsData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 购买每日特惠礼包 - * @param {{ activityId: number, dayIndex: number, cellIndex: number}} msg - * @param {BackendSession} session - * @memberof DailyGiftsHandler - */ - async buyDailyGiftsCell(msg: { activityId: number, dayIndex: number, cellIndex: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerDailyGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let dailyItemData: DailyGiftItem = playerData.findDailyGiftsItem(dayIndex, cellIndex); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!dailyItemData.canBuy()) {//最大次数 - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (dayIndex > playerData.today()) {//还未开启 - return resResult(STATUS.ACTIVITY_UNOPENED); - } - - //货币是否足够 - let consumeData = dailyItemData.consumeRes(); - let consumeType = consumeData.type;//购买类型 - - if (consumeType == ACTIVITY_RESOURCES_TYPE.GOODS) {//物品表,元宝、金币、体力 - let result = await handleCost(roleId, sid, [{ id: consumeData.id, count: consumeData.count }], ITEM_CHANGE_REASON.BUY_DAILY_GIFTS); - if (!result) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - } else if (consumeType == ACTIVITY_RESOURCES_TYPE.RMB) {//RMB购买 - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - - await ActivityDailyGiftsModel.buyRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.BUY_DAILY_GIFTS) - - dailyItemData.buyCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex }, - item: dailyItemData, - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; +import { handleCost } from '../../../services/role/rewardService'; +import { getPlayerDailyGiftsData } from '../../../services/activity/dailyGiftsService'; +import { DailyGiftItem } from '@domain/activityField/dailyGiftsField'; +import { ActivityDailyGiftsModel } from '@db/ActivityDailyGifts'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyGiftsHandler(app); +} + +export class DailyGiftsHandler { + constructor(private app: Application) { + } + + + /************************每日特惠礼包****************************/ + + /** + * @description 获取每日特惠礼包活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyGiftsHandler + */ + async getDailyGiftsActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyGiftsData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 购买每日特惠礼包 + * @param {{ activityId: number, dayIndex: number, cellIndex: number}} msg + * @param {BackendSession} session + * @memberof DailyGiftsHandler + */ + async buyDailyGiftsCell(msg: { activityId: number, dayIndex: number, cellIndex: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerDailyGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let dailyItemData: DailyGiftItem = playerData.findDailyGiftsItem(dayIndex, cellIndex); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!dailyItemData.canBuy()) {//最大次数 + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (dayIndex > playerData.today()) {//还未开启 + return resResult(STATUS.ACTIVITY_UNOPENED); + } + + //货币是否足够 + let consumeData = dailyItemData.consumeRes(); + let consumeType = consumeData.type;//购买类型 + + if (consumeType == ACTIVITY_RESOURCES_TYPE.GOODS) {//物品表,元宝、金币、体力 + let result = await handleCost(roleId, sid, [{ id: consumeData.id, count: consumeData.count }], ITEM_CHANGE_REASON.BUY_DAILY_GIFTS); + if (!result) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } else if (consumeType == ACTIVITY_RESOURCES_TYPE.RMB) {//RMB购买 + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + + await ActivityDailyGiftsModel.buyRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.BUY_DAILY_GIFTS) + + dailyItemData.buyCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex }, + item: dailyItemData, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/dailyMealHandler.ts b/game-server/app/servers/activity/handler/dailyMealHandler.ts index 72aa71410..2379a1aac 100644 --- a/game-server/app/servers/activity/handler/dailyMealHandler.ts +++ b/game-server/app/servers/activity/handler/dailyMealHandler.ts @@ -1,88 +1,89 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { handleCost } from '../../../services/role/rewardService'; -import { getPlayerDailyMealData } from '../../../services/activity/dailyMealService'; -import { DailyMealItem } from '../../../domain/activityField/dailyMealField'; -import { ActivityDailyMealModel } from '../../../db/ActivityDailyMeal'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import moment = require('moment'); - - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyMealHandler(app); -} - -export class DailyMealHandler { - constructor(private app: Application) { - } - - - /************************每日午饭/晚饭****************************/ - - /** - * @description 获取每日午饭/晚饭活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyMealHandler - */ - async getDailyMealActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyMealData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 领取奖励 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyMealHandler - */ - async getDailyMealReward(msg: { activityId: number, type: number }, session: BackendSession) { - const { activityId, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerDailyMealData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let itemData: DailyMealItem = playerData.findItem(type); - if (!itemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (itemData.isReceive) {//最大次数 - return resResult(STATUS.ACTIVITY_REWARDED); - } - let curDate = moment(new Date()).valueOf(); - if (curDate < itemData.beginTime) {//没到饭点 - return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); - } - if (curDate > itemData.endTime) {//补领 - //检查资源 - let consume = stringToConsumeParam(itemData.consume) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.DAILY_MEAL_RECEIVE_REPAIRE); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - } - //免费期间 - let rewardParamArr: Array = stringToRewardParam(itemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_MEAL_RECEIVE); - await ActivityDailyMealModel.addReceiveRecord(serverId, activityId, roleId, type, curDate, playerData.roundIndex); - itemData.isReceive = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, type }, - item: itemData, - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { handleCost } from '../../../services/role/rewardService'; +import { getPlayerDailyMealData } from '../../../services/activity/dailyMealService'; +import { DailyMealItem } from '@domain/activityField/dailyMealField'; +import { ActivityDailyMealModel } from '@db/ActivityDailyMeal'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import moment = require('moment'); + + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyMealHandler(app); +} + +export class DailyMealHandler { + constructor(private app: Application) { + } + + + /************************每日午饭/晚饭****************************/ + + /** + * @description 获取每日午饭/晚饭活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyMealHandler + */ + async getDailyMealActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyMealData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 领取奖励 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyMealHandler + */ + async getDailyMealReward(msg: { activityId: number, type: number }, session: BackendSession) { + const { activityId, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerDailyMealData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let itemData: DailyMealItem = playerData.findItem(type); + if (!itemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (itemData.isReceive) {//最大次数 + return resResult(STATUS.ACTIVITY_REWARDED); + } + let curDate = moment(new Date()).valueOf(); + if (curDate < itemData.beginTime) {//没到饭点 + return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + } + if (curDate > itemData.endTime) {//补领 + //检查资源 + let consume = stringToConsumeParam(itemData.consume) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.DAILY_MEAL_RECEIVE_REPAIRE); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } + //免费期间 + let rewardParamArr: Array = stringToRewardParam(itemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_MEAL_RECEIVE); + await ActivityDailyMealModel.addReceiveRecord(serverId, activityId, roleId, type, curDate, playerData.roundIndex); + itemData.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, type }, + item: itemData, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/dailyRMBGiftsHandler.ts b/game-server/app/servers/activity/handler/dailyRMBGiftsHandler.ts index 13c63cd03..f2d2ce8d6 100644 --- a/game-server/app/servers/activity/handler/dailyRMBGiftsHandler.ts +++ b/game-server/app/servers/activity/handler/dailyRMBGiftsHandler.ts @@ -1,95 +1,96 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { getPlayerDailyRMBGiftsData } from '../../../services/activity/dailyRMBGiftsService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityDailyRMBGiftsModel } from '../../../db/ActivityDailyRMBGifts'; -import moment = require('moment'); -import { DailyRMBGiftsItem } from '../../../domain/activityField/dailyRMBGiftsField'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new DailyRMBGiftsHandler(app); -} - -export class DailyRMBGiftsHandler { - constructor(private app: Application) { - } - - /************************每日特惠礼包RMB购买4挡,有可能免费,一次性支付购买7天,每天只能领取当天的礼包奖励****************************/ - - /** - * @description 获取每日特惠礼包活动数据 - * @param {{ }} msg - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DailyRMBGiftsHandler - */ - async getDailyRMBGiftsActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 一次性购买7天后,获取当天的礼包 - * @param {{ activityId: number, id:number}} msg - * @param {BackendSession} session - * @memberof DailyRMBGiftsHandler - */ - async getDailyRMBGiftsReward(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let items: DailyRMBGiftsItem[] = []; - if(id > 0) { - let item = playerData.findItem(id); - if (!item) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (item.isReceive) { - return resResult(STATUS.ACTIVITY_REWARDED); - } - if (!playerData.isBuy && item.price > 0) { - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - items.push(item); - } else { - if (!playerData.isBuy) { - return resResult(STATUS.ACTIVITY_UNOPENED); - } - items.push(...playerData.unReceiveItem()); - } - if (items.length == 0) { - return resResult(STATUS.ACTIVITY_REWARDED); - } - - let rewardArray: RewardParam[] = []; - let ids: number[] = [] - for (let item of items) { - ids.push(item.id); - rewardArray.push(...stringToRewardParam(item.reward)); - } - let resultItems = playerData.receiveItems(ids); - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.DAILY_RMB_GIFT) - await ActivityDailyRMBGiftsModel.receiveRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, ids); - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, unReceiveCount: playerData.unReceiveCount, buttonStatus: playerData.buttonStatus }, - items: resultItems - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { getPlayerDailyRMBGiftsData } from '../../../services/activity/dailyRMBGiftsService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityDailyRMBGiftsModel } from '@db/ActivityDailyRMBGifts'; +import moment = require('moment'); +import { DailyRMBGiftsItem } from '@domain/activityField/dailyRMBGiftsField'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new DailyRMBGiftsHandler(app); +} + +export class DailyRMBGiftsHandler { + constructor(private app: Application) { + } + + /************************每日特惠礼包RMB购买4挡,有可能免费,一次性支付购买7天,每天只能领取当天的礼包奖励****************************/ + + /** + * @description 获取每日特惠礼包活动数据 + * @param {{ }} msg + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyRMBGiftsHandler + */ + async getDailyRMBGiftsActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 一次性购买7天后,获取当天的礼包 + * @param {{ activityId: number, id:number}} msg + * @param {BackendSession} session + * @memberof DailyRMBGiftsHandler + */ + async getDailyRMBGiftsReward(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let items: DailyRMBGiftsItem[] = []; + if(id > 0) { + let item = playerData.findItem(id); + if (!item) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (item.isReceive) { + return resResult(STATUS.ACTIVITY_REWARDED); + } + if (!playerData.isBuy && item.price > 0) { + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + items.push(item); + } else { + if (!playerData.isBuy) { + return resResult(STATUS.ACTIVITY_UNOPENED); + } + items.push(...playerData.unReceiveItem()); + } + if (items.length == 0) { + return resResult(STATUS.ACTIVITY_REWARDED); + } + + let rewardArray: RewardParam[] = []; + let ids: number[] = [] + for (let item of items) { + ids.push(item.id); + rewardArray.push(...stringToRewardParam(item.reward)); + } + let resultItems = playerData.receiveItems(ids); + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.DAILY_RMB_GIFT) + await ActivityDailyRMBGiftsModel.receiveRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, ids); + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, unReceiveCount: playerData.unReceiveCount, buttonStatus: playerData.buttonStatus }, + items: resultItems + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/dragonBoatHandler.ts b/game-server/app/servers/activity/handler/dragonBoatHandler.ts index 4162312cb..928fc9b39 100644 --- a/game-server/app/servers/activity/handler/dragonBoatHandler.ts +++ b/game-server/app/servers/activity/handler/dragonBoatHandler.ts @@ -1,137 +1,138 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { parseNumberList, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getPlayerDragonBoatData, getPlayerDragonBoatDataShow } from '../../../services/activity/dragonBoatService'; -import { ActivityDragonBoatModel } from '../../../db/ActivityDragonBoat'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new DragonBoatHandler(app); -} - -export class DragonBoatHandler { - constructor(private app: Application) { - } - - /** - * @description 获取火神祭祀活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof DragonBoatHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDragonBoatDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 挑战开始 - * @param {{ activityId: number, id: number}} msg - * @param {BackendSession} session - * @memberof DragonBoatHandler - */ - async gameStart(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_COUNT_OVER); - - let route = playerData.findRoute(id); - if(!route) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_NOTFOUND); - if(route.hasPass) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_HAS_PASS); - if(route.preId && route.preId != '&') { - let preIds = parseNumberList(route.preId); - let hasPass = preIds.find(preId => { - let preRoute = playerData.findRoute(preId); - return preRoute && preRoute.hasPass; - }); - if(!hasPass) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_PRE_NOT_PASS); - } - let rewards = stringToRewardParam(route.reward); - let playerRecord = await ActivityDragonBoatModel.record(serverId, activityId, playerData.roundIndex, roleId, { todayIndex: playerData.todayIndex, id, time: new Date(), rewards }) - playerData.setPlayerRecords(playerRecord); - - await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_DRAGON_BOAT); - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - route: playerData.findRoute(id)?.getShowResult() - }); - } - - /** - * @description 挑战结束 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof DragonBoatHandler - */ - async gameEnd(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let route = playerData.findRoute(id); - if(!route) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_NOTFOUND); - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - route: route.getShowResult(), - goods: route.resultReward - }); - } - - /** - * @description 购买次数 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof DragonBoatHandler - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // 可购买次数 - if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_BUY_COUNT_OVER); - if(playerData.todayPlayCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_CANNOT_BUY); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_DRAGON_BOAT_BUY_COST); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 保存数据 - let buildResult = await ActivityDragonBoatModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); - // 更新数据 - playerData.setPlayerRecords(buildResult); - - return resResult(STATUS.SUCCESS, { - activityId, - maxBuyCnt: playerData.maxBuyCnt, - buyCnt: playerData.buyCnt - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { parseNumberList, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getPlayerDragonBoatData, getPlayerDragonBoatDataShow } from '../../../services/activity/dragonBoatService'; +import { ActivityDragonBoatModel } from '@db/ActivityDragonBoat'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new DragonBoatHandler(app); +} + +export class DragonBoatHandler { + constructor(private app: Application) { + } + + /** + * @description 获取火神祭祀活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DragonBoatHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDragonBoatDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 挑战开始 + * @param {{ activityId: number, id: number}} msg + * @param {BackendSession} session + * @memberof DragonBoatHandler + */ + async gameStart(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_COUNT_OVER); + + let route = playerData.findRoute(id); + if(!route) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_NOTFOUND); + if(route.hasPass) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_HAS_PASS); + if(route.preId && route.preId != '&') { + let preIds = parseNumberList(route.preId); + let hasPass = preIds.find(preId => { + let preRoute = playerData.findRoute(preId); + return preRoute && preRoute.hasPass; + }); + if(!hasPass) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_PRE_NOT_PASS); + } + let rewards = stringToRewardParam(route.reward); + let playerRecord = await ActivityDragonBoatModel.record(serverId, activityId, playerData.roundIndex, roleId, { todayIndex: playerData.todayIndex, id, time: new Date(), rewards }) + playerData.setPlayerRecords(playerRecord); + + await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_DRAGON_BOAT); + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + route: playerData.findRoute(id)?.getShowResult() + }); + } + + /** + * @description 挑战结束 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof DragonBoatHandler + */ + async gameEnd(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let route = playerData.findRoute(id); + if(!route) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_ROUTE_NOTFOUND); + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + route: route.getShowResult(), + goods: route.resultReward + }); + } + + /** + * @description 购买次数 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof DragonBoatHandler + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // 可购买次数 + if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_BUY_COUNT_OVER); + if(playerData.todayPlayCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_CANNOT_BUY); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_DRAGON_BOAT_BUY_COST); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 保存数据 + let buildResult = await ActivityDragonBoatModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); + // 更新数据 + playerData.setPlayerRecords(buildResult); + + return resResult(STATUS.SUCCESS, { + activityId, + maxBuyCnt: playerData.maxBuyCnt, + buyCnt: playerData.buyCnt + }); + } +} + diff --git a/game-server/app/servers/activity/handler/entertainHandler.ts b/game-server/app/servers/activity/handler/entertainHandler.ts index 8a9e84a26..c92c0a1d0 100644 --- a/game-server/app/servers/activity/handler/entertainHandler.ts +++ b/game-server/app/servers/activity/handler/entertainHandler.ts @@ -1,132 +1,133 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { getRandSingleEelm, parseNumberList, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getPlayerEntertainData, getPlayerEntertainDataShow } from '../../../services/activity/entertainService'; -import { ActivityEntertainRecModel } from '../../../db/ActivityEntertainRec'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new EntertainHandler(app); -} - -export class EntertainHandler { - constructor(private app: Application) { - } - - /** - * @description 获取火神祭祀活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof EntertainHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerEntertainDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 宴请 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof EntertainHandler - */ - async invite(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerEntertainData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); - - let pool = playerData.heroes.filter(hero => { - if(hero.num >= hero.maxNum) return false; - for(let condition of hero.conditionArr) { - if(condition.type == 1 && playerData.invitedHeroNum < condition.param) return false; - if(condition.type == 2 && playerData.invitedHids.indexOf(condition.param) == -1) return false; - } - return true; - }); - if(pool.length <= 0) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); - let randResult = getRandSingleEelm(pool); - if(!randResult) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); - - let rewards = stringToRewardParam(randResult.reward); - let todayIndex = playerData.todayIndex; // 免费挑战算在第几天 - if(playerData.todayPlayCnt >= playerData.freeCntDaily && playerData.playCnt < playerData.freeCnt) { - let playerRecord = await ActivityEntertainRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - let records = playerRecord?.record||[]; - for(let i = 1; i <= todayIndex; i++) { - let times = records.filter(cur => cur.todayIndex == i).length; - playerData.playCnt += times; - if(times < playerData.freeCntDaily) { - todayIndex = i; break; - } - } - } - - let playerRecord = await ActivityEntertainRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { todayIndex, id: randResult.id, hid: randResult.hid, index: randResult.index, time: new Date(), reward: randResult.reward }) - let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_ENTERTAIN); - playerData.todayPlayCnt = 0; - playerData.playCnt = 0; - playerData.freeCnt = playerData.freeCntDaily * playerData.todayIndex; - for(let hero of playerData.heroes) hero.num = 0; - playerData.setPlayerRecords(playerRecord); - let newRandResult = playerData.heroes.find(cur => cur.id == randResult.id); - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - curHero: newRandResult?.getShowResult(), - goods - }); - } - - /** - * @description 购买次数 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof EntertainHandler - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerEntertainData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // 可购买次数 - if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_ENTERTAIN_BUY_COUNT_OVER); - // if(playerData.todayPlayCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_CANNOT_BUY); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 保存数据 - let buildResult = await ActivityEntertainRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); - // // 更新数据 - playerData.updateBuyCnt(buildResult); - - return resResult(STATUS.SUCCESS, { - activityId, - maxBuyCnt: playerData.maxBuyCnt, - buyCnt: playerData.buyCnt - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { getRandSingleEelm, parseNumberList, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getPlayerEntertainData, getPlayerEntertainDataShow } from '../../../services/activity/entertainService'; +import { ActivityEntertainRecModel } from '@db/ActivityEntertainRec'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new EntertainHandler(app); +} + +export class EntertainHandler { + constructor(private app: Application) { + } + + /** + * @description 获取火神祭祀活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof EntertainHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerEntertainDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 宴请 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof EntertainHandler + */ + async invite(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerEntertainData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); + + let pool = playerData.heroes.filter(hero => { + if(hero.num >= hero.maxNum) return false; + for(let condition of hero.conditionArr) { + if(condition.type == 1 && playerData.invitedHeroNum < condition.param) return false; + if(condition.type == 2 && playerData.invitedHids.indexOf(condition.param) == -1) return false; + } + return true; + }); + if(pool.length <= 0) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); + let randResult = getRandSingleEelm(pool); + if(!randResult) return resResult(STATUS.ACTIVITY_ENTERTAIN_NO_NUM); + + let rewards = stringToRewardParam(randResult.reward); + let todayIndex = playerData.todayIndex; // 免费挑战算在第几天 + if(playerData.todayPlayCnt >= playerData.freeCntDaily && playerData.playCnt < playerData.freeCnt) { + let playerRecord = await ActivityEntertainRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + let records = playerRecord?.record||[]; + for(let i = 1; i <= todayIndex; i++) { + let times = records.filter(cur => cur.todayIndex == i).length; + playerData.playCnt += times; + if(times < playerData.freeCntDaily) { + todayIndex = i; break; + } + } + } + + let playerRecord = await ActivityEntertainRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { todayIndex, id: randResult.id, hid: randResult.hid, index: randResult.index, time: new Date(), reward: randResult.reward }) + let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_ENTERTAIN); + playerData.todayPlayCnt = 0; + playerData.playCnt = 0; + playerData.freeCnt = playerData.freeCntDaily * playerData.todayIndex; + for(let hero of playerData.heroes) hero.num = 0; + playerData.setPlayerRecords(playerRecord); + let newRandResult = playerData.heroes.find(cur => cur.id == randResult.id); + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + curHero: newRandResult?.getShowResult(), + goods + }); + } + + /** + * @description 购买次数 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof EntertainHandler + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerEntertainData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // 可购买次数 + if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_ENTERTAIN_BUY_COUNT_OVER); + // if(playerData.todayPlayCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_DRAGON_BOAT_CANNOT_BUY); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 保存数据 + let buildResult = await ActivityEntertainRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); + // // 更新数据 + playerData.updateBuyCnt(buildResult); + + return resResult(STATUS.SUCCESS, { + activityId, + maxBuyCnt: playerData.maxBuyCnt, + buyCnt: playerData.buyCnt + }); + } +} + diff --git a/game-server/app/servers/activity/handler/firstGiftHandler.ts b/game-server/app/servers/activity/handler/firstGiftHandler.ts index c7eb2a8f6..cde75d2c7 100644 --- a/game-server/app/servers/activity/handler/firstGiftHandler.ts +++ b/game-server/app/servers/activity/handler/firstGiftHandler.ts @@ -1,92 +1,93 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { FIRST_GIFT_STATE, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerFirstGiftData, getPlayerFirstGiftDataShow } from '../../../services/activity/firstGiftService'; -import { RoleModel } from '../../../db/Role'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityFirstGiftModel } from '../../../db/ActivityFirstGift'; -import { RewardParam } from '../../../domain/activityField/rewardField'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new FirstGiftHandler(app); -} - -export class FirstGiftHandler { - constructor(private app: Application) { - } - - /************************首充礼包****************************/ - - /**首冲活动按玩家注册时间 - * 不充,首充活动就一直在那里 - * @description 获取首充礼包数据 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof FirstGiftHandler - */ - async getFirstGiftActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerFirstGiftDataShow(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let { totalPay } = await RoleModel.findByRoleId(roleId); - if (totalPay > 0) {//奖励开启 - - } - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 领取礼包奖励 - * @param {{ activityId: number, index: number}} msg - * @param {BackendSession} session - * @memberof FirstGiftHandler - */ - async getFirstGiftReward(msg: { activityId: number, pageIndex: number }, session: BackendSession) { - const { activityId, pageIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerFirstGiftData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let playerPageData = playerData.findPageByIndex(pageIndex); - if (playerPageData.state === FIRST_GIFT_STATE.NOT_PAY) { - return resResult(STATUS.ACTIVITY_FIRST_GIFT_NOT_OPEN); - } - let items = playerPageData.getCanReceiveItems(); - if (items.length === 0) { - return resResult(STATUS.ACTIVITY_REWARDED); - } - let rewardArray: RewardParam[] = []; - let indexArray: number[] = []; - for (let item of items) { - rewardArray.push(...stringToRewardParam(item.reward)); - indexArray.push(item.index) - item.isReceive = true; - } - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.FIRST_GIFT); - - let isOver = playerPageData.isComplete(); - let playerRecord = await ActivityFirstGiftModel.addRecord(activityId, roleId, pageIndex, indexArray, isOver); - playerPageData.setPlayerRecord(playerRecord); - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, pageIndex, state: playerPageData.state }, - items: items - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { FIRST_GIFT_STATE, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerFirstGiftData, getPlayerFirstGiftDataShow } from '../../../services/activity/firstGiftService'; +import { RoleModel } from '@db/Role'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityFirstGiftModel } from '@db/ActivityFirstGift'; +import { RewardParam } from '@domain/activityField/rewardField'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new FirstGiftHandler(app); +} + +export class FirstGiftHandler { + constructor(private app: Application) { + } + + /************************首充礼包****************************/ + + /**首冲活动按玩家注册时间 + * 不充,首充活动就一直在那里 + * @description 获取首充礼包数据 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof FirstGiftHandler + */ + async getFirstGiftActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerFirstGiftDataShow(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let { totalPay } = await RoleModel.findByRoleId(roleId); + if (totalPay > 0) {//奖励开启 + + } + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 领取礼包奖励 + * @param {{ activityId: number, index: number}} msg + * @param {BackendSession} session + * @memberof FirstGiftHandler + */ + async getFirstGiftReward(msg: { activityId: number, pageIndex: number }, session: BackendSession) { + const { activityId, pageIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerFirstGiftData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let playerPageData = playerData.findPageByIndex(pageIndex); + if (playerPageData.state === FIRST_GIFT_STATE.NOT_PAY) { + return resResult(STATUS.ACTIVITY_FIRST_GIFT_NOT_OPEN); + } + let items = playerPageData.getCanReceiveItems(); + if (items.length === 0) { + return resResult(STATUS.ACTIVITY_REWARDED); + } + let rewardArray: RewardParam[] = []; + let indexArray: number[] = []; + for (let item of items) { + rewardArray.push(...stringToRewardParam(item.reward)); + indexArray.push(item.index) + item.isReceive = true; + } + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.FIRST_GIFT); + + let isOver = playerPageData.isComplete(); + let playerRecord = await ActivityFirstGiftModel.addRecord(activityId, roleId, pageIndex, indexArray, isOver); + playerPageData.setPlayerRecord(playerRecord); + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, pageIndex, state: playerPageData.state }, + items: items + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/forgeHandler.ts b/game-server/app/servers/activity/handler/forgeHandler.ts index 18e610ff8..d37513c72 100644 --- a/game-server/app/servers/activity/handler/forgeHandler.ts +++ b/game-server/app/servers/activity/handler/forgeHandler.ts @@ -1,117 +1,118 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getMetialStr, getPlayerForgeData, getPlayerForgeDataShow } from '../../../services/activity/forgeService'; -import { ActivityForgeModel } from '../../../db/ActivityForge'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ForgeHandler(app); -} - -export class ForgeHandler { - constructor(private app: Application) { - } - - /** - * @description 获取火神祭祀活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async getForgeActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerForgeDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 铸造 - * @param {{ activityId: number, id: number, material: {id: number, count: number}[]}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async build(msg: { activityId: number, id: number, material: {id: number, count: number}[] }, session: BackendSession) { - const { activityId, id, material } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerForgeData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let materialCnt = material.reduce((pre, cur) => pre + cur.count, 0); - if(materialCnt <= 0) return resResult(STATUS.ACTIVITY_MATERIAL_COUNT_NOT_ZERO); - - let manual = playerData.findManual(id); - if(!manual) return resResult(STATUS.ACTIVITY_MANUAL_NOT_FOUND); - // 解锁日期 - if(manual.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_MANUAL_DAY_LOCK); - - // 铸造次数 - if(manual.buildCnt >= manual.freeCnt + manual.buyCnt) return resResult(STATUS.ACTIVITY_BUILD_COUNT); - // 配比是否正确 - let isSuccess = manual.checkMaterial(material); - // 扣材料 - let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.ACT_FORGE_BUILD); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - // 保存数据 - let buildResult = await ActivityForgeModel.build(serverId, activityId, roleId, playerData.roundIndex, id, { todayIndex: playerData.todayIndex, isSuccess, material: getMetialStr(material) }); - // 更新数据 - manual.setPlayerData(buildResult, playerData.todayIndex, playerData.hint); - let activityGoods = undefined; - if(isSuccess) { - let { goods } = await addReward(roleId, roleName, sid, serverId, stringToRewardParam(manual.reward), ITEM_CHANGE_REASON.ACT_FORGE_BUILD); - activityGoods = goods; - } - - return resResult(STATUS.SUCCESS, { - isSuccess, - curManual: manual, - activityGoods - }); - } - - /** - * @description 购买次数 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async buyCnt(msg: { activityId: number, id: number, count: number }, session: BackendSession) { - const { activityId, id, count } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerForgeData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let manual = playerData.findManual(id); - if(!manual) return resResult(STATUS.ACTIVITY_MANUAL_NOT_FOUND); - // 解锁日期 - if(manual.buyCnt >= manual.maxBuyCnt) return resResult(STATUS.ACTIVITY_BUY_CNT_MAX); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.consume), ITEM_CHANGE_REASON.ACT_FORGE_BUILD); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 保存数据 - let buildResult = await ActivityForgeModel.buyCnt(serverId, activityId, roleId, playerData.roundIndex, id, count); - // 更新数据 - manual.setPlayerData(buildResult, playerData.todayIndex); - - return resResult(STATUS.SUCCESS, { - curManual: manual - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getMetialStr, getPlayerForgeData, getPlayerForgeDataShow } from '../../../services/activity/forgeService'; +import { ActivityForgeModel } from '@db/ActivityForge'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ForgeHandler(app); +} + +export class ForgeHandler { + constructor(private app: Application) { + } + + /** + * @description 获取火神祭祀活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async getForgeActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerForgeDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 铸造 + * @param {{ activityId: number, id: number, material: {id: number, count: number}[]}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async build(msg: { activityId: number, id: number, material: {id: number, count: number}[] }, session: BackendSession) { + const { activityId, id, material } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerForgeData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let materialCnt = material.reduce((pre, cur) => pre + cur.count, 0); + if(materialCnt <= 0) return resResult(STATUS.ACTIVITY_MATERIAL_COUNT_NOT_ZERO); + + let manual = playerData.findManual(id); + if(!manual) return resResult(STATUS.ACTIVITY_MANUAL_NOT_FOUND); + // 解锁日期 + if(manual.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_MANUAL_DAY_LOCK); + + // 铸造次数 + if(manual.buildCnt >= manual.freeCnt + manual.buyCnt) return resResult(STATUS.ACTIVITY_BUILD_COUNT); + // 配比是否正确 + let isSuccess = manual.checkMaterial(material); + // 扣材料 + let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.ACT_FORGE_BUILD); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + // 保存数据 + let buildResult = await ActivityForgeModel.build(serverId, activityId, roleId, playerData.roundIndex, id, { todayIndex: playerData.todayIndex, isSuccess, material: getMetialStr(material) }); + // 更新数据 + manual.setPlayerData(buildResult, playerData.todayIndex, playerData.hint); + let activityGoods = undefined; + if(isSuccess) { + let { goods } = await addReward(roleId, roleName, sid, serverId, stringToRewardParam(manual.reward), ITEM_CHANGE_REASON.ACT_FORGE_BUILD); + activityGoods = goods; + } + + return resResult(STATUS.SUCCESS, { + isSuccess, + curManual: manual, + activityGoods + }); + } + + /** + * @description 购买次数 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async buyCnt(msg: { activityId: number, id: number, count: number }, session: BackendSession) { + const { activityId, id, count } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerForgeData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let manual = playerData.findManual(id); + if(!manual) return resResult(STATUS.ACTIVITY_MANUAL_NOT_FOUND); + // 解锁日期 + if(manual.buyCnt >= manual.maxBuyCnt) return resResult(STATUS.ACTIVITY_BUY_CNT_MAX); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.consume), ITEM_CHANGE_REASON.ACT_FORGE_BUILD); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 保存数据 + let buildResult = await ActivityForgeModel.buyCnt(serverId, activityId, roleId, playerData.roundIndex, id, count); + // 更新数据 + manual.setPlayerData(buildResult, playerData.todayIndex); + + return resResult(STATUS.SUCCESS, { + curManual: manual + }); + } +} + diff --git a/game-server/app/servers/activity/handler/gachaHandler.ts b/game-server/app/servers/activity/handler/gachaHandler.ts index 81209cb1e..29950dd62 100644 --- a/game-server/app/servers/activity/handler/gachaHandler.ts +++ b/game-server/app/servers/activity/handler/gachaHandler.ts @@ -1,547 +1,548 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { resResult, shouldRefresh, getRandSingleEelm, getGachaRemainFloor } from "../../../pubUtils/util"; -import { STATUS, GACHA_TYPE, HERO_QUALITY_TYPE, TASK_TYPE, ITEM_CHANGE_REASON, } from "../../../consts"; -import { gameData, getDefArtifactByGid } from "../../../pubUtils/data"; -import { UserGachaModel } from "../../../db/UserGacha"; -import { refreshGacha, getGachaList, getVisitedHeroList, GachaPull, GachaResults, getDicGachaByGachaCnt, getNormalGachaId, getDicGachas } from "../../../services/activity/gachaService"; -import { RoleModel } from "../../../db/Role"; -import { HeroModel } from "../../../db/Hero"; -import { handleCost, addItems } from "../../../services/role/rewardService"; -import { getZeroPointD, getTimeFun } from "../../../pubUtils/timeUtil"; -import { UserGachaRecModel } from "../../../db/UserGachaRec"; -import { RECRUIT } from "../../../pubUtils/dicParam"; -import { getActivityById } from "../../../services/activity/activityService"; -import { checkTaskInGacha } from "../../../services/task/taskService"; -import { createHeroes } from "../../../services/role/createHero"; -import { getGuideGachaData } from "../../../services/activity/gachaService"; -import { getPlayerNewHeroGachaData } from "../../../services/activity/newHeroService"; -import { isHeroHidden } from "../../../services/dataService"; -import { GachaResultIndb } from "../../../domain/activityField/gachaField"; -import { CreateHeroParam } from "../../../domain/roleField/hero"; -import { ItemInter, RewardInter } from "../../../pubUtils/interface"; -import { getPlayerAuthorGachaData } from "../../../services/activity/authorGachaService"; -import { ActivityAuthorGachaRecModel, ActivityAuthorGachaRecModelType } from "../../../db/AuthorGachaRec"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GachaHandler(app); -} - -export class GachaHandler { - constructor(private app: Application) { - } - - /** - * @description 获取抽卡列表 元宝招募、友情点招募、求贤若渴 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async getGachaList(msg: {}, session: BackendSession) { - const { } = msg; - const roleId: string = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId, 'gachaHasGuide'); - const list = await getGachaList(roleId); - - return resResult(STATUS.SUCCESS, { hasInit: !!role.gachaHasGuide, list }); - } - - /** - * @description 抽卡,所有抽卡类型都 - * @param {{ gachaId: number, activityId: number, count: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async pull(msg: { gachaId: number, activityId: number, count: number }, session: BackendSession) { - const { gachaId, activityId, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - let dicGacha = gameData.gacha.get(gachaId); - if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let userGacha = await UserGachaModel.findByRole(roleId, gachaId, activityId); - userGacha = await refreshGacha(dicGacha, userGacha); - let { freeCount, pickHero, count: historyCount, hope, floor } = userGacha; - if ((dicGacha.gachaType == GACHA_TYPE.ASSIGN || dicGacha.gachaType == GACHA_TYPE.ACTIVITY) && !pickHero) return resResult(STATUS.GACHA_NOT_ASSIGN); - - let resultList: GachaResultIndb[] = [], heroInfo: CreateHeroParam[] = [], items: RewardInter[] = [], consume: ItemInter[] = []; - for(let { dic, min, max } of getDicGachas(dicGacha.gachaType, historyCount, count)) { - if(dicGacha.gachaType != GACHA_TYPE.NORMAL && dic.id != gachaId) continue; - // console.log('##########', dic, min, max) - let _count = max + 1 - min; - let gachaPull = new GachaPull(dic, { hope, floor, pickHero }); - let userHeroes = await HeroModel.findByRole(roleId); - let { resultList: _resultList, heroInfo: _heroInfo, items: _items } = gachaPull.pull(_count, userHeroes); - let { hope: _hope, floor: _floor } = gachaPull.getUserGachaParam(); - resultList.push(..._resultList); heroInfo.push(..._heroInfo); items.push(..._items); - hope = _hope; floor = _floor; - - let costNum = _count; - if (count == 1 && dic.free.count > 0) { // 单抽的时候免费 - if (count > dic.free.count - freeCount) { - costNum = _count - dic.free.count + freeCount; - freeCount = dic.free.count; - } else { - costNum = 0; - freeCount += _count; - } - } - // 消耗东西 - if (costNum > 0) { - let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * costNum } }); - consume.push(...cost); - } - } - - // console.log('##### consume', consume) - - // 消耗东西 - if (consume.length > 0) { - let costResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.GACHA_PULL); - if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); - } - - // 给东西 - // console.log('****', heroInfo) - let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); - await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); - // 更新数据 - userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { - freeCount, hope, floor, count: historyCount + count - }); - let newDicGacha = getDicGachaByGachaCnt(dicGacha, userGacha.count); - - await UserGachaRecModel.createRec(roleId, gachaId, activityId, count, resultList); - if(dicGacha.isTask) await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, false); - - //百家争鸣祈灵 - let playerData = await getPlayerAuthorGachaData(activityId, serverId, roleId); - let dbAuthorGacha:ActivityAuthorGachaRecModelType; - if (playerData) { - dbAuthorGacha = await ActivityAuthorGachaRecModel.updateGachaCnt(serverId, activityId, playerData.roundIndex, roleId, gachaId, count); - } - - return resResult(STATUS.SUCCESS, { - gachaId, activityId, - isFree: freeCount < newDicGacha.free.count, cost: newDicGacha.cost, - count: userGacha.count, point: userGacha.point, floor, hope, - // heroes: resultHeroes, - addHeros: heroes, - result: resultList, - remainFloor: getGachaRemainFloor(gachaId, floor), - authorGachaCnt:dbAuthorGacha?.gachaCnt||0, - }); - } - - /** - * @description 设置心愿单 - * @param {{ gachaId: number, hope: { id: number, hid: number }[] }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async setHope(msg: { gachaId: number, hope: { id: number, hid: number }[] }, session: BackendSession) { - const { gachaId, hope } = msg; - const roleId: string = session.get('roleId'); - let dicGacha = gameData.gacha.get(gachaId); - if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - for (let { hid } of hope) { - if (dicGacha.gachaType == GACHA_TYPE.NORMAL && hid != 0) { - let dicRecruit = gameData.recruit.get(hid); - if (!dicRecruit || !dicRecruit.canHope) { - return resResult(STATUS.GACHA_HOPE_NOT_GOLD); - } - } - if (dicGacha.gachaType == GACHA_TYPE.ARTIFACT && hid != 0) { - let dicArtifact = getDefArtifactByGid(hid); - if (!dicArtifact || !dicArtifact.canHope) { - return resResult(STATUS.GACHA_HOPE_NOT_GOLD); - } - } - } - let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); - let { hope: userHope = []} = await refreshGacha(gameData.gacha.get(gachaId), userGacha); - for (let { id, hid = 0 } of hope) { - let curHope = userHope.find(cur => cur.id == id); - if(curHope) { - if(curHope.hasGet) { - continue; - } else { - curHope.hid = hid; - curHope.hasGet = false; - } - } else { - userHope.push({ id, hid, hasGet: false }) - } - } - userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { hope: userHope }); - - return resResult(STATUS.SUCCESS, { - gachaId, - hope: userGacha.hope - }); - } - - /** - * @description 转盘 - * @param {{ gachaId: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async drawTurnTable(msg: { gachaId: number }, session: BackendSession) { - const { gachaId } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - - let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); - let { point, turntable, costPoint } = userGacha; - if (point < RECRUIT.RECRUIT_BONUS_RECRUIT) return resResult(STATUS.GACHA_TURNTABLE_POINT_NOT_ENOUGH); - - let turntablePool: { quality: number, count: number, planId: number }[] = []; - for (let { quality, count, planId } of gameData.gachaTurntable) { - let myTurntable = turntable.find(cur => cur.quality == quality); - if (!myTurntable || !myTurntable.hasGet) { - turntablePool.push({ quality, count, planId }); - } - } - if (turntablePool.length <= 0) { // 重置 - turntable = []; turntablePool = gameData.gachaTurntable; - } - - let randTurntable = getRandSingleEelm(turntablePool); - let { quality, count, planId } = randTurntable; - - let userHeroes = await HeroModel.findByRole(roleId); - let gachaResults = new GachaResults(); - gachaResults.addPlan(planId); - gachaResults.processDetail(null, count); - let { items, heroInfo, resultList } = gachaResults.transferToFinalResult(userHeroes); - - // 给东西 - // console.log('****', heroInfo) - let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); - await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); - // 更新数据 - await UserGachaRecModel.createRec(roleId, 0, 0, count, resultList); - - // 记录 - let myTurntable = turntable.find(cur => cur.quality == quality); - if (!myTurntable) { - myTurntable = { quality, hasGet: false }; - turntable.push(myTurntable); - } - myTurntable.hasGet = true; - // 扣除积分 - userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { turntable, costPoint: costPoint + 1 }); - - return resResult(STATUS.SUCCESS, { - gachaId, - point: userGacha.point, - turntable: userGacha.turntable, - result: resultList, - addHeros: heroes, - // heroes: resultHeroes - }); - } - - - /** - * @description 求贤若渴&限时招募里面设置pick武将 - * @param {{ gachaId: number, pickHero: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async setPickHero(msg: { gachaId: number, activityId: number, pickHero: number }, session: BackendSession) { - const { gachaId, activityId = 0, pickHero } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - - if(isHeroHidden(pickHero)) return resResult(STATUS.HERO_IS_HIDDEN); - - let dicHero = gameData.hero.get(pickHero); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if(activityId > 0) { - let data = await getPlayerNewHeroGachaData(activityId, serverId, roleId); - if(!data.isPickHero(pickHero)) return resResult(STATUS.GACHA_CAN_NOT_PICK); - } - - let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { pickHero }); - - return resResult(STATUS.SUCCESS, { - gachaId, - activityId, - pickHero: userGacha.pickHero - }); - - } - - /** - * @description 今天拜访过的武将 - * @param {{ }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async getVisitedHero(msg: {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - - let visitedHero = await getVisitedHeroList(roleId); - - return resResult(STATUS.SUCCESS, { - hids: visitedHero - }); - } - - /** - * @description 拜访武将 - * @param {{ hid: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async visitHero(msg: { hid: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { hid } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicRecruit = gameData.recruit.get(hid); - if (!dicRecruit || !dicRecruit.canVisit) return resResult(STATUS.GACHA_CAN_NOT_PICK); - let { pieceId } = dicHero; - - let gachaId = getNormalGachaId(); - let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, gachaId, 0); - if (shouldRefresh(refVisitedTime, new Date())) { - visitedHero = []; - refVisitedTime = getZeroPointD(); - } - if (visitedHero.includes(hid)) { - return resResult(STATUS.GACHA_HAS_VISITED); - } - if (visitedHero.length >= RECRUIT.RECRUIT_DAILY_RECRUIT_SHARD) { - return resResult(STATUS.GACHA_VISITED_COUNT_OVER); - } - - visitedHero.push(hid); - let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { visitedHero, refVisitedTime }); - let goods = await addItems(roleId, roleName, sid, [{ id: pieceId, count: RECRUIT.RECRUIT_SHARD_LIMIT }], ITEM_CHANGE_REASON.VISIT_HERO); - - return resResult(STATUS.SUCCESS, { - hids: userGacha.visitedHero, - goods - }); - } - - /** - * @description 获取特殊抽卡数据 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async getGuideGachaData(msg: { activityId: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - - const { activityId } = msg; - if(!activityId) return resResult(STATUS.SUCCESS); - - let playerData = await getGuideGachaData(serverId, activityId, roleId); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 预抽卡 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async guidePull(msg: { activityId: number; }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - const count = 10; - - const { activityId } = msg; - let playerData = await getGuideGachaData(serverId, activityId, roleId); - if(!playerData) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); - - const gachaId = playerData.gachaId; - const dicGacha = gameData.gacha.get(gachaId); - if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if(!playerData.canPull()) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); - - if(playerData.pullCnt == 0) { - // 消耗东西 - let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * count } }); - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.GACHA_PULL); - if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); - } - - let userHeroes = await HeroModel.findByRole(roleId); - let gachaPull = new GachaPull(dicGacha); - let { resultList } = gachaPull.pull(count, userHeroes); - - let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { guideResultList: resultList }, { pullCnt: 1 }); - playerData.setPlayerData(userGacha); - if(playerData.autoSave()) { // 最后几次自动保存 - await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); - } - - return resResult(STATUS.SUCCESS, { - activityId, - pullCnt: playerData.pullCnt, - result: playerData.latest, - candidates: playerData.candidates - }); - } - - /** - * @description 将结果保存到候选列表 - * @param {{ id: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async saveToCandidates(msg: { activityId: number, id: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - - const { activityId, id } = msg; - let playerData = await getGuideGachaData(serverId, activityId, roleId); - if(!playerData) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); - let gachaId = playerData.gachaId; - const dicGacha = gameData.gacha.get(gachaId); - if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let result = playerData.setCandidate(id); - if(!result) return resResult(STATUS.GACHA_GUIDE_NOT_DO) - - let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); - playerData.setPlayerData(userGacha); - - return resResult(STATUS.SUCCESS, { - activityId, - pullCnt: playerData.pullCnt, - candidates: playerData.candidates - }); - } - - /** - * @description 确定使用某个结果 - * @param {{ id: number }} msg - * @param {BackendSession} session - * @memberof GachaHandler - */ - async decide(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - const count = 10; - - let playerData = await getGuideGachaData(serverId, activityId, roleId); - if(!playerData || !playerData.canDecide()) return resResult(STATUS.GACHA_GUIDE_HAS_DONE); - let gachaId = playerData.gachaId; - const dicGacha = gameData.gacha.get(gachaId); - if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let candidate = playerData.chooseCandidate(id); - if(!candidate) return resResult(STATUS.GACHA_GUIDE_NO_CANDIDATE); - - let userHeroes = await HeroModel.findByRole(roleId); - let results = new GachaResults(); - results.addBySimpleResult(candidate.list); - let { items, heroInfo, resultList } = results.transferToFinalResult(userHeroes); - - let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); - playerData.setPlayerData(userGacha); - - // 给东西 - let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); - await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); - // 更新数据 - await UserGachaRecModel.createRec(roleId, gachaId, 0, count, resultList); - - // 任务 - if(dicGacha.isTask) await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, true); - - return resResult(STATUS.SUCCESS, { - activityId, - pullCnt: playerData.pullCnt, - addHeros: heroes, - result: resultList - }); - } - - async debugClearGachaRecord(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - let serverId = session.get('serverId'); - await UserGachaModel.deleteMany({ roleId }); - - return resResult(STATUS.SUCCESS); - } - - async test(msg: { gachaId: number, count: number, isGuide: boolean }, session: BackendSession) { - const { gachaId, count, isGuide } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const dicGacha = gameData.gacha.get(gachaId); - console.log(`====== map of content ${gachaId} ====== start`) - - let mapOfContent = new Map(); - - let hope = []; - let floor = []; - - let n = Math.ceil(count/10/200); - let sum = 0; - - function cal(num: number) { - for(let i = 0; i < 200; i++) { - console.log(num, i) - let gachaPull = new GachaPull(dicGacha, { floor, hope, pickHero: 1 }); - let { resultList } = gachaPull.pull(10, []); - let { hope: _hope, floor: _floor } = gachaPull.getUserGachaParam(); - floor = _floor; - hope = _hope; - - gachaPull = undefined; - - for(let { planId } of resultList ) { - if(!mapOfContent.has(planId)) { - mapOfContent.set(planId, 1); - } else { - mapOfContent.set(planId, mapOfContent.get(planId) + 1); - } - sum++; - } - } - } - - let num = 0; - cal(num); - let interval = setInterval(() => { - if (++num < n) { - cal(num); - } else { - console.log(`====== map of content ${gachaId} sum: ${sum} ======`) - console.log('planId \t count') - for(let [ planId, count ] of mapOfContent) { - console.log(`${planId} \t ${count}`); - } - clearInterval(interval); - } - }, 50) - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { resResult, shouldRefresh, getRandSingleEelm, getGachaRemainFloor } from "@pubUtils/util"; +import { STATUS, GACHA_TYPE, HERO_QUALITY_TYPE, TASK_TYPE, ITEM_CHANGE_REASON, } from "../../../consts"; +import { gameData, getDefArtifactByGid } from "@pubUtils/data"; +import { UserGachaModel } from "@db/UserGacha"; +import { refreshGacha, getGachaList, getVisitedHeroList, GachaPull, GachaResults, getDicGachaByGachaCnt, getNormalGachaId, getDicGachas } from "../../../services/activity/gachaService"; +import { RoleModel } from "@db/Role"; +import { HeroModel } from "@db/Hero"; +import { handleCost, addItems } from "../../../services/role/rewardService"; +import { getZeroPointD, getTimeFun } from "@pubUtils/timeUtil"; +import { UserGachaRecModel } from "@db/UserGachaRec"; +import { RECRUIT } from "@pubUtils/dicParam"; +import { getActivityById } from "../../../services/activity/activityService"; +import { checkTaskInGacha } from "../../../services/task/taskService"; +import { createHeroes } from "../../../services/role/createHero"; +import { getGuideGachaData } from "../../../services/activity/gachaService"; +import { getPlayerNewHeroGachaData } from "../../../services/activity/newHeroService"; +import { isHeroHidden } from "../../../services/dataService"; +import { GachaResultIndb } from "@domain/activityField/gachaField"; +import { CreateHeroParam } from "@domain/roleField/hero"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; +import { getPlayerAuthorGachaData } from "../../../services/activity/authorGachaService"; +import { ActivityAuthorGachaRecModel, ActivityAuthorGachaRecModelType } from "@db/AuthorGachaRec"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GachaHandler(app); +} + +export class GachaHandler { + constructor(private app: Application) { + } + + /** + * @description 获取抽卡列表 元宝招募、友情点招募、求贤若渴 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async getGachaList(msg: {}, session: BackendSession) { + const { } = msg; + const roleId: string = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId, 'gachaHasGuide'); + const list = await getGachaList(roleId); + + return resResult(STATUS.SUCCESS, { hasInit: !!role.gachaHasGuide, list }); + } + + /** + * @description 抽卡,所有抽卡类型都 + * @param {{ gachaId: number, activityId: number, count: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async pull(msg: { gachaId: number, activityId: number, count: number }, session: BackendSession) { + const { gachaId, activityId, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + let dicGacha = gameData.gacha.get(gachaId); + if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let userGacha = await UserGachaModel.findByRole(roleId, gachaId, activityId); + userGacha = await refreshGacha(dicGacha, userGacha); + let { freeCount, pickHero, count: historyCount, hope, floor } = userGacha; + if ((dicGacha.gachaType == GACHA_TYPE.ASSIGN || dicGacha.gachaType == GACHA_TYPE.ACTIVITY) && !pickHero) return resResult(STATUS.GACHA_NOT_ASSIGN); + + let resultList: GachaResultIndb[] = [], heroInfo: CreateHeroParam[] = [], items: RewardInter[] = [], consume: ItemInter[] = []; + for(let { dic, min, max } of getDicGachas(dicGacha.gachaType, historyCount, count)) { + if(dicGacha.gachaType != GACHA_TYPE.NORMAL && dic.id != gachaId) continue; + // console.log('##########', dic, min, max) + let _count = max + 1 - min; + let gachaPull = new GachaPull(dic, { hope, floor, pickHero }); + let userHeroes = await HeroModel.findByRole(roleId); + let { resultList: _resultList, heroInfo: _heroInfo, items: _items } = gachaPull.pull(_count, userHeroes); + let { hope: _hope, floor: _floor } = gachaPull.getUserGachaParam(); + resultList.push(..._resultList); heroInfo.push(..._heroInfo); items.push(..._items); + hope = _hope; floor = _floor; + + let costNum = _count; + if (count == 1 && dic.free.count > 0) { // 单抽的时候免费 + if (count > dic.free.count - freeCount) { + costNum = _count - dic.free.count + freeCount; + freeCount = dic.free.count; + } else { + costNum = 0; + freeCount += _count; + } + } + // 消耗东西 + if (costNum > 0) { + let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * costNum } }); + consume.push(...cost); + } + } + + // console.log('##### consume', consume) + + // 消耗东西 + if (consume.length > 0) { + let costResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.GACHA_PULL); + if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); + } + + // 给东西 + // console.log('****', heroInfo) + let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); + await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); + // 更新数据 + userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { + freeCount, hope, floor, count: historyCount + count + }); + let newDicGacha = getDicGachaByGachaCnt(dicGacha, userGacha.count); + + await UserGachaRecModel.createRec(roleId, gachaId, activityId, count, resultList); + if(dicGacha.isTask) await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, false); + + //百家争鸣祈灵 + let playerData = await getPlayerAuthorGachaData(activityId, serverId, roleId); + let dbAuthorGacha:ActivityAuthorGachaRecModelType; + if (playerData) { + dbAuthorGacha = await ActivityAuthorGachaRecModel.updateGachaCnt(serverId, activityId, playerData.roundIndex, roleId, gachaId, count); + } + + return resResult(STATUS.SUCCESS, { + gachaId, activityId, + isFree: freeCount < newDicGacha.free.count, cost: newDicGacha.cost, + count: userGacha.count, point: userGacha.point, floor, hope, + // heroes: resultHeroes, + addHeros: heroes, + result: resultList, + remainFloor: getGachaRemainFloor(gachaId, floor), + authorGachaCnt:dbAuthorGacha?.gachaCnt||0, + }); + } + + /** + * @description 设置心愿单 + * @param {{ gachaId: number, hope: { id: number, hid: number }[] }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async setHope(msg: { gachaId: number, hope: { id: number, hid: number }[] }, session: BackendSession) { + const { gachaId, hope } = msg; + const roleId: string = session.get('roleId'); + let dicGacha = gameData.gacha.get(gachaId); + if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + for (let { hid } of hope) { + if (dicGacha.gachaType == GACHA_TYPE.NORMAL && hid != 0) { + let dicRecruit = gameData.recruit.get(hid); + if (!dicRecruit || !dicRecruit.canHope) { + return resResult(STATUS.GACHA_HOPE_NOT_GOLD); + } + } + if (dicGacha.gachaType == GACHA_TYPE.ARTIFACT && hid != 0) { + let dicArtifact = getDefArtifactByGid(hid); + if (!dicArtifact || !dicArtifact.canHope) { + return resResult(STATUS.GACHA_HOPE_NOT_GOLD); + } + } + } + let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); + let { hope: userHope = []} = await refreshGacha(gameData.gacha.get(gachaId), userGacha); + for (let { id, hid = 0 } of hope) { + let curHope = userHope.find(cur => cur.id == id); + if(curHope) { + if(curHope.hasGet) { + continue; + } else { + curHope.hid = hid; + curHope.hasGet = false; + } + } else { + userHope.push({ id, hid, hasGet: false }) + } + } + userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { hope: userHope }); + + return resResult(STATUS.SUCCESS, { + gachaId, + hope: userGacha.hope + }); + } + + /** + * @description 转盘 + * @param {{ gachaId: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async drawTurnTable(msg: { gachaId: number }, session: BackendSession) { + const { gachaId } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + + let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); + let { point, turntable, costPoint } = userGacha; + if (point < RECRUIT.RECRUIT_BONUS_RECRUIT) return resResult(STATUS.GACHA_TURNTABLE_POINT_NOT_ENOUGH); + + let turntablePool: { quality: number, count: number, planId: number }[] = []; + for (let { quality, count, planId } of gameData.gachaTurntable) { + let myTurntable = turntable.find(cur => cur.quality == quality); + if (!myTurntable || !myTurntable.hasGet) { + turntablePool.push({ quality, count, planId }); + } + } + if (turntablePool.length <= 0) { // 重置 + turntable = []; turntablePool = gameData.gachaTurntable; + } + + let randTurntable = getRandSingleEelm(turntablePool); + let { quality, count, planId } = randTurntable; + + let userHeroes = await HeroModel.findByRole(roleId); + let gachaResults = new GachaResults(); + gachaResults.addPlan(planId); + gachaResults.processDetail(null, count); + let { items, heroInfo, resultList } = gachaResults.transferToFinalResult(userHeroes); + + // 给东西 + // console.log('****', heroInfo) + let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); + await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); + // 更新数据 + await UserGachaRecModel.createRec(roleId, 0, 0, count, resultList); + + // 记录 + let myTurntable = turntable.find(cur => cur.quality == quality); + if (!myTurntable) { + myTurntable = { quality, hasGet: false }; + turntable.push(myTurntable); + } + myTurntable.hasGet = true; + // 扣除积分 + userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { turntable, costPoint: costPoint + 1 }); + + return resResult(STATUS.SUCCESS, { + gachaId, + point: userGacha.point, + turntable: userGacha.turntable, + result: resultList, + addHeros: heroes, + // heroes: resultHeroes + }); + } + + + /** + * @description 求贤若渴&限时招募里面设置pick武将 + * @param {{ gachaId: number, pickHero: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async setPickHero(msg: { gachaId: number, activityId: number, pickHero: number }, session: BackendSession) { + const { gachaId, activityId = 0, pickHero } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + + if(isHeroHidden(pickHero)) return resResult(STATUS.HERO_IS_HIDDEN); + + let dicHero = gameData.hero.get(pickHero); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if(activityId > 0) { + let data = await getPlayerNewHeroGachaData(activityId, serverId, roleId); + if(!data.isPickHero(pickHero)) return resResult(STATUS.GACHA_CAN_NOT_PICK); + } + + let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { pickHero }); + + return resResult(STATUS.SUCCESS, { + gachaId, + activityId, + pickHero: userGacha.pickHero + }); + + } + + /** + * @description 今天拜访过的武将 + * @param {{ }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async getVisitedHero(msg: {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + + let visitedHero = await getVisitedHeroList(roleId); + + return resResult(STATUS.SUCCESS, { + hids: visitedHero + }); + } + + /** + * @description 拜访武将 + * @param {{ hid: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async visitHero(msg: { hid: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { hid } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicRecruit = gameData.recruit.get(hid); + if (!dicRecruit || !dicRecruit.canVisit) return resResult(STATUS.GACHA_CAN_NOT_PICK); + let { pieceId } = dicHero; + + let gachaId = getNormalGachaId(); + let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, gachaId, 0); + if (shouldRefresh(refVisitedTime, new Date())) { + visitedHero = []; + refVisitedTime = getZeroPointD(); + } + if (visitedHero.includes(hid)) { + return resResult(STATUS.GACHA_HAS_VISITED); + } + if (visitedHero.length >= RECRUIT.RECRUIT_DAILY_RECRUIT_SHARD) { + return resResult(STATUS.GACHA_VISITED_COUNT_OVER); + } + + visitedHero.push(hid); + let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { visitedHero, refVisitedTime }); + let goods = await addItems(roleId, roleName, sid, [{ id: pieceId, count: RECRUIT.RECRUIT_SHARD_LIMIT }], ITEM_CHANGE_REASON.VISIT_HERO); + + return resResult(STATUS.SUCCESS, { + hids: userGacha.visitedHero, + goods + }); + } + + /** + * @description 获取特殊抽卡数据 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async getGuideGachaData(msg: { activityId: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + + const { activityId } = msg; + if(!activityId) return resResult(STATUS.SUCCESS); + + let playerData = await getGuideGachaData(serverId, activityId, roleId); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 预抽卡 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async guidePull(msg: { activityId: number; }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + const count = 10; + + const { activityId } = msg; + let playerData = await getGuideGachaData(serverId, activityId, roleId); + if(!playerData) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); + + const gachaId = playerData.gachaId; + const dicGacha = gameData.gacha.get(gachaId); + if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if(!playerData.canPull()) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); + + if(playerData.pullCnt == 0) { + // 消耗东西 + let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * count } }); + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.GACHA_PULL); + if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); + } + + let userHeroes = await HeroModel.findByRole(roleId); + let gachaPull = new GachaPull(dicGacha); + let { resultList } = gachaPull.pull(count, userHeroes); + + let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { guideResultList: resultList }, { pullCnt: 1 }); + playerData.setPlayerData(userGacha); + if(playerData.autoSave()) { // 最后几次自动保存 + await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); + } + + return resResult(STATUS.SUCCESS, { + activityId, + pullCnt: playerData.pullCnt, + result: playerData.latest, + candidates: playerData.candidates + }); + } + + /** + * @description 将结果保存到候选列表 + * @param {{ id: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async saveToCandidates(msg: { activityId: number, id: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + + const { activityId, id } = msg; + let playerData = await getGuideGachaData(serverId, activityId, roleId); + if(!playerData) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); + let gachaId = playerData.gachaId; + const dicGacha = gameData.gacha.get(gachaId); + if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let result = playerData.setCandidate(id); + if(!result) return resResult(STATUS.GACHA_GUIDE_NOT_DO) + + let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); + playerData.setPlayerData(userGacha); + + return resResult(STATUS.SUCCESS, { + activityId, + pullCnt: playerData.pullCnt, + candidates: playerData.candidates + }); + } + + /** + * @description 确定使用某个结果 + * @param {{ id: number }} msg + * @param {BackendSession} session + * @memberof GachaHandler + */ + async decide(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + const count = 10; + + let playerData = await getGuideGachaData(serverId, activityId, roleId); + if(!playerData || !playerData.canDecide()) return resResult(STATUS.GACHA_GUIDE_HAS_DONE); + let gachaId = playerData.gachaId; + const dicGacha = gameData.gacha.get(gachaId); + if (!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let candidate = playerData.chooseCandidate(id); + if(!candidate) return resResult(STATUS.GACHA_GUIDE_NO_CANDIDATE); + + let userHeroes = await HeroModel.findByRole(roleId); + let results = new GachaResults(); + results.addBySimpleResult(candidate.list); + let { items, heroInfo, resultList } = results.transferToFinalResult(userHeroes); + + let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { candidates: playerData.candidates }); + playerData.setPlayerData(userGacha); + + // 给东西 + let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); + await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); + // 更新数据 + await UserGachaRecModel.createRec(roleId, gachaId, 0, count, resultList); + + // 任务 + if(dicGacha.isTask) await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, true); + + return resResult(STATUS.SUCCESS, { + activityId, + pullCnt: playerData.pullCnt, + addHeros: heroes, + result: resultList + }); + } + + async debugClearGachaRecord(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + let serverId = session.get('serverId'); + await UserGachaModel.deleteMany({ roleId }); + + return resResult(STATUS.SUCCESS); + } + + async test(msg: { gachaId: number, count: number, isGuide: boolean }, session: BackendSession) { + const { gachaId, count, isGuide } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const dicGacha = gameData.gacha.get(gachaId); + console.log(`====== map of content ${gachaId} ====== start`) + + let mapOfContent = new Map(); + + let hope = []; + let floor = []; + + let n = Math.ceil(count/10/200); + let sum = 0; + + function cal(num: number) { + for(let i = 0; i < 200; i++) { + console.log(num, i) + let gachaPull = new GachaPull(dicGacha, { floor, hope, pickHero: 1 }); + let { resultList } = gachaPull.pull(10, []); + let { hope: _hope, floor: _floor } = gachaPull.getUserGachaParam(); + floor = _floor; + hope = _hope; + + gachaPull = undefined; + + for(let { planId } of resultList ) { + if(!mapOfContent.has(planId)) { + mapOfContent.set(planId, 1); + } else { + mapOfContent.set(planId, mapOfContent.get(planId) + 1); + } + sum++; + } + } + } + + let num = 0; + cal(num); + let interval = setInterval(() => { + if (++num < n) { + cal(num); + } else { + console.log(`====== map of content ${gachaId} sum: ${sum} ======`) + console.log('planId \t count') + for(let [ planId, count ] of mapOfContent) { + console.log(`${planId} \t ${count}`); + } + clearInterval(interval); + } + }, 50) + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/groupShopHandler.ts b/game-server/app/servers/activity/handler/groupShopHandler.ts index 8ea7b84dc..2dd80cce5 100644 --- a/game-server/app/servers/activity/handler/groupShopHandler.ts +++ b/game-server/app/servers/activity/handler/groupShopHandler.ts @@ -1,152 +1,153 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { resResult } from "../../../pubUtils/util"; -import { STATUS, ITEM_CHANGE_REASON, GROUP_SHOP_PRICE_STATUS, PUSH_ROUTE, ACTIVITY_TYPE, } from "../../../consts"; -import { getGroupShopData, getGroupShopDataShow, getGroupShopPriceStatus, getGroupShopServerData, refundGroupShop } from "../../../services/activity/groupShopService"; -import { addItems, getGoldObject, handleCost } from "../../../services/role/rewardService"; -import { ActivityGroupShopUserRecModel, GroupShopBuyRecord } from "../../../db/ActivityGroupShopUserRec"; -import { ActivityGroupShopRecModel, GroupShopRecord } from "../../../db/ActivityGroupShopRec"; -import { pick } from "underscore"; -import { addRoleToGroupShopChannel, leaveGroupShopChannel } from "../../../services/chatChannelService"; -import { sendMessageToGroupShopWithSuc } from "../../../services/pushService"; -import { getActivitiesByType } from "../../../services/activity/activityService"; -import { GroupShopData } from "../../../domain/activityField/groupShopField"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GroupShopHandler(app); -} - -export class GroupShopHandler { - constructor(private app: Application) { - } - - /** - * @description 1. 进入团购主页面 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GroupShopHandler - */ - async getGroupShopPage(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - - let playerData = await getGroupShopDataShow(activityId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - await addRoleToGroupShopChannel(roleId, sid); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 2. 离开团购主页面 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GroupShopHandler - */ - async leaveGroupShopPage(msg: { activityId: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - - await leaveGroupShopChannel(roleId, sid) - return resResult(STATUS.SUCCESS); - } - - /** - * @description 3. 购买 - * @param {{}} msg - * @param {BackendSession} session - * @memberof GroupShopHandler - */ - async buy(msg: { activityId: number, price: number, itemId: number, buyCnt: number }, session: BackendSession) { - const { activityId, price: clientPrice, itemId, buyCnt } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - - let playerData = await getGroupShopData(activityId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let item = playerData.findItemById(itemId); - if (!item) return resResult(STATUS.ACTIVITY_GROUP_SHOP_ITEM_NOT_FOUND); - if(!item.checkBuyCnt(buyCnt)) return resResult(STATUS.ACTIVITY_GROUP_SHOP_BUY_CNT_MAX); - - let curDiscount = item.getCurDiscount(); - let priceStatus = getGroupShopPriceStatus(clientPrice, curDiscount.price); - if(priceStatus == GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH) return resResult(STATUS.ACTIVITY_GROUP_SHOP_PRICE_ERR); - let cost = [getGoldObject(curDiscount.price)]; - let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY); - if(!result) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - - // 玩家添加次数 - let playerRecord = await ActivityGroupShopUserRecModel.incBuyCnt(activityId, roleId, itemId, item.id, buyCnt, new GroupShopBuyRecord(curDiscount, buyCnt)); - playerData.setPlayerRecord([playerRecord]); - // 全服添加次数 - let serverRecord = await ActivityGroupShopRecModel.incBuyCnt(activityId, itemId, item.id, buyCnt); - let isRankUp = playerData.incAllRecord(serverRecord); - - item = playerData.findItemById(itemId); - let nextDiscount = item.getCurDiscount(); - if(isRankUp) { - await ActivityGroupShopRecModel.addRecord(activityId, itemId, new GroupShopRecord(nextDiscount)); - // 推送频道 - await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId, itemId, sum: item.sum, curDiscount: nextDiscount }); - } - let reward = [{ id: item.id, count: item.count * buyCnt }]; - let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY); - - return resResult(STATUS.SUCCESS, { - curItem: pick(item, ['itemId', 'id', 'sum', 'hasBoughtCnt']), - goods, - status: priceStatus, - oldDiscount: curDiscount, - nextDiscount - }); - } - - async debugRefund(msg: {}, session: BackendSession) { - await refundGroupShop(true); - return resResult(STATUS.SUCCESS); - } - - async debugSetSum(msg: { itemId: number, sum: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId = session.get('serverId'); - let { itemId = 0, sum = 0 } = msg; - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GROUP_SHOP); - if(activities.length <= 0) return resResult(STATUS.ACTIVITY_MISSING); - for(let activityData of activities) { - let recs = await ActivityGroupShopRecModel.debugSetSum(activityData.activityId, itemId, sum); - let playerData = new GroupShopData(activityData, 0, 0); - playerData.setRecords(recs); - - let items = itemId == 0? playerData.items: [playerData.findItemById(itemId)]; - for(let item of items) { - if(!item) continue; - let nextDiscount = item.getCurDiscount(); - // 推送频道 - await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId: activityData.activityId, itemId: item.itemId, sum: item.sum, curDiscount: nextDiscount }); - } - } - let playerData = await getGroupShopDataShow(activities[0].activityId, roleId); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - async debugClearCnt(msg: { }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId = session.get('serverId'); - - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GROUP_SHOP); - if(activities.length <= 0) return resResult(STATUS.ACTIVITY_MISSING); - - for(let activityData of activities) { - await ActivityGroupShopUserRecModel.clearCnt(activityData.activityId, roleId); - } - - let playerData = await getGroupShopDataShow(activities[0].activityId, roleId); - return resResult(STATUS.SUCCESS, { playerData }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { resResult } from "@pubUtils/util"; +import { STATUS, ITEM_CHANGE_REASON, GROUP_SHOP_PRICE_STATUS, PUSH_ROUTE, ACTIVITY_TYPE, } from "../../../consts"; +import { getGroupShopData, getGroupShopDataShow, getGroupShopPriceStatus, getGroupShopServerData, refundGroupShop } from "../../../services/activity/groupShopService"; +import { addItems, getGoldObject, handleCost } from "../../../services/role/rewardService"; +import { ActivityGroupShopUserRecModel, GroupShopBuyRecord } from "@db/ActivityGroupShopUserRec"; +import { ActivityGroupShopRecModel, GroupShopRecord } from "@db/ActivityGroupShopRec"; +import { pick } from "underscore"; +import { addRoleToGroupShopChannel, leaveGroupShopChannel } from "../../../services/chatChannelService"; +import { sendMessageToGroupShopWithSuc } from "../../../services/pushService"; +import { getActivitiesByType } from "../../../services/activity/activityService"; +import { GroupShopData } from "@domain/activityField/groupShopField"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GroupShopHandler(app); +} + +export class GroupShopHandler { + constructor(private app: Application) { + } + + /** + * @description 1. 进入团购主页面 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GroupShopHandler + */ + async getGroupShopPage(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + + let playerData = await getGroupShopDataShow(activityId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + await addRoleToGroupShopChannel(roleId, sid); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 2. 离开团购主页面 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GroupShopHandler + */ + async leaveGroupShopPage(msg: { activityId: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + + await leaveGroupShopChannel(roleId, sid) + return resResult(STATUS.SUCCESS); + } + + /** + * @description 3. 购买 + * @param {{}} msg + * @param {BackendSession} session + * @memberof GroupShopHandler + */ + async buy(msg: { activityId: number, price: number, itemId: number, buyCnt: number }, session: BackendSession) { + const { activityId, price: clientPrice, itemId, buyCnt } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + + let playerData = await getGroupShopData(activityId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let item = playerData.findItemById(itemId); + if (!item) return resResult(STATUS.ACTIVITY_GROUP_SHOP_ITEM_NOT_FOUND); + if(!item.checkBuyCnt(buyCnt)) return resResult(STATUS.ACTIVITY_GROUP_SHOP_BUY_CNT_MAX); + + let curDiscount = item.getCurDiscount(); + let priceStatus = getGroupShopPriceStatus(clientPrice, curDiscount.price); + if(priceStatus == GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH) return resResult(STATUS.ACTIVITY_GROUP_SHOP_PRICE_ERR); + let cost = [getGoldObject(curDiscount.price)]; + let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY); + if(!result) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + + // 玩家添加次数 + let playerRecord = await ActivityGroupShopUserRecModel.incBuyCnt(activityId, roleId, itemId, item.id, buyCnt, new GroupShopBuyRecord(curDiscount, buyCnt)); + playerData.setPlayerRecord([playerRecord]); + // 全服添加次数 + let serverRecord = await ActivityGroupShopRecModel.incBuyCnt(activityId, itemId, item.id, buyCnt); + let isRankUp = playerData.incAllRecord(serverRecord); + + item = playerData.findItemById(itemId); + let nextDiscount = item.getCurDiscount(); + if(isRankUp) { + await ActivityGroupShopRecModel.addRecord(activityId, itemId, new GroupShopRecord(nextDiscount)); + // 推送频道 + await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId, itemId, sum: item.sum, curDiscount: nextDiscount }); + } + let reward = [{ id: item.id, count: item.count * buyCnt }]; + let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY); + + return resResult(STATUS.SUCCESS, { + curItem: pick(item, ['itemId', 'id', 'sum', 'hasBoughtCnt']), + goods, + status: priceStatus, + oldDiscount: curDiscount, + nextDiscount + }); + } + + async debugRefund(msg: {}, session: BackendSession) { + await refundGroupShop(true); + return resResult(STATUS.SUCCESS); + } + + async debugSetSum(msg: { itemId: number, sum: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId = session.get('serverId'); + let { itemId = 0, sum = 0 } = msg; + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GROUP_SHOP); + if(activities.length <= 0) return resResult(STATUS.ACTIVITY_MISSING); + for(let activityData of activities) { + let recs = await ActivityGroupShopRecModel.debugSetSum(activityData.activityId, itemId, sum); + let playerData = new GroupShopData(activityData, 0, 0); + playerData.setRecords(recs); + + let items = itemId == 0? playerData.items: [playerData.findItemById(itemId)]; + for(let item of items) { + if(!item) continue; + let nextDiscount = item.getCurDiscount(); + // 推送频道 + await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId: activityData.activityId, itemId: item.itemId, sum: item.sum, curDiscount: nextDiscount }); + } + } + let playerData = await getGroupShopDataShow(activities[0].activityId, roleId); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + async debugClearCnt(msg: { }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId = session.get('serverId'); + + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GROUP_SHOP); + if(activities.length <= 0) return resResult(STATUS.ACTIVITY_MISSING); + + for(let activityData of activities) { + await ActivityGroupShopUserRecModel.clearCnt(activityData.activityId, roleId); + } + + let playerData = await getGroupShopDataShow(activities[0].activityId, roleId); + return resResult(STATUS.SUCCESS, { playerData }); + } +} + diff --git a/game-server/app/servers/activity/handler/growthFundHandler.ts b/game-server/app/servers/activity/handler/growthFundHandler.ts index dbb25ab9c..84b918299 100644 --- a/game-server/app/servers/activity/handler/growthFundHandler.ts +++ b/game-server/app/servers/activity/handler/growthFundHandler.ts @@ -1,84 +1,85 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerGrowthFundData } from '../../../services/activity/growthFundService'; -import { GrowthFundItem } from '../../../domain/activityField/growthFundField'; -import { ActivityGrowthFundModel } from '../../../db/ActivityGrowthFund'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new GrowthFundHandler(app); -} - -export class GrowthFundHandler { - constructor(private app: Application) { - } - - /************************成长基金****************************/ - - /** - * @description 获取成长基金活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof GrowthFundHandler - */ - async getGrowthFundActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerGrowthFundData(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_GROWTH_FUND_END); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取成长基金奖励 - * @param {{ activityId: number, pageIndex: number, cellIndex: number}} msg - * @param {BackendSession} session - * @memberof GrowthFundHandler - */ - async getGrowthFundCellReward(msg: { activityId: number, pageIndex: number, cellIndex: number }, session: BackendSession) { - const { activityId, pageIndex, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerGrowthFundData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (playerData.isVipActivity() && !playerData.isBuy(pageIndex)) {//vip高阶活动,需要购买 - return resResult(STATUS.ACTIVITY_NEED_BUY); - } - - let growthFundItemData: GrowthFundItem = playerData.findGrowthFundItem(pageIndex, cellIndex); - if (!growthFundItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!growthFundItemData.isComplete) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - let hasReceive = await ActivityGrowthFundModel.exists({ roleId, activityId, pageIndex, cellIndex }); - if (hasReceive) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityGrowthFundModel.addRecord(activityId, roleId, pageIndex, cellIndex); - - let rewardParamArr: Array = stringToRewardParam(growthFundItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_FUND) - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, pageIndex, cellIndex }, - item: growthFundItemData - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerGrowthFundData } from '../../../services/activity/growthFundService'; +import { GrowthFundItem } from '@domain/activityField/growthFundField'; +import { ActivityGrowthFundModel } from '@db/ActivityGrowthFund'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new GrowthFundHandler(app); +} + +export class GrowthFundHandler { + constructor(private app: Application) { + } + + /************************成长基金****************************/ + + /** + * @description 获取成长基金活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof GrowthFundHandler + */ + async getGrowthFundActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerGrowthFundData(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_GROWTH_FUND_END); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取成长基金奖励 + * @param {{ activityId: number, pageIndex: number, cellIndex: number}} msg + * @param {BackendSession} session + * @memberof GrowthFundHandler + */ + async getGrowthFundCellReward(msg: { activityId: number, pageIndex: number, cellIndex: number }, session: BackendSession) { + const { activityId, pageIndex, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerGrowthFundData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (playerData.isVipActivity() && !playerData.isBuy(pageIndex)) {//vip高阶活动,需要购买 + return resResult(STATUS.ACTIVITY_NEED_BUY); + } + + let growthFundItemData: GrowthFundItem = playerData.findGrowthFundItem(pageIndex, cellIndex); + if (!growthFundItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!growthFundItemData.isComplete) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + let hasReceive = await ActivityGrowthFundModel.exists({ roleId, activityId, pageIndex, cellIndex }); + if (hasReceive) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityGrowthFundModel.addRecord(activityId, roleId, pageIndex, cellIndex); + + let rewardParamArr: Array = stringToRewardParam(growthFundItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_FUND) + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, pageIndex, cellIndex }, + item: growthFundItemData + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/growthHandler.ts b/game-server/app/servers/activity/handler/growthHandler.ts index 844599d08..b4edcf254 100644 --- a/game-server/app/servers/activity/handler/growthHandler.ts +++ b/game-server/app/servers/activity/handler/growthHandler.ts @@ -1,124 +1,125 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerGrowthData } from '../../../services/activity/growthService'; -import { GrowthItem, PointRewardItem } from '../../../domain/activityField/growthField'; -import { ActivityGrowthModel } from '../../../db/ActivityGrowth'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityGrowthPointModel } from '../../../db/ActivityGrowthPoint'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new GrowthHandler(app); -} - -export class GrowthHandler { - constructor(private app: Application) { - } - - /************************成长任务****************************/ - - /** - * @description 获取成长任务活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof GrowthHandler - */ - async getGrowthActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerGrowthData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取成长任务每天完成的单个奖励 - * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg - * @param {BackendSession} session - * @memberof GrowthHandler - */ - async getGrowthCellReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerGrowthData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let growthItemData: GrowthItem = playerData.findGrowthItem(dayIndex, cellIndex, type); - if (!growthItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!growthItemData.isComplete()) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (!growthItemData.canReceive()) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - if(growthItemData.dayIndex < playerData.today()) { - return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); - } - - - await ActivityGrowthModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - let rewardParamArr: Array = stringToRewardParam(growthItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_REWARD) - - growthItemData.receiveRewardCount = 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex, type }, - item: growthItemData, - })); - } - - /** - * @description 成长任务每天奖章兑换奖励 - * @param {{ activityId: number, id: number}} msg - * @param {BackendSession} session - * @memberof GrowthHandler - */ - async getGrowthDayReward(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerGrowthData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let pointItemData: PointRewardItem = playerData.findPointItem(id); - if (!pointItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (playerData.getTotalPoint() < pointItemData.progress) { - return resResult(STATUS.ACTIVITY_NO_POINT); - } - if (pointItemData.getPointReward) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityGrowthPointModel.addRecord(serverId, activityId, roleId, id); - - let rewardParamArr: Array = stringToRewardParam(pointItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_DAY_EXCHANGE) - - - pointItemData.getPointReward = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, id }, - item: pointItemData, - })); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerGrowthData } from '../../../services/activity/growthService'; +import { GrowthItem, PointRewardItem } from '@domain/activityField/growthField'; +import { ActivityGrowthModel } from '@db/ActivityGrowth'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityGrowthPointModel } from '@db/ActivityGrowthPoint'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new GrowthHandler(app); +} + +export class GrowthHandler { + constructor(private app: Application) { + } + + /************************成长任务****************************/ + + /** + * @description 获取成长任务活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof GrowthHandler + */ + async getGrowthActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerGrowthData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取成长任务每天完成的单个奖励 + * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg + * @param {BackendSession} session + * @memberof GrowthHandler + */ + async getGrowthCellReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerGrowthData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let growthItemData: GrowthItem = playerData.findGrowthItem(dayIndex, cellIndex, type); + if (!growthItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!growthItemData.isComplete()) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (!growthItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + if(growthItemData.dayIndex < playerData.today()) { + return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + } + + + await ActivityGrowthModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + let rewardParamArr: Array = stringToRewardParam(growthItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_REWARD) + + growthItemData.receiveRewardCount = 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex, type }, + item: growthItemData, + })); + } + + /** + * @description 成长任务每天奖章兑换奖励 + * @param {{ activityId: number, id: number}} msg + * @param {BackendSession} session + * @memberof GrowthHandler + */ + async getGrowthDayReward(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerGrowthData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let pointItemData: PointRewardItem = playerData.findPointItem(id); + if (!pointItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (playerData.getTotalPoint() < pointItemData.progress) { + return resResult(STATUS.ACTIVITY_NO_POINT); + } + if (pointItemData.getPointReward) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityGrowthPointModel.addRecord(serverId, activityId, roleId, id); + + let rewardParamArr: Array = stringToRewardParam(pointItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_DAY_EXCHANGE) + + + pointItemData.getPointReward = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, id }, + item: pointItemData, + })); + } +} + diff --git a/game-server/app/servers/activity/handler/guildPayHandler.ts b/game-server/app/servers/activity/handler/guildPayHandler.ts index 4d425680f..d2c9541cc 100644 --- a/game-server/app/servers/activity/handler/guildPayHandler.ts +++ b/game-server/app/servers/activity/handler/guildPayHandler.ts @@ -1,86 +1,87 @@ -import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; -import { isNumber } from 'underscore'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { ActivityGuildPayRecordModel } from '../../../db/ActivityGuildPayRecord'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { resResult } from '../../../pubUtils/util'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getGuildPayDataShow, getGuildPayData } from '../../../services/activity/guildPayService'; - - -export default function (app: Application) { - return new GuildPayHandler(app); -} - -export class GuildPayHandler { - constructor(private app: Application) { - } - - - /** - * @description 获取活动数据 - * @param {{ }} msg - * @param {BackendSession} session - * @memberof GuildPayHandler - */ - async getGuildPayData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - let playerData = await getGuildPayDataShow(serverId, activityId, roleId, guildCode); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description (一键)领取奖励 - * @param {{ }} msg - * @param {BackendSession} session - * @memberof GuildPayHandler - */ - async receiveItems(msg: { activityId: number, cellIndex: number }, session: BackendSession) { - const { activityId, cellIndex } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - if(!isNumber(cellIndex)) return resResult(STATUS.WRONG_PARMS); - - let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let items = playerData.receiveItems(cellIndex); - if(!items) return resResult(STATUS.ACTIVITY_ITEM_CANNOT_RECEIVE); - - - let records: number[] = [], rewards: RewardParam[] = []; - for(let item of items) { - records.push(item.cellIndex); - rewards.push(...stringToRewardParam(item.reward)); - } - await ActivityGuildPayRecordModel.receiveItems(serverId, activityId, playerData.roundIndex, roleId, records); - let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_GUILD_PAY_REWARD); - - return resResult(STATUS.SUCCESS, { items, ...result }); - } - - async getGuildPayMembers(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { - payMemberCnt: playerData.payMemberCnt, - payRecord: playerData.payRecord - }); - } -} +import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; +import { isNumber } from 'underscore'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { ActivityGuildPayRecordModel } from '@db/ActivityGuildPayRecord'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { resResult } from '@pubUtils/util'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getGuildPayDataShow, getGuildPayData } from '../../../services/activity/guildPayService'; + + +export default function (app: Application) { + return new GuildPayHandler(app); +} + +export class GuildPayHandler { + constructor(private app: Application) { + } + + + /** + * @description 获取活动数据 + * @param {{ }} msg + * @param {BackendSession} session + * @memberof GuildPayHandler + */ + async getGuildPayData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let playerData = await getGuildPayDataShow(serverId, activityId, roleId, guildCode); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description (一键)领取奖励 + * @param {{ }} msg + * @param {BackendSession} session + * @memberof GuildPayHandler + */ + async receiveItems(msg: { activityId: number, cellIndex: number }, session: BackendSession) { + const { activityId, cellIndex } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + if(!isNumber(cellIndex)) return resResult(STATUS.WRONG_PARMS); + + let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let items = playerData.receiveItems(cellIndex); + if(!items) return resResult(STATUS.ACTIVITY_ITEM_CANNOT_RECEIVE); + + + let records: number[] = [], rewards: RewardParam[] = []; + for(let item of items) { + records.push(item.cellIndex); + rewards.push(...stringToRewardParam(item.reward)); + } + await ActivityGuildPayRecordModel.receiveItems(serverId, activityId, playerData.roundIndex, roleId, records); + let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_GUILD_PAY_REWARD); + + return resResult(STATUS.SUCCESS, { items, ...result }); + } + + async getGuildPayMembers(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { + payMemberCnt: playerData.payMemberCnt, + payRecord: playerData.payRecord + }); + } +} + diff --git a/game-server/app/servers/activity/handler/limitPackageHandler.ts b/game-server/app/servers/activity/handler/limitPackageHandler.ts index 34d7933ff..a0a411422 100644 --- a/game-server/app/servers/activity/handler/limitPackageHandler.ts +++ b/game-server/app/servers/activity/handler/limitPackageHandler.ts @@ -1,134 +1,135 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { newPlayerLimitPackageActivity, getPlayerLimitPackageData } from '../../../services/activity/limitPackageService'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityShopModel } from '../../../db/ActivityShop'; -import moment = require('moment'); -import { RoleModel } from '../../../db/Role'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new LimitPackageHandler(app); -} - -export class LimitPackageHandler { - constructor(private app: Application) { - } - - /************************新手限定礼包****************************/ - - /** - * @description 获取新手限定活动数据 开服1-7天可以购买,第8天0-5点只能看,不能买 - * @param {{ activityId:number}} msg - * @param {BackendSession} session - * @memberof LimitPackageHandler - */ - async getNewPlayerLimitPackageActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - - let { createTime } = await RoleModel.findByRoleId(roleId); - let createDate = moment(createTime * 1000).toDate(); - let endTime = moment(createDate).startOf('d').add(7, 'd').add(5, 'h').toDate(); - if (new Date() > endTime) { - return resResult(STATUS.ACTIVITY_NEW_PLAYER_GIFT_END); - } - let playerData = await newPlayerLimitPackageActivity(serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - return resResult(STATUS.SUCCESS, { playerData }); - } - - /************************每日每周限购礼包****************************/ - - /** - * @description 获取每日/每周限购礼包数据 - * @param {{ activityId:number, type:number }} msg - * @param {BackendSession} session - * @memberof LimitPackageHandler - */ - async getLimitPackageActivity(msg: { activityId: number, type: number }, session: BackendSession) { - const { activityId, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLimitPackageData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - return resResult(STATUS.SUCCESS, { playerData }); - } - - - /** - * @description 购买礼包 - * @param {{ activityId: number, roundIndex: number, id: number}} msg - * @param {BackendSession} session - * @memberof LimitPackageHandler - */ - async buyGood(msg: { activityId: number, roundIndex: number, id: number }, session: BackendSession) { - const { activityId, roundIndex, id, } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerLimitPackageData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - if (playerData.roundIndex != roundIndex) { - return resResult(STATUS.ACTIVITY_EXPIRE); - } - - switch (playerData.type) { - case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: - { - let { createTime } = await RoleModel.findByRoleId(roleId); - let createDate = moment(createTime * 1000).toDate(); - let endTime = moment(createDate).startOf('d').add(7, 'd').toDate(); - if (new Date() > endTime) { - return resResult(STATUS.ACTIVITY_NEW_PLAYER_LIMIT_PACKAGE_END); - } - break; - } - default: - break; - } - - let item = playerData.findItem(id); - if (!item) { - return resResult(STATUS.ACTIVITY_ID_ERROR); - } - if (item.countMax > 0 && item.buyCount >= item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (item.price > 0) { - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - - //检查资源 - let consume = stringToConsumeParam(item.consume) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let rewardArray = stringToRewardParam(item.reward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); - - await ActivityShopModel.addRecord(activityId, roleId, roundIndex, id, 1); - - item.buyCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, roundIndex, id }, - item: item - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { newPlayerLimitPackageActivity, getPlayerLimitPackageData } from '../../../services/activity/limitPackageService'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityShopModel } from '@db/ActivityShop'; +import moment = require('moment'); +import { RoleModel } from '@db/Role'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new LimitPackageHandler(app); +} + +export class LimitPackageHandler { + constructor(private app: Application) { + } + + /************************新手限定礼包****************************/ + + /** + * @description 获取新手限定活动数据 开服1-7天可以购买,第8天0-5点只能看,不能买 + * @param {{ activityId:number}} msg + * @param {BackendSession} session + * @memberof LimitPackageHandler + */ + async getNewPlayerLimitPackageActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + + let { createTime } = await RoleModel.findByRoleId(roleId); + let createDate = moment(createTime * 1000).toDate(); + let endTime = moment(createDate).startOf('d').add(7, 'd').add(5, 'h').toDate(); + if (new Date() > endTime) { + return resResult(STATUS.ACTIVITY_NEW_PLAYER_GIFT_END); + } + let playerData = await newPlayerLimitPackageActivity(serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + return resResult(STATUS.SUCCESS, { playerData }); + } + + /************************每日每周限购礼包****************************/ + + /** + * @description 获取每日/每周限购礼包数据 + * @param {{ activityId:number, type:number }} msg + * @param {BackendSession} session + * @memberof LimitPackageHandler + */ + async getLimitPackageActivity(msg: { activityId: number, type: number }, session: BackendSession) { + const { activityId, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLimitPackageData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + return resResult(STATUS.SUCCESS, { playerData }); + } + + + /** + * @description 购买礼包 + * @param {{ activityId: number, roundIndex: number, id: number}} msg + * @param {BackendSession} session + * @memberof LimitPackageHandler + */ + async buyGood(msg: { activityId: number, roundIndex: number, id: number }, session: BackendSession) { + const { activityId, roundIndex, id, } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerLimitPackageData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + if (playerData.roundIndex != roundIndex) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + + switch (playerData.type) { + case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: + { + let { createTime } = await RoleModel.findByRoleId(roleId); + let createDate = moment(createTime * 1000).toDate(); + let endTime = moment(createDate).startOf('d').add(7, 'd').toDate(); + if (new Date() > endTime) { + return resResult(STATUS.ACTIVITY_NEW_PLAYER_LIMIT_PACKAGE_END); + } + break; + } + default: + break; + } + + let item = playerData.findItem(id); + if (!item) { + return resResult(STATUS.ACTIVITY_ID_ERROR); + } + if (item.countMax > 0 && item.buyCount >= item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (item.price > 0) { + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + + //检查资源 + let consume = stringToConsumeParam(item.consume) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let rewardArray = stringToRewardParam(item.reward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); + + await ActivityShopModel.addRecord(activityId, roleId, roundIndex, id, 1); + + item.buyCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, roundIndex, id }, + item: item + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/luckyHandler.ts b/game-server/app/servers/activity/handler/luckyHandler.ts index d08266fb7..469559949 100644 --- a/game-server/app/servers/activity/handler/luckyHandler.ts +++ b/game-server/app/servers/activity/handler/luckyHandler.ts @@ -1,98 +1,99 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerLuckyDataShow, getPlayerLuckyData } from '../../../services/activity/luckyService'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { pick } from 'underscore'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityLuckyModel } from '../../../db/ActivityLuckyRec'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new LuckyTurntableNewHandler(app); -} - -export class LuckyTurntableNewHandler { - constructor(private app: Application) { - } - - /************************幸运转盘****************************/ - /** - * @description 幸运转盘活动 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof LuckyHandler - */ - async getTurntableData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyDataShow(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 转转盘 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof LuckyHandler - */ - async pull(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let cost = playerData.getCost(count); - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { result, records, goodResult, pool, floor } = playerData.pull(roleName, count); - await ActivityLuckyModel.updateData(serverId, activityId, roleId, playerData.roundIndex, { ...pick(playerData, ['todayCount', 'count', 'records', 'floorRecord']), refTodayCount: new Date() }); - await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); - - return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count, pool, floor }); - } - - - /** - * @description 领宝箱 - * @param {{ activityId: number, boxCount: number }} msg - * @param {BackendSession} session - * @memberof LuckyHandler - */ - async receiveBox(msg: { activityId: number, boxCount: number }, session: BackendSession) { - const { activityId, boxCount } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let canReceive = playerData.canReceive(boxCount); - if (!canReceive) return resResult(STATUS.BOX_CAN_NOT_RECEIVE); - - let box = playerData.findBox(boxCount); - let rewardArray = stringToRewardParam(box.rewards) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_TURNTABLE_RECEIVE_BOX); - await ActivityLuckyModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, boxCount); - - return resResult(STATUS.SUCCESS, { ...result, box: { ...box, isReceived: true } }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerLuckyDataShow, getPlayerLuckyData } from '../../../services/activity/luckyService'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { pick } from 'underscore'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityLuckyModel } from '@db/ActivityLuckyRec'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new LuckyTurntableNewHandler(app); +} + +export class LuckyTurntableNewHandler { + constructor(private app: Application) { + } + + /************************幸运转盘****************************/ + /** + * @description 幸运转盘活动 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof LuckyHandler + */ + async getTurntableData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyDataShow(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 转转盘 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof LuckyHandler + */ + async pull(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let cost = playerData.getCost(count); + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { result, records, goodResult, pool, floor } = playerData.pull(roleName, count); + await ActivityLuckyModel.updateData(serverId, activityId, roleId, playerData.roundIndex, { ...pick(playerData, ['todayCount', 'count', 'records', 'floorRecord']), refTodayCount: new Date() }); + await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); + + return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count, pool, floor }); + } + + + /** + * @description 领宝箱 + * @param {{ activityId: number, boxCount: number }} msg + * @param {BackendSession} session + * @memberof LuckyHandler + */ + async receiveBox(msg: { activityId: number, boxCount: number }, session: BackendSession) { + const { activityId, boxCount } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let canReceive = playerData.canReceive(boxCount); + if (!canReceive) return resResult(STATUS.BOX_CAN_NOT_RECEIVE); + + let box = playerData.findBox(boxCount); + let rewardArray = stringToRewardParam(box.rewards) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_TURNTABLE_RECEIVE_BOX); + await ActivityLuckyModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, boxCount); + + return resResult(STATUS.SUCCESS, { ...result, box: { ...box, isReceived: true } }); + } +} + diff --git a/game-server/app/servers/activity/handler/luckyTurntableHandler.ts b/game-server/app/servers/activity/handler/luckyTurntableHandler.ts index 5b139dbc9..27cae6baf 100644 --- a/game-server/app/servers/activity/handler/luckyTurntableHandler.ts +++ b/game-server/app/servers/activity/handler/luckyTurntableHandler.ts @@ -1,98 +1,99 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerLuckyTurntableDataShow, getPlayerLuckyTurntableData } from '../../../services/activity/luckyTurntableService'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { ActivityTurntableModel } from '../../../db/ActivityTurntableRec'; -import { pick } from 'underscore'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new LuckyTurntableHandler(app); -} - -export class LuckyTurntableHandler { - constructor(private app: Application) { - } - - /************************幸运转盘****************************/ - /** - * @description 幸运转盘活动 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof LuckyTurntableHandler - */ - async getTurntableData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyTurntableDataShow(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 转转盘 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof LuckyTurntableHandler - */ - async pull(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let cost = playerData.getCost(count); - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { result, records, goodResult } = playerData.pull(roleName, count); - await ActivityTurntableModel.updateData(serverId, activityId, roleId, playerData.roundIndex, {...pick(playerData, ['todayCount', 'count', 'records', 'greatRewardCount']), refTodayCount: new Date()}); - await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); - - return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count }); - } - - - /** - * @description 领宝箱 - * @param {{ activityId: number, boxCount: number }} msg - * @param {BackendSession} session - * @memberof LuckyTurntableHandler - */ - async receiveBox(msg: { activityId: number, boxCount: number }, session: BackendSession) { - const { activityId, boxCount } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - let canReceive = playerData.canReceive(boxCount); - if(!canReceive) return resResult(STATUS.BOX_CAN_NOT_RECEIVE); - - let box = playerData.findBox(boxCount); - let rewardArray = stringToRewardParam(box.rewards) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_TURNTABLE_RECEIVE_BOX); - await ActivityTurntableModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, boxCount); - - return resResult(STATUS.SUCCESS, { ...result, box: {...box, isReceived: true} }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerLuckyTurntableDataShow, getPlayerLuckyTurntableData } from '../../../services/activity/luckyTurntableService'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { ActivityTurntableModel } from '@db/ActivityTurntableRec'; +import { pick } from 'underscore'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new LuckyTurntableHandler(app); +} + +export class LuckyTurntableHandler { + constructor(private app: Application) { + } + + /************************幸运转盘****************************/ + /** + * @description 幸运转盘活动 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof LuckyTurntableHandler + */ + async getTurntableData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyTurntableDataShow(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 转转盘 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof LuckyTurntableHandler + */ + async pull(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let cost = playerData.getCost(count); + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { result, records, goodResult } = playerData.pull(roleName, count); + await ActivityTurntableModel.updateData(serverId, activityId, roleId, playerData.roundIndex, {...pick(playerData, ['todayCount', 'count', 'records', 'greatRewardCount']), refTodayCount: new Date()}); + await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); + + return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count }); + } + + + /** + * @description 领宝箱 + * @param {{ activityId: number, boxCount: number }} msg + * @param {BackendSession} session + * @memberof LuckyTurntableHandler + */ + async receiveBox(msg: { activityId: number, boxCount: number }, session: BackendSession) { + const { activityId, boxCount } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + let canReceive = playerData.canReceive(boxCount); + if(!canReceive) return resResult(STATUS.BOX_CAN_NOT_RECEIVE); + + let box = playerData.findBox(boxCount); + let rewardArray = stringToRewardParam(box.rewards) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.ACT_TURNTABLE_RECEIVE_BOX); + await ActivityTurntableModel.receiveBox(serverId, activityId, roleId, playerData.roundIndex, boxCount); + + return resResult(STATUS.SUCCESS, { ...result, box: {...box, isReceived: true} }); + } +} + diff --git a/game-server/app/servers/activity/handler/midAutumnHandler.ts b/game-server/app/servers/activity/handler/midAutumnHandler.ts index 2b16d9131..b4330b240 100644 --- a/game-server/app/servers/activity/handler/midAutumnHandler.ts +++ b/game-server/app/servers/activity/handler/midAutumnHandler.ts @@ -1,183 +1,184 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { genCode, getRandSingleEelm, parseNumberList, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { ActivityMidAutumnRecModel } from '../../../db/ActivityMidAutumnRec'; -import { RewardInter } from '../../../pubUtils/interface'; -import { getPlayerMidAutumnData, getPlayerMidAutumnDataShow } from '../../../services/activity/midAutumnService'; -import { combineItems } from '../../../services/role/util'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new MidAutumnHandler(app); -} - -export class MidAutumnHandler { - constructor(private app: Application) { - } - - /** - * @description 获取火神祭祀活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof MidAutumnHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMidAutumnDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 游戏开始 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof MidAutumnHandler - */ - async gameStart(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); - - const gameCode = genCode(10); - let playerRecord = await ActivityMidAutumnRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { - todayIndex: playerData.recordTodayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, hasPass: false, isSkip: false - }); - playerData.updatePlayerRecord(playerRecord); - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - gameCode - }); - } - - - /** - * @description 游戏结束 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof MidAutumnHandler - */ - async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean }, session: BackendSession) { - const { activityId, gameCode, isSuccess } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); - - let curRecord = playerData.records.find(cur => cur.gameCode == gameCode); - if(!curRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - if(curRecord.hasPass) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_HAS_PLAY); - - let playerRecord = await ActivityMidAutumnRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), playerData.rewards); - if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - playerData.updatePlayerRecord(playerRecord); - let goods: RewardInter[] = []; - if(isSuccess) { - let rewards = stringToRewardParam(playerData.rewards); - goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.MID_AUTUMN_REWARD) - } - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - gameCode, - goods - }); - } - - /** - * @description 扫荡 - * @param {{ activityId: number, count: number }} msg - * @param {BackendSession} session - * @memberof MidAutumnHandler - */ - async gameSweep(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt + count > playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); - if(playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_SWEEP); - - let rewards: RewardInter[] = []; - for(let i = 0; i < count; i++) { - let playerRecord = await ActivityMidAutumnRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { - todayIndex: playerData.recordTodayIndex, gameCode: 'sweep', time: new Date(), rewards: playerData.rewards, isSuccess: true, hasPass: true, isSkip: true - }); - if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - playerData.updatePlayerRecord(playerRecord); - rewards.push(...stringToRewardParam(playerData.rewards)); - } - - let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.MID_AUTUMN_REWARD); - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - goods - }); - } - - /** - * @description 购买次数 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof MidAutumnHandler - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // 可购买次数 - if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_QIXI_BUY_COUNT_OVER); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 保存数据 - let buildResult = await ActivityMidAutumnRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); - // // 更新数据 - playerData.updatePlayerRecord(buildResult); - - return resResult(STATUS.SUCCESS, { - activityId, - maxBuyCnt: playerData.maxBuyCnt, - buyCnt: playerData.buyCnt - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { genCode, getRandSingleEelm, parseNumberList, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { ActivityMidAutumnRecModel } from '@db/ActivityMidAutumnRec'; +import { RewardInter } from '@pubUtils/interface'; +import { getPlayerMidAutumnData, getPlayerMidAutumnDataShow } from '../../../services/activity/midAutumnService'; +import { combineItems } from '../../../services/role/util'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new MidAutumnHandler(app); +} + +export class MidAutumnHandler { + constructor(private app: Application) { + } + + /** + * @description 获取火神祭祀活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof MidAutumnHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMidAutumnDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 游戏开始 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof MidAutumnHandler + */ + async gameStart(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); + + const gameCode = genCode(10); + let playerRecord = await ActivityMidAutumnRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { + todayIndex: playerData.recordTodayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, hasPass: false, isSkip: false + }); + playerData.updatePlayerRecord(playerRecord); + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + gameCode + }); + } + + + /** + * @description 游戏结束 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof MidAutumnHandler + */ + async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean }, session: BackendSession) { + const { activityId, gameCode, isSuccess } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); + + let curRecord = playerData.records.find(cur => cur.gameCode == gameCode); + if(!curRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + if(curRecord.hasPass) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_HAS_PLAY); + + let playerRecord = await ActivityMidAutumnRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), playerData.rewards); + if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + playerData.updatePlayerRecord(playerRecord); + let goods: RewardInter[] = []; + if(isSuccess) { + let rewards = stringToRewardParam(playerData.rewards); + goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.MID_AUTUMN_REWARD) + } + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + gameCode, + goods + }); + } + + /** + * @description 扫荡 + * @param {{ activityId: number, count: number }} msg + * @param {BackendSession} session + * @memberof MidAutumnHandler + */ + async gameSweep(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt + count > playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_MID_AUTUMN_NO_NUM); + if(playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_SWEEP); + + let rewards: RewardInter[] = []; + for(let i = 0; i < count; i++) { + let playerRecord = await ActivityMidAutumnRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { + todayIndex: playerData.recordTodayIndex, gameCode: 'sweep', time: new Date(), rewards: playerData.rewards, isSuccess: true, hasPass: true, isSkip: true + }); + if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + playerData.updatePlayerRecord(playerRecord); + rewards.push(...stringToRewardParam(playerData.rewards)); + } + + let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.MID_AUTUMN_REWARD); + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + goods + }); + } + + /** + * @description 购买次数 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof MidAutumnHandler + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // 可购买次数 + if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_QIXI_BUY_COUNT_OVER); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 保存数据 + let buildResult = await ActivityMidAutumnRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); + // // 更新数据 + playerData.updatePlayerRecord(buildResult); + + return resResult(STATUS.SUCCESS, { + activityId, + maxBuyCnt: playerData.maxBuyCnt, + buyCnt: playerData.buyCnt + }); + } +} + diff --git a/game-server/app/servers/activity/handler/miniGameHandler.ts b/game-server/app/servers/activity/handler/miniGameHandler.ts index fbf02419d..c1ef45ba4 100644 --- a/game-server/app/servers/activity/handler/miniGameHandler.ts +++ b/game-server/app/servers/activity/handler/miniGameHandler.ts @@ -1,217 +1,218 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, MINI_GAME_TYPE, REDIS_KEY, STATUS, TASK_TYPE } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getPlayerMiniGameData, getPlayerMiniGameDataShow } from '../../../services/activity/miniGameService'; -import { ActivityMiniGameRecModel } from '../../../db/ActivityMiniGameRec'; -import { ActivityMiniGameModel } from '../../../db/ActivityMiniGame'; -import { handleCost } from '../../../services/role/rewardService'; -import { Rank } from '../../../services/rankService'; -import { nowSeconds } from '../../../pubUtils/timeUtil'; -import { RoleRankInfo } from '../../../domain/rank'; -import { getAllServerName } from '../../../services/redisService'; -import { checkTask } from '../../../services/task/taskService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ForgeHandler(app); -} - -export class ForgeHandler { - constructor(private app: Application) { - } - - /** - * @description 小游戏数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async getMiniGameActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 小游戏开始 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async gameStart(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if(playerData.playCnt >= playerData.buyCnt + playerData.freeCnt) return resResult(STATUS.ACTIVITY_MINI_GAME_COUNT_LACK); - let record = await ActivityMiniGameRecModel.gameStart(serverId, activityId, playerData.roundIndex, playerData.todayIndex, roleId, playerData.gameType); - - return resResult(STATUS.SUCCESS, { - activityId, - gameCode: record.gameCode, - playCnt: playerData.playCnt - }); - } - - /** - * @description 小游戏结束 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async gameEnd(msg: { activityId: number, gameCode: string, score: number, params: number[] }, session: BackendSession) { - let { activityId, gameCode, score, params } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // 记录得分&次数 - let record = await ActivityMiniGameRecModel.gameEnd(activityId, roleId, gameCode, score, params); - if(!record) return resResult(STATUS.ACTIVITY_MINI_GAME_RECORD_NOT_FOUND); - - if(playerData.gameType == MINI_GAME_TYPE.CATCH_ZONGZI && score > 100) score = 100; - - let playerRecord = await ActivityMiniGameModel.incScore(serverId, activityId, playerData.roundIndex, roleId, score, playerData.nextRefreshTime); - if(!record) return resResult(STATUS.ACTIVITY_MINI_GAME_RECORD_NOT_FOUND); - playerData.setPlayerData(playerRecord); - playerData.incPlayCnt(); - - let rewards = stringToRewardParam(playerData.reward); - let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_MINI_GAME_REWARD); - - let r = new Rank(REDIS_KEY.ACTIVITY_MINI_GAME, { activityId, roundIndex: playerData.roundIndex }); - await r.setRankWithRoleInfo(roleId, score, nowSeconds(), null, true); - - if(playerData.gameType == MINI_GAME_TYPE.SHOOT) { - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_SHOOT, { score }); - } else if(playerData.gameType == MINI_GAME_TYPE.ERASE) { - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_ERASE, { step: params[0] }); - } else if(playerData.gameType == MINI_GAME_TYPE.EAT_ZONGZI) { - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_EAT_ZONGZI, { score }); - } else if(playerData.gameType == MINI_GAME_TYPE.CATCH_ZONGZI) { - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_CATCH_ZONGZI, { score }); - } else { - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_SCORE, { gameType: playerData.gameType, score }); - await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_STEP, { gameType: playerData.gameType, step: params[0] }); - } - - return resResult(STATUS.SUCCESS, { - activityId, - gameCode, - playCnt: playerData.playCnt, - score: playerData.score, - goods - }); - } - - /** - * @description 购买挑战次数 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_MINI_GAME_BUY_COUNT_MAX); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.consume), ITEM_CHANGE_REASON.ACT_MINI_GAME_BUY_CNT); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let playerRecord = await ActivityMiniGameModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count, playerData.nextRefreshTime); - playerData.setPlayerData(playerRecord); - - return resResult(STATUS.SUCCESS, { - activityId, - buyCnt: playerData.buyCnt, - maxBuyCnt: playerData.maxBuyCnt - }); - } - - /** - * @description 领取宝箱 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async receiveBox(msg: { activityId: number, boxId: number }, session: BackendSession) { - const { activityId, boxId } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let box = playerData.findBox(boxId); - if(!box) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_NOT_FOUND); - if(box.hasReceived) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_HAS_RECEIVED); - if(box.score > playerData.score) return resResult(STATUS.ACTIVITY_MINI_GAME_SCORE_NOT_ENOUGH); - let result = await ActivityMiniGameModel.receiveBox(serverId, activityId, playerData.roundIndex, roleId, boxId); - if(!result) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_HAS_RECEIVED); - playerData.setPlayerData(result); - - let rewards = stringToRewardParam(box.reward); - let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_MINI_GAME_REWARD); - - return resResult(STATUS.SUCCESS, { - activityId, - curBox: playerData.findBox(boxId), - goods - }); - } - - /** - * @description 排行榜 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ForgeHandler - */ - async getRanks(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let serverNames = await getAllServerName(); - let r = new Rank(REDIS_KEY.ACTIVITY_MINI_GAME, { activityId, roundIndex: playerData.roundIndex }); - r.setGenerFieldsFun((obj => { - if(obj instanceof RoleRankInfo) { - return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, serverId: obj.serverId, serverName: serverNames[obj.serverId], num: obj.num } - } - return null - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); - if (!myRank) { - myRank = await r.generMyRankWithRole(roleId, playerData.score, nowSeconds()); - } - - return resResult(STATUS.SUCCESS, { - activityId, - gameType: playerData.gameType, - ranks, myRank - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, MINI_GAME_TYPE, REDIS_KEY, STATUS, TASK_TYPE } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getPlayerMiniGameData, getPlayerMiniGameDataShow } from '../../../services/activity/miniGameService'; +import { ActivityMiniGameRecModel } from '@db/ActivityMiniGameRec'; +import { ActivityMiniGameModel } from '@db/ActivityMiniGame'; +import { handleCost } from '../../../services/role/rewardService'; +import { Rank } from '../../../services/rankService'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { RoleRankInfo } from '@domain/rank'; +import { getAllServerName } from '../../../services/redisService'; +import { checkTask } from '../../../services/task/taskService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ForgeHandler(app); +} + +export class ForgeHandler { + constructor(private app: Application) { + } + + /** + * @description 小游戏数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async getMiniGameActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 小游戏开始 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async gameStart(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if(playerData.playCnt >= playerData.buyCnt + playerData.freeCnt) return resResult(STATUS.ACTIVITY_MINI_GAME_COUNT_LACK); + let record = await ActivityMiniGameRecModel.gameStart(serverId, activityId, playerData.roundIndex, playerData.todayIndex, roleId, playerData.gameType); + + return resResult(STATUS.SUCCESS, { + activityId, + gameCode: record.gameCode, + playCnt: playerData.playCnt + }); + } + + /** + * @description 小游戏结束 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async gameEnd(msg: { activityId: number, gameCode: string, score: number, params: number[] }, session: BackendSession) { + let { activityId, gameCode, score, params } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // 记录得分&次数 + let record = await ActivityMiniGameRecModel.gameEnd(activityId, roleId, gameCode, score, params); + if(!record) return resResult(STATUS.ACTIVITY_MINI_GAME_RECORD_NOT_FOUND); + + if(playerData.gameType == MINI_GAME_TYPE.CATCH_ZONGZI && score > 100) score = 100; + + let playerRecord = await ActivityMiniGameModel.incScore(serverId, activityId, playerData.roundIndex, roleId, score, playerData.nextRefreshTime); + if(!record) return resResult(STATUS.ACTIVITY_MINI_GAME_RECORD_NOT_FOUND); + playerData.setPlayerData(playerRecord); + playerData.incPlayCnt(); + + let rewards = stringToRewardParam(playerData.reward); + let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_MINI_GAME_REWARD); + + let r = new Rank(REDIS_KEY.ACTIVITY_MINI_GAME, { activityId, roundIndex: playerData.roundIndex }); + await r.setRankWithRoleInfo(roleId, score, nowSeconds(), null, true); + + if(playerData.gameType == MINI_GAME_TYPE.SHOOT) { + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_SHOOT, { score }); + } else if(playerData.gameType == MINI_GAME_TYPE.ERASE) { + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_ERASE, { step: params[0] }); + } else if(playerData.gameType == MINI_GAME_TYPE.EAT_ZONGZI) { + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_EAT_ZONGZI, { score }); + } else if(playerData.gameType == MINI_GAME_TYPE.CATCH_ZONGZI) { + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_CATCH_ZONGZI, { score }); + } else { + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_SCORE, { gameType: playerData.gameType, score }); + await checkTask(serverId, roleId, sid, TASK_TYPE.MINI_GAME_STEP, { gameType: playerData.gameType, step: params[0] }); + } + + return resResult(STATUS.SUCCESS, { + activityId, + gameCode, + playCnt: playerData.playCnt, + score: playerData.score, + goods + }); + } + + /** + * @description 购买挑战次数 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_MINI_GAME_BUY_COUNT_MAX); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.consume), ITEM_CHANGE_REASON.ACT_MINI_GAME_BUY_CNT); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let playerRecord = await ActivityMiniGameModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count, playerData.nextRefreshTime); + playerData.setPlayerData(playerRecord); + + return resResult(STATUS.SUCCESS, { + activityId, + buyCnt: playerData.buyCnt, + maxBuyCnt: playerData.maxBuyCnt + }); + } + + /** + * @description 领取宝箱 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async receiveBox(msg: { activityId: number, boxId: number }, session: BackendSession) { + const { activityId, boxId } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let box = playerData.findBox(boxId); + if(!box) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_NOT_FOUND); + if(box.hasReceived) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_HAS_RECEIVED); + if(box.score > playerData.score) return resResult(STATUS.ACTIVITY_MINI_GAME_SCORE_NOT_ENOUGH); + let result = await ActivityMiniGameModel.receiveBox(serverId, activityId, playerData.roundIndex, roleId, boxId); + if(!result) return resResult(STATUS.ACTIVITY_MINI_GAME_BOX_HAS_RECEIVED); + playerData.setPlayerData(result); + + let rewards = stringToRewardParam(box.reward); + let { goods } = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_MINI_GAME_REWARD); + + return resResult(STATUS.SUCCESS, { + activityId, + curBox: playerData.findBox(boxId), + goods + }); + } + + /** + * @description 排行榜 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ForgeHandler + */ + async getRanks(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let serverNames = await getAllServerName(); + let r = new Rank(REDIS_KEY.ACTIVITY_MINI_GAME, { activityId, roundIndex: playerData.roundIndex }); + r.setGenerFieldsFun((obj => { + if(obj instanceof RoleRankInfo) { + return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, serverId: obj.serverId, serverName: serverNames[obj.serverId], num: obj.num } + } + return null + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); + if (!myRank) { + myRank = await r.generMyRankWithRole(roleId, playerData.score, nowSeconds()); + } + + return resResult(STATUS.SUCCESS, { + activityId, + gameType: playerData.gameType, + ranks, myRank + }); + } +} + diff --git a/game-server/app/servers/activity/handler/monthlyFundHandler.ts b/game-server/app/servers/activity/handler/monthlyFundHandler.ts index 29023c4dc..1a16f2184 100644 --- a/game-server/app/servers/activity/handler/monthlyFundHandler.ts +++ b/game-server/app/servers/activity/handler/monthlyFundHandler.ts @@ -1,86 +1,87 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getMonthlyFundData, getMonthlyFundDataShow } from '../../../services/activity/monthlyFundService'; -import { ActivityWeeklyFundModel } from '../../../db/ActivityWeeklyFund'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityMonthlyFundModel } from '../../../db/ActivityMonthlyFund'; -import { monthlyFundSchedule } from '../../../services/timeTaskService'; -import moment = require('moment'); - - -export default function (app: Application) { - new HandlerService(app, {}); - return new MonthlyFundHandler(app); -} - -export class MonthlyFundHandler { - constructor(private app: Application) { - } - - /************************月基金****************************/ - - /** - * @description 获取数据 - * @param {BackendSession} session - * @memberof MonthlyFundHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getMonthlyFundDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 签到 - * @param {BackendSession} session - * @memberof MonthlyFundHandler - */ - async sign(msg: { activityId: number, pageIndex: number, dayIndex: number }, session: BackendSession) { - - const { activityId, pageIndex, dayIndex } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getMonthlyFundData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let pageData = playerData.findPage(pageIndex); - if (!pageData) return resResult(STATUS.ACTIVITY_MISSING); - - if(!pageData.hasBought) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_NOT_BOUGHT); - - let signReward = pageData.findSignReward(dayIndex); - if(!signReward) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_NOT_FOUND); - if(signReward.hasReceived) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_HAS_SIGN); - if(signReward.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_LOCK); - - let record = await ActivityMonthlyFundModel.sign(serverId, activityId, roleId, playerData.roundIndex, pageIndex, dayIndex, playerData.todayIndex); - if(!record) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_HAS_SIGN); - - pageData.setPlayerRecord(record); - if(pageData.hasReceivedAll()) { - await ActivityMonthlyFundModel.setReceivedAll(serverId, activityId, roleId, playerData.roundIndex, pageIndex); - } - - let rewardParamArr = stringToRewardParam(signReward.reward); - let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_MONTHLY_FUND_SIGN); - - return resResult(STATUS.SUCCESS, { - activityId, dayIndex, pageIndex, goods, addHeros - }); - } - - async debugSendMonthlyFundReward(msg: {}, session: BackendSession) { - - await monthlyFundSchedule(parseInt(moment().format('YYYYMM'))); - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getMonthlyFundData, getMonthlyFundDataShow } from '../../../services/activity/monthlyFundService'; +import { ActivityWeeklyFundModel } from '@db/ActivityWeeklyFund'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityMonthlyFundModel } from '@db/ActivityMonthlyFund'; +import { monthlyFundSchedule } from '../../../services/timeTaskService'; +import moment = require('moment'); + + +export default function (app: Application) { + new HandlerService(app, {}); + return new MonthlyFundHandler(app); +} + +export class MonthlyFundHandler { + constructor(private app: Application) { + } + + /************************月基金****************************/ + + /** + * @description 获取数据 + * @param {BackendSession} session + * @memberof MonthlyFundHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getMonthlyFundDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 签到 + * @param {BackendSession} session + * @memberof MonthlyFundHandler + */ + async sign(msg: { activityId: number, pageIndex: number, dayIndex: number }, session: BackendSession) { + + const { activityId, pageIndex, dayIndex } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getMonthlyFundData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let pageData = playerData.findPage(pageIndex); + if (!pageData) return resResult(STATUS.ACTIVITY_MISSING); + + if(!pageData.hasBought) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_NOT_BOUGHT); + + let signReward = pageData.findSignReward(dayIndex); + if(!signReward) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_NOT_FOUND); + if(signReward.hasReceived) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_HAS_SIGN); + if(signReward.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_LOCK); + + let record = await ActivityMonthlyFundModel.sign(serverId, activityId, roleId, playerData.roundIndex, pageIndex, dayIndex, playerData.todayIndex); + if(!record) return resResult(STATUS.ACTIVITY_MONTHLY_FUND_HAS_SIGN); + + pageData.setPlayerRecord(record); + if(pageData.hasReceivedAll()) { + await ActivityMonthlyFundModel.setReceivedAll(serverId, activityId, roleId, playerData.roundIndex, pageIndex); + } + + let rewardParamArr = stringToRewardParam(signReward.reward); + let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_MONTHLY_FUND_SIGN); + + return resResult(STATUS.SUCCESS, { + activityId, dayIndex, pageIndex, goods, addHeros + }); + } + + async debugSendMonthlyFundReward(msg: {}, session: BackendSession) { + + await monthlyFundSchedule(parseInt(moment().format('YYYYMM'))); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/monthlyTicketHandler.ts b/game-server/app/servers/activity/handler/monthlyTicketHandler.ts index 93f364d21..f48db91bd 100644 --- a/game-server/app/servers/activity/handler/monthlyTicketHandler.ts +++ b/game-server/app/servers/activity/handler/monthlyTicketHandler.ts @@ -1,54 +1,55 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, } from '../../../consts'; -import { getPlayerMonthlyTicketData, getPlayerMonthlyTicketDayReward } from '../../../services/activity/monthlyTicketService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new MonthlyTicketHandler(app); -} - -export class MonthlyTicketHandler { - constructor(private app: Application) { - } - - /************************月卡活动****************************/ - - /** - * @description 获取月卡活动数据 - * @param {BackendSession} session - * @memberof MonthlyTicketHandler - */ - async getMonthlyTicketActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerMonthlyTicketData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 领取月卡奖品 - * @param {BackendSession} session - * @memberof MonthlyTicketHandler - */ - async getMonthlyTicketReward(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let result = await getPlayerMonthlyTicketDayReward(roleId, roleName, sid, serverId, activityId) - if (result) { - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId }, - })); - } - return resResult(STATUS.NO_MOTHLY_TICKET_REWARD); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS, } from '../../../consts'; +import { getPlayerMonthlyTicketData, getPlayerMonthlyTicketDayReward } from '../../../services/activity/monthlyTicketService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new MonthlyTicketHandler(app); +} + +export class MonthlyTicketHandler { + constructor(private app: Application) { + } + + /************************月卡活动****************************/ + + /** + * @description 获取月卡活动数据 + * @param {BackendSession} session + * @memberof MonthlyTicketHandler + */ + async getMonthlyTicketActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerMonthlyTicketData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 领取月卡奖品 + * @param {BackendSession} session + * @memberof MonthlyTicketHandler + */ + async getMonthlyTicketReward(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let result = await getPlayerMonthlyTicketDayReward(roleId, roleName, sid, serverId, activityId) + if (result) { + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId }, + })); + } + return resResult(STATUS.NO_MOTHLY_TICKET_REWARD); + } +} + diff --git a/game-server/app/servers/activity/handler/newHeroGKHandler.ts b/game-server/app/servers/activity/handler/newHeroGKHandler.ts index de9ca7cca..191ed0ae9 100644 --- a/game-server/app/servers/activity/handler/newHeroGKHandler.ts +++ b/game-server/app/servers/activity/handler/newHeroGKHandler.ts @@ -1,74 +1,75 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; -import { getPlayerNewHeroGKData } from '../../../services/activity/newHeroGKService'; -import { ActivityNewHeroGKModel } from '../../../db/ActivityNewHeroGK'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new NewHeroGKHandler(app); -} - -export class NewHeroGKHandler { - constructor(private app: Application) { - } - - /************************新将演绎 (通用每日关卡,分页,自定义每个关卡开放的时间长短);(配置N个武将,每个武将有X个关卡;活动期间,*天(时间自定义)开启每个武将对应的一个关卡,只有第一次通关会获得奖励)****************************/ - - /** - * @description 获取关卡活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof NewHeroGKHandler - */ - async getNewHeroGKActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerNewHeroGKData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取今日挑战的单个奖励 - * @param {{ activityId: number, pageIndex: number, index:number}} msg - * @param {BackendSession} session - * @memberof NewHeroGKHandler - */ - async getGK(msg: { activityId: number, pageIndex: number, index: number }, session: BackendSession) { - const { activityId, pageIndex, index } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - // let playerData = await getPlayerNewHeroGKData(activityId, serverId, roleId) - // if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // let dailyItemData: NewHeroGKItem = playerData.findNewHeroGKItem(pageIndex, index); - // if (!dailyItemData) { - // return resResult(STATUS.ACTIVITY_DATA_ERROR); - // } - - // if (dailyItemData.begin > playerData.todayIndex || dailyItemData.end < playerData.todayIndex) { - // return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); - // } - // // await challengeNewHeroGK(serverId, roleId, activityId, pageIndex, dailyItemData.gk) - - return resResult(STATUS.SUCCESS); - } - - async debugResetGK(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - await ActivityNewHeroGKModel.deleteMany({ roleId }); - - return resResult(STATUS.SUCCESS); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '../../../consts'; +import { getPlayerNewHeroGKData } from '../../../services/activity/newHeroGKService'; +import { ActivityNewHeroGKModel } from '@db/ActivityNewHeroGK'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new NewHeroGKHandler(app); +} + +export class NewHeroGKHandler { + constructor(private app: Application) { + } + + /************************新将演绎 (通用每日关卡,分页,自定义每个关卡开放的时间长短);(配置N个武将,每个武将有X个关卡;活动期间,*天(时间自定义)开启每个武将对应的一个关卡,只有第一次通关会获得奖励)****************************/ + + /** + * @description 获取关卡活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof NewHeroGKHandler + */ + async getNewHeroGKActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerNewHeroGKData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取今日挑战的单个奖励 + * @param {{ activityId: number, pageIndex: number, index:number}} msg + * @param {BackendSession} session + * @memberof NewHeroGKHandler + */ + async getGK(msg: { activityId: number, pageIndex: number, index: number }, session: BackendSession) { + const { activityId, pageIndex, index } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + // let playerData = await getPlayerNewHeroGKData(activityId, serverId, roleId) + // if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // let dailyItemData: NewHeroGKItem = playerData.findNewHeroGKItem(pageIndex, index); + // if (!dailyItemData) { + // return resResult(STATUS.ACTIVITY_DATA_ERROR); + // } + + // if (dailyItemData.begin > playerData.todayIndex || dailyItemData.end < playerData.todayIndex) { + // return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + // } + // // await challengeNewHeroGK(serverId, roleId, activityId, pageIndex, dailyItemData.gk) + + return resResult(STATUS.SUCCESS); + } + + async debugResetGK(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + await ActivityNewHeroGKModel.deleteMany({ roleId }); + + return resResult(STATUS.SUCCESS); + } + +} + diff --git a/game-server/app/servers/activity/handler/newHeroGachaHandler.ts b/game-server/app/servers/activity/handler/newHeroGachaHandler.ts index 3b5cae258..fdd15f461 100644 --- a/game-server/app/servers/activity/handler/newHeroGachaHandler.ts +++ b/game-server/app/servers/activity/handler/newHeroGachaHandler.ts @@ -1,33 +1,34 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; -import { getPlayerNewHeroGachaData } from '../../../services/activity/newHeroService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new NewHeroGachaHandler(app); -} - -export class NewHeroGachaHandler { - constructor(private app: Application) { - } - - /** - * @description 获取关卡活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof NewHeroGachaHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerNewHeroGachaData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '../../../consts'; +import { getPlayerNewHeroGachaData } from '../../../services/activity/newHeroService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new NewHeroGachaHandler(app); +} + +export class NewHeroGachaHandler { + constructor(private app: Application) { + } + + /** + * @description 获取关卡活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof NewHeroGachaHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerNewHeroGachaData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } +} + diff --git a/game-server/app/servers/activity/handler/newHeroGiftsHandler.ts b/game-server/app/servers/activity/handler/newHeroGiftsHandler.ts index 210176edf..6288087bc 100644 --- a/game-server/app/servers/activity/handler/newHeroGiftsHandler.ts +++ b/game-server/app/servers/activity/handler/newHeroGiftsHandler.ts @@ -1,73 +1,74 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { getPlayerNewHeroGiftsData } from '../../../services/activity/newHeroService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityNewHeroGiftModel } from '../../../db/ActivityNewHeroGift'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new NewHeroGiftsHandler(app); -} - -export class NewHeroGiftsHandler { - constructor(private app: Application) { - } - - /************************新将好礼,很多红包,用积分兑换一遍结束****************************/ - - /** - * @description 获取新将好礼活动数据 - * @param {{ }} msg - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof NewHeroGiftsHandler - */ - async getNewHeroGiftsActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 兑换点数 - * @param {{ activityId: number, index:number}} msg - * @param {BackendSession} session - * @memberof NewHeroGiftsHandler - */ - async exchangePoint(msg: { activityId: number, index: number }, session: BackendSession) { - const { activityId, index } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let item = playerData.findItem(index); - if (!item) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (item.countMax <= item.buyCount) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (playerData.consumePoint + playerData.consumeTotalPoint > playerData.totalPoint) { - return resResult(STATUS.ACTIVITY_NO_POINT); - } - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.NEW_HERO_EXCHANGE) - await ActivityNewHeroGiftModel.addReceiveRecord(serverId, activityId, roleId, index, playerData.consumePoint); - item.buyCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, index }, - item: item, consumeTotalPoint: playerData.consumeTotalPoint + playerData.consumePoint - })); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { getPlayerNewHeroGiftsData } from '../../../services/activity/newHeroService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityNewHeroGiftModel } from '@db/ActivityNewHeroGift'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new NewHeroGiftsHandler(app); +} + +export class NewHeroGiftsHandler { + constructor(private app: Application) { + } + + /************************新将好礼,很多红包,用积分兑换一遍结束****************************/ + + /** + * @description 获取新将好礼活动数据 + * @param {{ }} msg + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof NewHeroGiftsHandler + */ + async getNewHeroGiftsActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 兑换点数 + * @param {{ activityId: number, index:number}} msg + * @param {BackendSession} session + * @memberof NewHeroGiftsHandler + */ + async exchangePoint(msg: { activityId: number, index: number }, session: BackendSession) { + const { activityId, index } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let item = playerData.findItem(index); + if (!item) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (item.countMax <= item.buyCount) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (playerData.consumePoint + playerData.consumeTotalPoint > playerData.totalPoint) { + return resResult(STATUS.ACTIVITY_NO_POINT); + } + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.NEW_HERO_EXCHANGE) + await ActivityNewHeroGiftModel.addReceiveRecord(serverId, activityId, roleId, index, playerData.consumePoint); + item.buyCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, index }, + item: item, consumeTotalPoint: playerData.consumeTotalPoint + playerData.consumePoint + })); + } +} + diff --git a/game-server/app/servers/activity/handler/novemberHandler.ts b/game-server/app/servers/activity/handler/novemberHandler.ts index c8498abde..b44ae8abf 100644 --- a/game-server/app/servers/activity/handler/novemberHandler.ts +++ b/game-server/app/servers/activity/handler/novemberHandler.ts @@ -1,170 +1,171 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { getPlayerNovemberData, getPlayerNovemberDataShow } from '../../../services/activity/novemberServices'; -import { genCode, getRandSingleEelm, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { ActivityNovemberRecModel, NovemberRecord } from '../../../db/ActivityNovemberRec'; -import { RewardInter } from '../../../pubUtils/interface'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getZeroPoint } from '../../../pubUtils/timeUtil'; - -/** - * 辜月集会 - * @param app - * @returns - */ -export default function (app: Application) { - new HandlerService(app, {}); - return new NovemberHandler(app); -} - -export class NovemberHandler { - constructor(private app: Application) { - } - - /** - * 获取数据 - * @param msg - * @param session - * @returns - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerNovemberDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * 开始游戏 - * @param msg - * @param session - * @returns - */ - async gameStart(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerNovemberData(activityId, serverId, roleId); - if (!playerData || playerData.menuIds.length == 0) return resResult(STATUS.ACTIVITY_MISSING); - - // 检测挑战次数 - if (playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); - - const gameCode = genCode(10); - const menuId = getRandSingleEelm(playerData.menuIds); - await ActivityNovemberRecModel.records(serverId, activityId, playerData.roundIndex, roleId, [{ - todayIndex: playerData.todayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, isSkip: false, menuId, hasPass: false - }]); - - return resResult(STATUS.SUCCESS, { activityId, gameCode, menuId }); - } - - /** - * 结束游戏 - * @param msg - * @param session - * @returns - */ - async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean }, session: BackendSession) { - const { activityId, gameCode, isSuccess } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - - let playerData = await getPlayerNovemberData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if (!playerData.records || playerData.records.length == 0) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); - let record = playerData.records.find(cur => cur.gameCode == gameCode); - if (!record) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); - if (record.hasPass) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_USE); - - let menuId = record.menuId; - - // 检测挑战次数 - if (playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); - - let rewards: string = playerData.successRewards; - if (!isSuccess) rewards = '&';//playerData.failRewards; - let playerRecord = await ActivityNovemberRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), rewards, true); - if (!playerRecord) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); - playerData = await getPlayerNovemberData(activityId, serverId, roleId); - - let goods: RewardInter[] = await addItems(roleId, roleName, sid, stringToRewardParam(rewards), ITEM_CHANGE_REASON.NOVEMBER_REWARD); - - return resResult(STATUS.SUCCESS, { activityId, menuId, todayPlayCnt: playerData.todayPlayCnt, playCnt: playerData.playCnt, freeCnt: playerData.freeCnt, goods }); - } - - /** - * 购买次数 - * @param msg - * @param session - * @returns - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerNovemberData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_BUY_COUNT_OVER); - - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.NOVEMBER_COST); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let buyResult = await ActivityNovemberRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); - if (!buyResult) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); - - playerData = await getPlayerNovemberData(activityId, serverId, roleId); - - return resResult(STATUS.SUCCESS, { activityId, buyCnt: playerData.buyCnt, maxBuyCnt: playerData.maxBuyCnt }); - } - - /** - * 扫荡 - * @param msg - * @param session - * @returns - */ - async gameSweep(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerNovemberData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if (playerData.menuIds.length == 0) return (STATUS.ACTIVITY_NOVEMBER_MENU_NOT_FIND) - if (playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMESWEEP_LOCK); - - if (playerData.playCnt + count > playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); - - let rewards: RewardInter[] = []; - let records: NovemberRecord[] = []; - for (let i = 0; i < count; i++) { - records.push({ todayIndex: playerData.todayIndex, gameCode: 'sweep', time: new Date(), rewards: playerData.successRewards, isSuccess: true, isSkip: true, menuId: 0, hasPass: true }) - rewards.push(...stringToRewardParam(playerData.successRewards)); - } - await ActivityNovemberRecModel.records(serverId, activityId, playerData.roundIndex, roleId, records); - - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.NOVEMBER_REWARD) - - playerData = await getPlayerNovemberData(activityId, serverId, roleId); - - - return resResult(STATUS.SUCCESS, { activityId, todayPlayCnt: playerData.todayPlayCnt, playCnt: playerData.playCnt, goods }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { getPlayerNovemberData, getPlayerNovemberDataShow } from '../../../services/activity/novemberServices'; +import { genCode, getRandSingleEelm, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { ActivityNovemberRecModel, NovemberRecord } from '@db/ActivityNovemberRec'; +import { RewardInter } from '@pubUtils/interface'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getZeroPoint } from '@pubUtils/timeUtil'; + +/** + * 辜月集会 + * @param app + * @returns + */ +export default function (app: Application) { + new HandlerService(app, {}); + return new NovemberHandler(app); +} + +export class NovemberHandler { + constructor(private app: Application) { + } + + /** + * 获取数据 + * @param msg + * @param session + * @returns + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerNovemberDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * 开始游戏 + * @param msg + * @param session + * @returns + */ + async gameStart(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerNovemberData(activityId, serverId, roleId); + if (!playerData || playerData.menuIds.length == 0) return resResult(STATUS.ACTIVITY_MISSING); + + // 检测挑战次数 + if (playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); + + const gameCode = genCode(10); + const menuId = getRandSingleEelm(playerData.menuIds); + await ActivityNovemberRecModel.records(serverId, activityId, playerData.roundIndex, roleId, [{ + todayIndex: playerData.todayIndex, gameCode, time: new Date(), rewards: '', isSuccess: false, isSkip: false, menuId, hasPass: false + }]); + + return resResult(STATUS.SUCCESS, { activityId, gameCode, menuId }); + } + + /** + * 结束游戏 + * @param msg + * @param session + * @returns + */ + async gameEnd(msg: { activityId: number, gameCode: string, isSuccess: boolean }, session: BackendSession) { + const { activityId, gameCode, isSuccess } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + + let playerData = await getPlayerNovemberData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if (!playerData.records || playerData.records.length == 0) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); + let record = playerData.records.find(cur => cur.gameCode == gameCode); + if (!record) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); + if (record.hasPass) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_USE); + + let menuId = record.menuId; + + // 检测挑战次数 + if (playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); + + let rewards: string = playerData.successRewards; + if (!isSuccess) rewards = '&';//playerData.failRewards; + let playerRecord = await ActivityNovemberRecModel.gameEnd(serverId, activityId, playerData.roundIndex, roleId, gameCode, isSuccess, new Date(), rewards, true); + if (!playerRecord) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); + playerData = await getPlayerNovemberData(activityId, serverId, roleId); + + let goods: RewardInter[] = await addItems(roleId, roleName, sid, stringToRewardParam(rewards), ITEM_CHANGE_REASON.NOVEMBER_REWARD); + + return resResult(STATUS.SUCCESS, { activityId, menuId, todayPlayCnt: playerData.todayPlayCnt, playCnt: playerData.playCnt, freeCnt: playerData.freeCnt, goods }); + } + + /** + * 购买次数 + * @param msg + * @param session + * @returns + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerNovemberData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_BUY_COUNT_OVER); + + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.NOVEMBER_COST); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let buyResult = await ActivityNovemberRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); + if (!buyResult) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMECODE_NOT_FOUND); + + playerData = await getPlayerNovemberData(activityId, serverId, roleId); + + return resResult(STATUS.SUCCESS, { activityId, buyCnt: playerData.buyCnt, maxBuyCnt: playerData.maxBuyCnt }); + } + + /** + * 扫荡 + * @param msg + * @param session + * @returns + */ + async gameSweep(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerNovemberData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if (playerData.menuIds.length == 0) return (STATUS.ACTIVITY_NOVEMBER_MENU_NOT_FIND) + if (playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_NOVEMBER_GAMESWEEP_LOCK); + + if (playerData.playCnt + count > playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_NOVEMBER_NO_NUM); + + let rewards: RewardInter[] = []; + let records: NovemberRecord[] = []; + for (let i = 0; i < count; i++) { + records.push({ todayIndex: playerData.todayIndex, gameCode: 'sweep', time: new Date(), rewards: playerData.successRewards, isSuccess: true, isSkip: true, menuId: 0, hasPass: true }) + rewards.push(...stringToRewardParam(playerData.successRewards)); + } + await ActivityNovemberRecModel.records(serverId, activityId, playerData.roundIndex, roleId, records); + + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.NOVEMBER_REWARD) + + playerData = await getPlayerNovemberData(activityId, serverId, roleId); + + + return resResult(STATUS.SUCCESS, { activityId, todayPlayCnt: playerData.todayPlayCnt, playCnt: playerData.playCnt, goods }); + } +} + diff --git a/game-server/app/servers/activity/handler/popUpShopHandler.ts b/game-server/app/servers/activity/handler/popUpShopHandler.ts index 7b1877312..e4e2d91bd 100644 --- a/game-server/app/servers/activity/handler/popUpShopHandler.ts +++ b/game-server/app/servers/activity/handler/popUpShopHandler.ts @@ -1,197 +1,198 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult, } from '../../../pubUtils/util'; -import { STATUS, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, ACTIVITY_TYPE, DEBUG_MAGIC_WORD, PUSH_ROUTE, } from '../../../consts'; -import { checkPopUpCondition, getPopUpShopData, getPopUpShopDataShow } from '../../../services/activity/popUpShopService'; -import { ActivityPopUpShopModel } from '../../../db/ActivityPopUpShop'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { handleCost } from '../../../services/role/rewardService'; -import { setInterval } from 'timers'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new PopUpShopHandler(app); -} - -export class PopUpShopHandler { - constructor(private app: Application) { - } - - /************************弹出式商店****************************/ - - /** - * @description 获取弹出式商店数据 - * @param {{ }} msg - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof PopUpShopHandler - */ - async getPopUpShopActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPopUpShopDataShow(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_THIRTY_DAYS_END); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - async checkPopUpCondition(msg: { conditionType: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - let { conditionType } = msg; - if( - conditionType != POP_UP_SHOP_CONDITION_TYPE.GACHA_RES_NOT_ENOUGH && - conditionType != POP_UP_SHOP_CONDITION_TYPE.TERAPH_RES_NOT_ENOUGH && - conditionType != POP_UP_SHOP_CONDITION_TYPE.STONE_NOT_ENOUGH && - conditionType != POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR_NOT_ENOUGH && - conditionType != POP_UP_SHOP_CONDITION_TYPE.FAVOR_NOT_ENOUGH && - conditionType != POP_UP_SHOP_CONDITION_TYPE.EXP_NOT_ENOUGH - ) { - return resResult(STATUS.WRONG_PARMS); - } - - await checkPopUpCondition(serverId, roleId, conditionType, {}); - - return resResult(STATUS.SUCCESS); - } - - - /** - * @description 购买礼包 - * @param {{ activityId: number, id: number, beginTimeStamp: number}} msg - * @param {BackendSession} session - * @memberof PopUpShopHandler - */ - async buyGift(msg: { activityId: number, id: number, code: string }, session: BackendSession) { - const { activityId, code, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPopUpShopData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - if (playerData.type !== ACTIVITY_TYPE.POP_UP_SHOP) { - return resResult(STATUS.ACTIVITY_TYPE_ERROR); - } - - let record = await ActivityPopUpShopModel.findByCode(serverId, activityId, roleId, code); - if(!record) return resResult(STATUS.ACTIVITY_TASK_NOT_COMPLETE); - let pkg = playerData.findPackageById(record.id); - let item = pkg?.findItemById(id); - if(!item) { - return resResult(STATUS.ACTIVITY_MISSING); - } - if(item.productID) { - return resResult(STATUS.ACTIVITY_POP_UP_MUST_BUY); - } - - let consume = stringToConsumeParam(item.consume); - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT); - if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - record = await ActivityPopUpShopModel.addRecordById(serverId, activityId, roleId, code, id); - let showItem = playerData.updateRecordById(record, id); - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT) - - - return resResult(STATUS.SUCCESS, { - ...result, param: { activityId, id }, - item: showItem - }); - } - - // 客户端展示弹出礼包的通知 - async showGift(msg: { code: string }, session: BackendSession) { - const { code } = msg; - - let rec = await ActivityPopUpShopModel.show(code); - if (!rec) return resResult(STATUS.ACTIVITY_MISSING); - return resResult(STATUS.SUCCESS); - } - - async debugPushPopUpShop(msg: { conditionType: number, magicWord: string, param: number, needDelete: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - let serverId = session.get('serverId'); - const { magicWord, conditionType, param } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - // let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.POP_UP_SHOP); - // for(let { activityId } of activities) { - // let playerData = await getPopUpShopData(activityId, serverId, roleId); - // for(let pkg of playerData.packages) { - // if(pkg.conditionType == conditionType) { - // await ActivityPopUpShopModel.deleteMany({ roleId, activityId, id: pkg.id }); - // } - // } - // } - - - let arr = await checkPopUpCondition(serverId, roleId, conditionType, { - oldLv: param? param - 1: 0, - newLv: param||100, - quality: param||3, - warId: param||128, - seasonWinNum: param||10, - equipStar: param||10 - }); - - return resResult(STATUS.SUCCESS, { activities:arr }); - } - - private interval: NodeJS.Timer; - private pushId = 0; - - async debugPushPopUpInterval(msg: { magicWord: string }, session: BackendSession) { - const roleId = session.get('roleId'); - let sid = session.get('sid'); - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - if(this.interval) { - clearInterval(this.interval); - } - let fun = async () => { - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_UPDATE, { - activities: [{ - activityId: 25, - activityType: 24, - param: { popUpShopItems: [ - {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":1,"name":"超值第一章通关礼包","price":6,"productID":"com.bantu.sgzzyz.yb34-20","consume":"&","reward":"2&11002&20|2&22001&2|2&31001&10000","rebate":1000,"buyCnt":1,"hasBoughtCnt":0}, - {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":2,"name":"超值第一章通关礼包","price":30,"productID":"com.bantu.sgzzyz.yb34-21","consume":"&","reward":"2&11002&40|2&22001&10|2&31001&20000","rebate":850,"buyCnt":1,"hasBoughtCnt":0}, - {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":3,"name":"超值第一章通关礼包","price":68,"productID":"com.bantu.sgzzyz.yb34-22","consume":"&","reward":"2&11003&20|2&22001&25|2&31001&40000","rebate":950,"buyCnt":1,"hasBoughtCnt":0} - ]}, - }], - pushId: ++this.pushId - }, sid); - }; - await fun(); - this.interval = setInterval(fun, 60000) - - return resResult(STATUS.SUCCESS); - } - - async debugStopPupUpInterval(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - if(this.interval) { - clearInterval(this.interval); - } - this.pushId = 0; - - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult, } from '@pubUtils/util'; +import { STATUS, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, ACTIVITY_TYPE, DEBUG_MAGIC_WORD, PUSH_ROUTE, } from '../../../consts'; +import { checkPopUpCondition, getPopUpShopData, getPopUpShopDataShow } from '../../../services/activity/popUpShopService'; +import { ActivityPopUpShopModel } from '@db/ActivityPopUpShop'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { handleCost } from '../../../services/role/rewardService'; +import { setInterval } from 'timers'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new PopUpShopHandler(app); +} + +export class PopUpShopHandler { + constructor(private app: Application) { + } + + /************************弹出式商店****************************/ + + /** + * @description 获取弹出式商店数据 + * @param {{ }} msg + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof PopUpShopHandler + */ + async getPopUpShopActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPopUpShopDataShow(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_THIRTY_DAYS_END); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + async checkPopUpCondition(msg: { conditionType: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + let { conditionType } = msg; + if( + conditionType != POP_UP_SHOP_CONDITION_TYPE.GACHA_RES_NOT_ENOUGH && + conditionType != POP_UP_SHOP_CONDITION_TYPE.TERAPH_RES_NOT_ENOUGH && + conditionType != POP_UP_SHOP_CONDITION_TYPE.STONE_NOT_ENOUGH && + conditionType != POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR_NOT_ENOUGH && + conditionType != POP_UP_SHOP_CONDITION_TYPE.FAVOR_NOT_ENOUGH && + conditionType != POP_UP_SHOP_CONDITION_TYPE.EXP_NOT_ENOUGH + ) { + return resResult(STATUS.WRONG_PARMS); + } + + await checkPopUpCondition(serverId, roleId, conditionType, {}); + + return resResult(STATUS.SUCCESS); + } + + + /** + * @description 购买礼包 + * @param {{ activityId: number, id: number, beginTimeStamp: number}} msg + * @param {BackendSession} session + * @memberof PopUpShopHandler + */ + async buyGift(msg: { activityId: number, id: number, code: string }, session: BackendSession) { + const { activityId, code, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPopUpShopData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + if (playerData.type !== ACTIVITY_TYPE.POP_UP_SHOP) { + return resResult(STATUS.ACTIVITY_TYPE_ERROR); + } + + let record = await ActivityPopUpShopModel.findByCode(serverId, activityId, roleId, code); + if(!record) return resResult(STATUS.ACTIVITY_TASK_NOT_COMPLETE); + let pkg = playerData.findPackageById(record.id); + let item = pkg?.findItemById(id); + if(!item) { + return resResult(STATUS.ACTIVITY_MISSING); + } + if(item.productID) { + return resResult(STATUS.ACTIVITY_POP_UP_MUST_BUY); + } + + let consume = stringToConsumeParam(item.consume); + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT); + if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + record = await ActivityPopUpShopModel.addRecordById(serverId, activityId, roleId, code, id); + let showItem = playerData.updateRecordById(record, id); + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT) + + + return resResult(STATUS.SUCCESS, { + ...result, param: { activityId, id }, + item: showItem + }); + } + + // 客户端展示弹出礼包的通知 + async showGift(msg: { code: string }, session: BackendSession) { + const { code } = msg; + + let rec = await ActivityPopUpShopModel.show(code); + if (!rec) return resResult(STATUS.ACTIVITY_MISSING); + return resResult(STATUS.SUCCESS); + } + + async debugPushPopUpShop(msg: { conditionType: number, magicWord: string, param: number, needDelete: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + let serverId = session.get('serverId'); + const { magicWord, conditionType, param } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + // let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.POP_UP_SHOP); + // for(let { activityId } of activities) { + // let playerData = await getPopUpShopData(activityId, serverId, roleId); + // for(let pkg of playerData.packages) { + // if(pkg.conditionType == conditionType) { + // await ActivityPopUpShopModel.deleteMany({ roleId, activityId, id: pkg.id }); + // } + // } + // } + + + let arr = await checkPopUpCondition(serverId, roleId, conditionType, { + oldLv: param? param - 1: 0, + newLv: param||100, + quality: param||3, + warId: param||128, + seasonWinNum: param||10, + equipStar: param||10 + }); + + return resResult(STATUS.SUCCESS, { activities:arr }); + } + + private interval: NodeJS.Timer; + private pushId = 0; + + async debugPushPopUpInterval(msg: { magicWord: string }, session: BackendSession) { + const roleId = session.get('roleId'); + let sid = session.get('sid'); + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + if(this.interval) { + clearInterval(this.interval); + } + let fun = async () => { + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_UPDATE, { + activities: [{ + activityId: 25, + activityType: 24, + param: { popUpShopItems: [ + {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":1,"name":"超值第一章通关礼包","price":6,"productID":"com.bantu.sgzzyz.yb34-20","consume":"&","reward":"2&11002&20|2&22001&2|2&31001&10000","rebate":1000,"buyCnt":1,"hasBoughtCnt":0}, + {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":2,"name":"超值第一章通关礼包","price":30,"productID":"com.bantu.sgzzyz.yb34-21","consume":"&","reward":"2&11002&40|2&22001&10|2&31001&20000","rebate":850,"buyCnt":1,"hasBoughtCnt":0}, + {"code":"eefXmwD2","packageId":5,"endTime":Date.now() + 60000,"id":3,"name":"超值第一章通关礼包","price":68,"productID":"com.bantu.sgzzyz.yb34-22","consume":"&","reward":"2&11003&20|2&22001&25|2&31001&40000","rebate":950,"buyCnt":1,"hasBoughtCnt":0} + ]}, + }], + pushId: ++this.pushId + }, sid); + }; + await fun(); + this.interval = setInterval(fun, 60000) + + return resResult(STATUS.SUCCESS); + } + + async debugStopPupUpInterval(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + if(this.interval) { + clearInterval(this.interval); + } + this.pushId = 0; + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/qixiHandler.ts b/game-server/app/servers/activity/handler/qixiHandler.ts index 7d9384804..9163fb006 100644 --- a/game-server/app/servers/activity/handler/qixiHandler.ts +++ b/game-server/app/servers/activity/handler/qixiHandler.ts @@ -1,186 +1,187 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { genCode, getRandSingleEelm, parseNumberList, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { getPlayerQixiData, getPlayerQixiDataShow } from '../../../services/activity/qixiService'; -import { ActivityQixiRecModel } from '../../../db/ActivityQixiRec'; -import { RewardInter } from '../../../pubUtils/interface'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new QiXiHandler(app); -} - -export class QiXiHandler { - constructor(private app: Application) { - } - - /** - * @description 获取火神祭祀活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof QiXiHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerQixiDataShow(activityId, serverId, roleId); - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 召唤鹊桥游戏 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof QiXiHandler - */ - async gameStart(msg: { activityId: number, progress: number }, session: BackendSession) { - const { activityId, progress } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerQixiData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.progress != progress) return resResult(STATUS.ACTIVITY_QIXI_PROGRESS_NOT_FIT); - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); - - const gameCode = genCode(10); - let playerRecord = await ActivityQixiRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { - todayIndex: playerData.recordTodayIndex, gameCode, time: new Date(), rewards: '', progress, afterProgress: progress, hasPass: false - }); - playerData.updatePlayerRecord(playerRecord); - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - gameCode, - progress: playerData.progress - }); - } - - - /** - * @description 召唤鹊桥游戏 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof QiXiHandler - */ - async gameEnd(msg: { activityId: number, gameCode: string, progress: number, addProgress: number }, session: BackendSession) { - const { activityId, gameCode, progress, addProgress } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerQixiData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.progress != progress) return resResult(STATUS.ACTIVITY_QIXI_PROGRESS_NOT_FIT); - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); - - let curRecord = playerData.records.find(cur => cur.gameCode == gameCode); - if(!curRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - if(curRecord.hasPass) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_HAS_PLAY); - - let playerRecord = await ActivityQixiRecModel.addProgress(serverId, activityId, playerData.roundIndex, roleId, gameCode, addProgress, new Date()); - if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - playerData.updatePlayerRecord(playerRecord); - let goods: RewardInter[] = []; - if(playerData.progress >= playerData.maxProgress) { - await ActivityQixiRecModel.recordReward(serverId, activityId, playerData.roundIndex, roleId, gameCode, playerData.rewards); - let rewards = stringToRewardParam(playerData.rewards); - goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.QIXI_REWARD) - } - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - gameCode, - progress: playerData.progress, - goods - }); - } - - /** - * @description 扫荡 - * @param {{ activityId: number }} msg - * @param {BackendSession} session - * @memberof QiXiHandler - */ - async gameSweep(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - let playerData = await getPlayerQixiData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - // 挑战次数 - if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); - if(playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_SWEEP); - - let playerRecord = await ActivityQixiRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { - todayIndex: playerData.recordTodayIndex, gameCode: '', time: new Date(), rewards: playerData.rewards, progress: 0, afterProgress: playerData.maxProgress, hasPass: true, isSkip: true - }); - if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); - playerData.updatePlayerRecord(playerRecord); - let rewards = stringToRewardParam(playerData.rewards); - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.QIXI_REWARD) - - - return resResult(STATUS.SUCCESS, { - activityId, - todayPlayCnt: playerData.todayPlayCnt, - playCnt: playerData.playCnt, - freeCnt: playerData.freeCnt, - progress: playerData.progress, - goods - }); - } - - /** - * @description 购买次数 - * @param {{ activityId: number, id: number, count: number}} msg - * @param {BackendSession} session - * @memberof QiXiHandler - */ - async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerQixiData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - // 可购买次数 - if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_QIXI_BUY_COUNT_OVER); - // if(playerData.playCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_BUY); - // 扣材料 - let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 保存数据 - let buildResult = await ActivityQixiRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); - // // 更新数据 - playerData.updatePlayerRecord(buildResult); - - return resResult(STATUS.SUCCESS, { - activityId, - maxBuyCnt: playerData.maxBuyCnt, - buyCnt: playerData.buyCnt - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { genCode, getRandSingleEelm, parseNumberList, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { getPlayerQixiData, getPlayerQixiDataShow } from '../../../services/activity/qixiService'; +import { ActivityQixiRecModel } from '@db/ActivityQixiRec'; +import { RewardInter } from '@pubUtils/interface'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new QiXiHandler(app); +} + +export class QiXiHandler { + constructor(private app: Application) { + } + + /** + * @description 获取火神祭祀活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof QiXiHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerQixiDataShow(activityId, serverId, roleId); + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 召唤鹊桥游戏 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof QiXiHandler + */ + async gameStart(msg: { activityId: number, progress: number }, session: BackendSession) { + const { activityId, progress } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerQixiData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.progress != progress) return resResult(STATUS.ACTIVITY_QIXI_PROGRESS_NOT_FIT); + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); + + const gameCode = genCode(10); + let playerRecord = await ActivityQixiRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { + todayIndex: playerData.recordTodayIndex, gameCode, time: new Date(), rewards: '', progress, afterProgress: progress, hasPass: false + }); + playerData.updatePlayerRecord(playerRecord); + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + gameCode, + progress: playerData.progress + }); + } + + + /** + * @description 召唤鹊桥游戏 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof QiXiHandler + */ + async gameEnd(msg: { activityId: number, gameCode: string, progress: number, addProgress: number }, session: BackendSession) { + const { activityId, gameCode, progress, addProgress } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerQixiData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.progress != progress) return resResult(STATUS.ACTIVITY_QIXI_PROGRESS_NOT_FIT); + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); + + let curRecord = playerData.records.find(cur => cur.gameCode == gameCode); + if(!curRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + if(curRecord.hasPass) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_HAS_PLAY); + + let playerRecord = await ActivityQixiRecModel.addProgress(serverId, activityId, playerData.roundIndex, roleId, gameCode, addProgress, new Date()); + if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + playerData.updatePlayerRecord(playerRecord); + let goods: RewardInter[] = []; + if(playerData.progress >= playerData.maxProgress) { + await ActivityQixiRecModel.recordReward(serverId, activityId, playerData.roundIndex, roleId, gameCode, playerData.rewards); + let rewards = stringToRewardParam(playerData.rewards); + goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.QIXI_REWARD) + } + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + gameCode, + progress: playerData.progress, + goods + }); + } + + /** + * @description 扫荡 + * @param {{ activityId: number }} msg + * @param {BackendSession} session + * @memberof QiXiHandler + */ + async gameSweep(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + let playerData = await getPlayerQixiData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + // 挑战次数 + if(playerData.playCnt >= playerData.freeCnt + playerData.buyCnt) return resResult(STATUS.ACTIVITY_QIXI_NO_NUM); + if(playerData.todayPlayCnt <= 0) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_SWEEP); + + let playerRecord = await ActivityQixiRecModel.record(serverId, activityId, playerData.roundIndex, roleId, { + todayIndex: playerData.recordTodayIndex, gameCode: '', time: new Date(), rewards: playerData.rewards, progress: 0, afterProgress: playerData.maxProgress, hasPass: true, isSkip: true + }); + if(!playerRecord) return resResult(STATUS.ACTIVITY_QIXI_GAMECODE_NOT_FOUND); + playerData.updatePlayerRecord(playerRecord); + let rewards = stringToRewardParam(playerData.rewards); + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.QIXI_REWARD) + + + return resResult(STATUS.SUCCESS, { + activityId, + todayPlayCnt: playerData.todayPlayCnt, + playCnt: playerData.playCnt, + freeCnt: playerData.freeCnt, + progress: playerData.progress, + goods + }); + } + + /** + * @description 购买次数 + * @param {{ activityId: number, id: number, count: number}} msg + * @param {BackendSession} session + * @memberof QiXiHandler + */ + async buyCnt(msg: { activityId: number, count: number }, session: BackendSession) { + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerQixiData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + // 可购买次数 + if(playerData.buyCnt + count > playerData.maxBuyCnt) return resResult(STATUS.ACTIVITY_QIXI_BUY_COUNT_OVER); + // if(playerData.playCnt < playerData.freeCnt) return resResult(STATUS.ACTIVITY_QIXI_CANNOT_BUY); + // 扣材料 + let costResult = await handleCost(roleId, sid, stringToConsumeParam(playerData.buyCost), ITEM_CHANGE_REASON.ACT_ENTERTAIN_BUY_COST); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 保存数据 + let buildResult = await ActivityQixiRecModel.buyCnt(serverId, activityId, playerData.roundIndex, roleId, count); + // // 更新数据 + playerData.updatePlayerRecord(buildResult); + + return resResult(STATUS.SUCCESS, { + activityId, + maxBuyCnt: playerData.maxBuyCnt, + buyCnt: playerData.buyCnt + }); + } +} + diff --git a/game-server/app/servers/activity/handler/rebateHandler.ts b/game-server/app/servers/activity/handler/rebateHandler.ts index 191904bd0..6759800df 100644 --- a/game-server/app/servers/activity/handler/rebateHandler.ts +++ b/game-server/app/servers/activity/handler/rebateHandler.ts @@ -1,78 +1,79 @@ -import { Application, BackendSession, HandlerService } from 'pinus'; -import { genCode, resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { getPlayerRebateDataShow, getPlayerRebateData } from '../../../services/activity/rebateService'; -import { HistoryOrderModel } from '../../../db/HistoryOrder'; -import { UserModel } from '../../../db/User'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new RebateHandler(app); -} - -export class RebateHandler { - constructor(private app: Application) { - } - - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const uid = session.get('userid'); - - let playerData = await getPlayerRebateDataShow(activityId, roleId, serverId, uid); - return resResult(STATUS.SUCCESS, { - playerData - }) - } - - /** - * @description 领取奖励 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof RebateHandler - */ - async receiveReward(msg: { activityId: number, day: number }, session: BackendSession) { - const { activityId, day } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const uid = session.get('userid'); - - let playerData = await getPlayerRebateData(activityId, roleId, serverId, uid); - let item = playerData.findRebateByDay(day); - if(!item) return resResult(STATUS.WRONG_PARMS); - if(item.day > playerData.todayIndex) return resResult(STATUS.ACTIVITY_REBATE_DAY_NOT_REACH); - if(item.hasReceived) return resResult(STATUS.ACTIVITY_REBATE_HAS_RECEIVED); - - // console.log('####', playerData.channelId, roleId, day) - await HistoryOrderModel.receive(playerData.channelId, roleId, day); - let rewardArray = stringToRewardParam(item.rewards); - let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.RECEIVE_REBATE); - - return resResult(STATUS.SUCCESS, { - activityId, day, - hasReceived: true, - goods, addHeros - }); - } - - // debug接口,让自己能返利 - async debugSetRebate(msg: { totalPay: number }, session: BackendSession) { - const { totalPay } = msg; - const uid = session.get('userid'); - - let user = await UserModel.findUserByUid(uid); - if(!user.channelId) { - user = await UserModel.findOneAndUpdate({ uid }, { $set: { channelId: genCode(10) } }, { new: true }).lean(); - } - - await HistoryOrderModel.deleteMany({ channelId: user.channelId }); - await HistoryOrderModel.insertMany([{ channelId: user.channelId, totalPay }]); - - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService } from 'pinus'; +import { genCode, resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { getPlayerRebateDataShow, getPlayerRebateData } from '../../../services/activity/rebateService'; +import { HistoryOrderModel } from '@db/HistoryOrder'; +import { UserModel } from '@db/User'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new RebateHandler(app); +} + +export class RebateHandler { + constructor(private app: Application) { + } + + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const uid = session.get('userid'); + + let playerData = await getPlayerRebateDataShow(activityId, roleId, serverId, uid); + return resResult(STATUS.SUCCESS, { + playerData + }) + } + + /** + * @description 领取奖励 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof RebateHandler + */ + async receiveReward(msg: { activityId: number, day: number }, session: BackendSession) { + const { activityId, day } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const uid = session.get('userid'); + + let playerData = await getPlayerRebateData(activityId, roleId, serverId, uid); + let item = playerData.findRebateByDay(day); + if(!item) return resResult(STATUS.WRONG_PARMS); + if(item.day > playerData.todayIndex) return resResult(STATUS.ACTIVITY_REBATE_DAY_NOT_REACH); + if(item.hasReceived) return resResult(STATUS.ACTIVITY_REBATE_HAS_RECEIVED); + + // console.log('####', playerData.channelId, roleId, day) + await HistoryOrderModel.receive(playerData.channelId, roleId, day); + let rewardArray = stringToRewardParam(item.rewards); + let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.RECEIVE_REBATE); + + return resResult(STATUS.SUCCESS, { + activityId, day, + hasReceived: true, + goods, addHeros + }); + } + + // debug接口,让自己能返利 + async debugSetRebate(msg: { totalPay: number }, session: BackendSession) { + const { totalPay } = msg; + const uid = session.get('userid'); + + let user = await UserModel.findUserByUid(uid); + if(!user.channelId) { + user = await UserModel.findOneAndUpdate({ uid }, { $set: { channelId: genCode(10) } }, { new: true }).lean(); + } + + await HistoryOrderModel.deleteMany({ channelId: user.channelId }); + await HistoryOrderModel.insertMany([{ channelId: user.channelId, totalPay }]); + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/rechargeMoneyHandler.ts b/game-server/app/servers/activity/handler/rechargeMoneyHandler.ts index 8173490aa..712cd8cb3 100644 --- a/game-server/app/servers/activity/handler/rechargeMoneyHandler.ts +++ b/game-server/app/servers/activity/handler/rechargeMoneyHandler.ts @@ -1,75 +1,76 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerRechargeMoneyData, getPlayerRechargeMoneyDataShow } from '../../../services/activity/rechargeMoneyService'; -import { RechargeMoneyPool } from '../../../domain/activityField/rechargeMoneyField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityRechargeMoneyModel } from '../../../db/ActivityRechargeMoney'; -import { addItems } from '../../../services/role/rewardService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new RechargeMoneyHandler(app); -} - -export class RechargeMoneyHandler { - constructor(private app: Application) { - } - - /************************每日累计充值****************************/ - - /** - * @description 获取活动数据 - * @param {BackendSession} session - * @memberof RechargeMoneyHandler - */ - async getRechargeMoneyActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerRechargeMoneyDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, {playerData}); - } - - /** - * @description 获取奖励 - * @param {BackendSession} session - * @memberof RechargeMoneyHandler - */ - async pull(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (playerData.ticketCnt <= 0) { - return resResult(STATUS.ACTIVITY_RECHARGE_TICKET_NOT_ENOUGH); - } - - let item = playerData.pull(); - if (!item) { - return resResult(STATUS.ACTIVITY_RECHARGE_TICKET_NOT_ENOUGH); - } - - let notGetRecord = playerData.recordArr[0]; - // console.log('notGetRecord', JSON.stringify(notGetRecord)); - await ActivityRechargeMoneyModel.addRecord(notGetRecord._id, item.id, `${item.gid}&${item.count}`); - let goods = await addItems(roleId, roleName, sid, [{ id: item.gid, count: item.count }], ITEM_CHANGE_REASON.RECHARGE_REWARD) - - return resResult(STATUS.SUCCESS, { - param: { activityId }, - item: item, - ticketCnt: playerData.ticketCnt, - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerRechargeMoneyData, getPlayerRechargeMoneyDataShow } from '../../../services/activity/rechargeMoneyService'; +import { RechargeMoneyPool } from '@domain/activityField/rechargeMoneyField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityRechargeMoneyModel } from '@db/ActivityRechargeMoney'; +import { addItems } from '../../../services/role/rewardService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new RechargeMoneyHandler(app); +} + +export class RechargeMoneyHandler { + constructor(private app: Application) { + } + + /************************每日累计充值****************************/ + + /** + * @description 获取活动数据 + * @param {BackendSession} session + * @memberof RechargeMoneyHandler + */ + async getRechargeMoneyActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerRechargeMoneyDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, {playerData}); + } + + /** + * @description 获取奖励 + * @param {BackendSession} session + * @memberof RechargeMoneyHandler + */ + async pull(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (playerData.ticketCnt <= 0) { + return resResult(STATUS.ACTIVITY_RECHARGE_TICKET_NOT_ENOUGH); + } + + let item = playerData.pull(); + if (!item) { + return resResult(STATUS.ACTIVITY_RECHARGE_TICKET_NOT_ENOUGH); + } + + let notGetRecord = playerData.recordArr[0]; + // console.log('notGetRecord', JSON.stringify(notGetRecord)); + await ActivityRechargeMoneyModel.addRecord(notGetRecord._id, item.id, `${item.gid}&${item.count}`); + let goods = await addItems(roleId, roleName, sid, [{ id: item.gid, count: item.count }], ITEM_CHANGE_REASON.RECHARGE_REWARD) + + return resResult(STATUS.SUCCESS, { + param: { activityId }, + item: item, + ticketCnt: playerData.ticketCnt, + }); + } +} + diff --git a/game-server/app/servers/activity/handler/refreshShopHandler.ts b/game-server/app/servers/activity/handler/refreshShopHandler.ts index e659b8734..774458e18 100644 --- a/game-server/app/servers/activity/handler/refreshShopHandler.ts +++ b/game-server/app/servers/activity/handler/refreshShopHandler.ts @@ -1,91 +1,92 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerRefreshShopData } from '../../../services/activity/refreshShopService'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ActivityRefreshShopModel } from '../../../db/ActivityRefreshShop'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RefreshShopHandler(app); -} - -export class RefreshShopHandler { - constructor(private app: Application) { - } - - /************************通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换)****************************/ - - /** - * @description 获取商店数据 - * @param {{ activityId:number}} msg - * @param {BackendSession} session - * @memberof RefreshShopHandler - */ - async getRefreshShopActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerRefreshShopData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - return resResult(STATUS.SUCCESS, { playerData }); - } - - - /** - * @description 购买 - * @param {{ activityId: number, roundIndex: number, id: number, pageIndex: number}} msg - * @param {BackendSession} session - * @memberof RefreshShopHandler - */ - async buyGood(msg: { activityId: number, roundIndex: number, id: number, pageIndex: number, count: number }, session: BackendSession) { - const { activityId, roundIndex, id, pageIndex, count = 1 } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerRefreshShopData(activityId, serverId, roleId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - if (playerData.roundIndex != roundIndex) { - return resResult(STATUS.ACTIVITY_EXPIRE); - } - - let item = playerData.findItem(id, pageIndex); - if (!item) { - return resResult(STATUS.ACTIVITY_ID_ERROR); - } - if (item.countMax > 0 && item.buyCount + count > item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (item.price > 0) { - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - - //检查资源 - let consumeArr = new Array(count).fill(item.consume); - let consume = stringToConsumeParam(...consumeArr); - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let rewardArray = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count })); - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); - - await ActivityRefreshShopModel.addRecord(activityId, roleId, roundIndex, pageIndex, id, count); - - item.buyCount += count; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, roundIndex, id }, - item: item - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerRefreshShopData } from '../../../services/activity/refreshShopService'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ActivityRefreshShopModel } from '@db/ActivityRefreshShop'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RefreshShopHandler(app); +} + +export class RefreshShopHandler { + constructor(private app: Application) { + } + + /************************通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换)****************************/ + + /** + * @description 获取商店数据 + * @param {{ activityId:number}} msg + * @param {BackendSession} session + * @memberof RefreshShopHandler + */ + async getRefreshShopActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerRefreshShopData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + return resResult(STATUS.SUCCESS, { playerData }); + } + + + /** + * @description 购买 + * @param {{ activityId: number, roundIndex: number, id: number, pageIndex: number}} msg + * @param {BackendSession} session + * @memberof RefreshShopHandler + */ + async buyGood(msg: { activityId: number, roundIndex: number, id: number, pageIndex: number, count: number }, session: BackendSession) { + const { activityId, roundIndex, id, pageIndex, count = 1 } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerRefreshShopData(activityId, serverId, roleId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + if (playerData.roundIndex != roundIndex) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + + let item = playerData.findItem(id, pageIndex); + if (!item) { + return resResult(STATUS.ACTIVITY_ID_ERROR); + } + if (item.countMax > 0 && item.buyCount + count > item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (item.price > 0) { + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + + //检查资源 + let consumeArr = new Array(count).fill(item.consume); + let consume = stringToConsumeParam(...consumeArr); + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let rewardArray = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count })); + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); + + await ActivityRefreshShopModel.addRecord(activityId, roleId, roundIndex, pageIndex, id, count); + + item.buyCount += count; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, roundIndex, id }, + item: item + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/refreshTaskHandler.ts b/game-server/app/servers/activity/handler/refreshTaskHandler.ts index 4e9ac3d89..c5f5cbfd9 100644 --- a/game-server/app/servers/activity/handler/refreshTaskHandler.ts +++ b/game-server/app/servers/activity/handler/refreshTaskHandler.ts @@ -1,123 +1,124 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getPlayerRefreshTaskData } from '../../../services/activity/refreshTaskService'; -import { RefreshTaskItem } from '../../../domain/activityField/refreshTaskField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityRefreshTaskModel } from '../../../db/ActivityRefreshTask'; -import { ActivityRefreshTaskPointModel } from '../../../db/ActivityRefreshTaskPoint'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new RefreshTaskHandler(app); -} - -export class RefreshTaskHandler { - constructor(private app: Application) { - } - - /************************通用的刷新任务(分页,可刷新,限制领取次数)****************************/ - - /** - * @description 获取任务活动数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof RefreshTaskHandler - */ - async getRefreshTaskActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取奖励 - * @param {{ activityId: number, roundIndex: number, pageIndex: number,id: number, type: number}} msg - * @param {BackendSession} session - * @memberof RefreshTaskHandler - */ - async getReward(msg: { activityId: number, roundIndex: number, pageIndex: number, id: number, type: number }, session: BackendSession) { - const { activityId, roundIndex, pageIndex, id, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if (playerData.roundIndex != roundIndex) { - return resResult(STATUS.ACTIVITY_EXPIRE); - } - let dailyItemData: RefreshTaskItem = playerData.findItem(pageIndex, id, type); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (dailyItemData.totalCount < dailyItemData.condition) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (dailyItemData.receiveRewardCount) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityRefreshTaskModel.addReceiveRecord(serverId, activityId, roleId, roundIndex, pageIndex, id, dailyItemData.getRefTime(), 1); - - let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.REFRESH_TASK_REWARD) - - //获得点数 - await ActivityRefreshTaskPointModel.addPoint(serverId, activityId, roleId, dailyItemData.point); - - dailyItemData.receiveRewardCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, roundIndex, pageIndex, id, type }, - item: dailyItemData, - totalPoint: playerData.totalPoint + dailyItemData.point, - })); - } - - /** - * @description 兑换点数 - * @param {{ activityId: number, roundIndex: number}} msg - * @param {BackendSession} session - * @memberof RefreshTaskHandler - */ - async exchangePoint(msg: { activityId: number, roundIndex: number }, session: BackendSession) { - const { activityId, roundIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if (playerData.roundIndex != roundIndex) { - return resResult(STATUS.ACTIVITY_EXPIRE); - } - - if ((playerData.totalPoint - playerData.exchangePoint) < playerData.consumePoint) {//点数不够 - return resResult(STATUS.ACTIVITY_NO_POINT); - } - - await ActivityRefreshTaskPointModel.addReceiveRecord(serverId, activityId, roleId, playerData.consumePoint); - - let rewardParamArr: Array = stringToRewardParam(playerData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.REFRESH_TASK_EXCHANGE) - - playerData.exchangePoint += playerData.consumePoint; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, roundIndex }, - item: { exchangePoint: playerData.exchangePoint }, - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getPlayerRefreshTaskData } from '../../../services/activity/refreshTaskService'; +import { RefreshTaskItem } from '@domain/activityField/refreshTaskField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityRefreshTaskModel } from '@db/ActivityRefreshTask'; +import { ActivityRefreshTaskPointModel } from '@db/ActivityRefreshTaskPoint'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new RefreshTaskHandler(app); +} + +export class RefreshTaskHandler { + constructor(private app: Application) { + } + + /************************通用的刷新任务(分页,可刷新,限制领取次数)****************************/ + + /** + * @description 获取任务活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof RefreshTaskHandler + */ + async getRefreshTaskActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取奖励 + * @param {{ activityId: number, roundIndex: number, pageIndex: number,id: number, type: number}} msg + * @param {BackendSession} session + * @memberof RefreshTaskHandler + */ + async getReward(msg: { activityId: number, roundIndex: number, pageIndex: number, id: number, type: number }, session: BackendSession) { + const { activityId, roundIndex, pageIndex, id, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if (playerData.roundIndex != roundIndex) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + let dailyItemData: RefreshTaskItem = playerData.findItem(pageIndex, id, type); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (dailyItemData.totalCount < dailyItemData.condition) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (dailyItemData.receiveRewardCount) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityRefreshTaskModel.addReceiveRecord(serverId, activityId, roleId, roundIndex, pageIndex, id, dailyItemData.getRefTime(), 1); + + let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.REFRESH_TASK_REWARD) + + //获得点数 + await ActivityRefreshTaskPointModel.addPoint(serverId, activityId, roleId, dailyItemData.point); + + dailyItemData.receiveRewardCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, roundIndex, pageIndex, id, type }, + item: dailyItemData, + totalPoint: playerData.totalPoint + dailyItemData.point, + })); + } + + /** + * @description 兑换点数 + * @param {{ activityId: number, roundIndex: number}} msg + * @param {BackendSession} session + * @memberof RefreshTaskHandler + */ + async exchangePoint(msg: { activityId: number, roundIndex: number }, session: BackendSession) { + const { activityId, roundIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerRefreshTaskData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if (playerData.roundIndex != roundIndex) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + + if ((playerData.totalPoint - playerData.exchangePoint) < playerData.consumePoint) {//点数不够 + return resResult(STATUS.ACTIVITY_NO_POINT); + } + + await ActivityRefreshTaskPointModel.addReceiveRecord(serverId, activityId, roleId, playerData.consumePoint); + + let rewardParamArr: Array = stringToRewardParam(playerData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.REFRESH_TASK_EXCHANGE) + + playerData.exchangePoint += playerData.consumePoint; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, roundIndex }, + item: { exchangePoint: playerData.exchangePoint }, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/selfServiceShopHandler.ts b/game-server/app/servers/activity/handler/selfServiceShopHandler.ts index 0b7254f90..ffbe0d7da 100644 --- a/game-server/app/servers/activity/handler/selfServiceShopHandler.ts +++ b/game-server/app/servers/activity/handler/selfServiceShopHandler.ts @@ -1,173 +1,174 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult, splitString } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { SelfServiceShopData } from '../../../domain/activityField/selfServiceShopField'; -import { handleCost } from '../../../services/role/rewardService'; -import { ActivitySelfServiceShopModel, ActivitySelfServiceShopModelType } from '../../../db/ActivitySelfServiceShop'; -import { ActivitySelfServiceModel } from '../../../db/ActivitySelfService'; -import { ActivitySelfServiceGoodsModel } from '../../../db/ActivitySelfServiceGoods'; -import { ActivityModelType } from '../../../db/Activity'; -import { addSelfServiceShopGiftReward, getSelfServiceShopActivityData, getPlayerActivityData } from '../../../services/activity/selfServiceShopActivityService'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { random } from 'underscore'; -import { getActivityById } from '../../../services/activity/activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../../../services/redisService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new SelfServiceShopHandler(app); -} - -export class SelfServiceShopHandler { - constructor(private app: Application) { - } - - /************************自助商店、糜家商队****************************/ - - /** - * @description 获取自助商店数据 - * @param {{ }} msg - * @param {BackendSession} session - * @memberof SelfServiceShopHandler - */ - async getSelfServiceShopActivity(msg: {}, session: BackendSession) { - const { } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getSelfServiceShopActivityData(serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let playerGoods = await ActivitySelfServiceGoodsModel.findData(playerData.activityId, roleId, playerData.roundIndex, true); - return resResult(STATUS.SUCCESS, { playerData, playerGoods: playerGoods ? playerGoods : [] }); - } - - /** - * @description 购买礼包 - * @param {{ activityId: number, roundIndex: number, index: number, cellIndex: number}} msg - * @param {BackendSession} session - * @memberof SelfServiceShopHandler - */ - async buyGift(msg: { activityId: number, roundIndex: number, index: number }, session: BackendSession) { - const { activityId, roundIndex, index } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SelfServiceShopData(activityData, createTime, serverTime); - let item = playerData.getItem(index); - - if (item.countMax > 0) {//限制购买次数 - let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityId, roleId, playerData.roundIndex, index); - if (playerRecords.length >= item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - } - - let price = item.price; - if (price > 0) {//RMB购买 - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - //检查资源 - let consume = stringToConsumeParam(item.consume) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_GIFT); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let result = await addSelfServiceShopGiftReward(roleId, roleName, sid, serverId, activityId, roundIndex, index, item); - return resResult(STATUS.SUCCESS, Object.assign(result, {})); - } - - /** - * @description 操作礼包 - * @param {{ data:Array<{activityId: number, roundIndex: number, index: number, cellIndex: number, rewardIndex: number}>}} msg - * @param {BackendSession} session - * @memberof SelfServiceShopHandler - */ - async saveGood(msg: { data: Array<{ activityId: number, roundIndex: number, index: number, cellIndex: number, rewardIndex: number }> }, session: BackendSession) { - const { data } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - for (let obj of data) { - await ActivitySelfServiceGoodsModel.addGoods(obj.activityId, roleId, obj.roundIndex, obj.index, obj.cellIndex, obj.rewardIndex); - } - - return resResult(STATUS.SUCCESS, { data }); - } - - /** - * @description 购买代币资源 - * @param {{ activityId: number, roundIndex: number}} msg - * @param {BackendSession} session - * @memberof SelfServiceShopHandler - */ - async buyRecources(msg: { activityId: number, roundIndex: number }, session: BackendSession) { - const { activityId, roundIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let activityData: ActivityModelType = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SelfServiceShopData(activityData, createTime, serverTime); - let unitPrice = playerData.unitPrice;//购买价格 - let unitCountMax = playerData.unitCountMax;//最大购买次数 - let unitReward = playerData.unitReward;//购买获得资源 - - let playerSelfServerData = await ActivitySelfServiceModel.findData(serverId, activityId, roleId, roundIndex); - - let buyCount = (playerSelfServerData && playerSelfServerData.unitBuyCount) ? playerSelfServerData.unitBuyCount : 0; - if (buyCount >= unitCountMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - - //检查资源 - let consume = stringToConsumeParam(unitPrice) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_RESOURCE); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - await ActivitySelfServiceModel.addBuyRecord(serverId, activityId, roleId, roundIndex, 1); - let rewardArray = stringToRewardParam(unitReward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_RESOURCE); - - return resResult(STATUS.SUCCESS, Object.assign(result, { unitBuyCount: buyCount + 1 })); - } - - /** - * @description 获取关卡id - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof SelfServiceShopHandler - */ - async getWarId(msg: { activityId: number, }, session: BackendSession) { - const { activityId, } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerActivityData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (playerData.challengeCount >= playerData.count) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - - let warIdArray = splitString(playerData.warid, '&') - let index = random(warIdArray.length - 1); - let warId = warIdArray[index]; - - return resResult(STATUS.SUCCESS, { warId }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult, splitString } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { SelfServiceShopData } from '@domain/activityField/selfServiceShopField'; +import { handleCost } from '../../../services/role/rewardService'; +import { ActivitySelfServiceShopModel, ActivitySelfServiceShopModelType } from '@db/ActivitySelfServiceShop'; +import { ActivitySelfServiceModel } from '@db/ActivitySelfService'; +import { ActivitySelfServiceGoodsModel } from '@db/ActivitySelfServiceGoods'; +import { ActivityModelType } from '@db/Activity'; +import { addSelfServiceShopGiftReward, getSelfServiceShopActivityData, getPlayerActivityData } from '../../../services/activity/selfServiceShopActivityService'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { random } from 'underscore'; +import { getActivityById } from '../../../services/activity/activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../../../services/redisService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new SelfServiceShopHandler(app); +} + +export class SelfServiceShopHandler { + constructor(private app: Application) { + } + + /************************自助商店、糜家商队****************************/ + + /** + * @description 获取自助商店数据 + * @param {{ }} msg + * @param {BackendSession} session + * @memberof SelfServiceShopHandler + */ + async getSelfServiceShopActivity(msg: {}, session: BackendSession) { + const { } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getSelfServiceShopActivityData(serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let playerGoods = await ActivitySelfServiceGoodsModel.findData(playerData.activityId, roleId, playerData.roundIndex, true); + return resResult(STATUS.SUCCESS, { playerData, playerGoods: playerGoods ? playerGoods : [] }); + } + + /** + * @description 购买礼包 + * @param {{ activityId: number, roundIndex: number, index: number, cellIndex: number}} msg + * @param {BackendSession} session + * @memberof SelfServiceShopHandler + */ + async buyGift(msg: { activityId: number, roundIndex: number, index: number }, session: BackendSession) { + const { activityId, roundIndex, index } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SelfServiceShopData(activityData, createTime, serverTime); + let item = playerData.getItem(index); + + if (item.countMax > 0) {//限制购买次数 + let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityId, roleId, playerData.roundIndex, index); + if (playerRecords.length >= item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + } + + let price = item.price; + if (price > 0) {//RMB购买 + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + //检查资源 + let consume = stringToConsumeParam(item.consume) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_GIFT); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let result = await addSelfServiceShopGiftReward(roleId, roleName, sid, serverId, activityId, roundIndex, index, item); + return resResult(STATUS.SUCCESS, Object.assign(result, {})); + } + + /** + * @description 操作礼包 + * @param {{ data:Array<{activityId: number, roundIndex: number, index: number, cellIndex: number, rewardIndex: number}>}} msg + * @param {BackendSession} session + * @memberof SelfServiceShopHandler + */ + async saveGood(msg: { data: Array<{ activityId: number, roundIndex: number, index: number, cellIndex: number, rewardIndex: number }> }, session: BackendSession) { + const { data } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + for (let obj of data) { + await ActivitySelfServiceGoodsModel.addGoods(obj.activityId, roleId, obj.roundIndex, obj.index, obj.cellIndex, obj.rewardIndex); + } + + return resResult(STATUS.SUCCESS, { data }); + } + + /** + * @description 购买代币资源 + * @param {{ activityId: number, roundIndex: number}} msg + * @param {BackendSession} session + * @memberof SelfServiceShopHandler + */ + async buyRecources(msg: { activityId: number, roundIndex: number }, session: BackendSession) { + const { activityId, roundIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let activityData: ActivityModelType = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SelfServiceShopData(activityData, createTime, serverTime); + let unitPrice = playerData.unitPrice;//购买价格 + let unitCountMax = playerData.unitCountMax;//最大购买次数 + let unitReward = playerData.unitReward;//购买获得资源 + + let playerSelfServerData = await ActivitySelfServiceModel.findData(serverId, activityId, roleId, roundIndex); + + let buyCount = (playerSelfServerData && playerSelfServerData.unitBuyCount) ? playerSelfServerData.unitBuyCount : 0; + if (buyCount >= unitCountMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + + //检查资源 + let consume = stringToConsumeParam(unitPrice) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_RESOURCE); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + await ActivitySelfServiceModel.addBuyRecord(serverId, activityId, roleId, roundIndex, 1); + let rewardArray = stringToRewardParam(unitReward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_RESOURCE); + + return resResult(STATUS.SUCCESS, Object.assign(result, { unitBuyCount: buyCount + 1 })); + } + + /** + * @description 获取关卡id + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof SelfServiceShopHandler + */ + async getWarId(msg: { activityId: number, }, session: BackendSession) { + const { activityId, } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerActivityData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (playerData.challengeCount >= playerData.count) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + + let warIdArray = splitString(playerData.warid, '&') + let index = random(warIdArray.length - 1); + let warId = warIdArray[index]; + + return resResult(STATUS.SUCCESS, { warId }); + } +} + diff --git a/game-server/app/servers/activity/handler/sevenDaysHandler.ts b/game-server/app/servers/activity/handler/sevenDaysHandler.ts index 8d000cd9c..91dc3554a 100644 --- a/game-server/app/servers/activity/handler/sevenDaysHandler.ts +++ b/game-server/app/servers/activity/handler/sevenDaysHandler.ts @@ -1,221 +1,222 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; -import { handleCost } from '../../../services/role/rewardService'; -import { ActivityGrowthModel } from '../../../db/ActivityGrowth'; -import { ActivityDailyGiftsModel } from '../../../db/ActivityDailyGifts'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityDailyChallengesModel } from '../../../db/ActivityDailyChallenges'; -import { ActivityGrowthPointModel } from '../../../db/ActivityGrowthPoint'; -import { getPlayerSevenDaysData, getPlayerSevenDaysGrowthData, getPlayerSevenDaysDailyChallengesData, getPlayerSevenDaysDailyGiftsData } from '../../../services/activity/sevenDaysService'; -import { SevenDaysGrowthItem, SevenDaysPointRewardItem, SevenDaysDailyItem, SevenDaysDailyGiftItem } from '../../../domain/activityField/sevenDaysField'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new SevenDaysHandler(app); -} - -export class SevenDaysHandler { - constructor(private app: Application) { - } - - - /** - * @description 获取七天乐活动总的数据 - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof SevenDaysHandler - */ - async getSevenDaysActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerSevenDaysData(activityId, serverId, roleId) - - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /************************成长任务****************************/ - - /** - * @description 获取成长任务每天完成的单个奖励 - * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg - * @param {BackendSession} session - * @memberof SevenDaysHandler - */ - async getGrowthCellReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerSevenDaysGrowthData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let growthItemData: SevenDaysGrowthItem = playerData.growth.findGrowthItem(dayIndex, cellIndex, type); - if (!growthItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!growthItemData.isComplete()) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (!growthItemData.canReceive()) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityGrowthModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - let rewardParamArr: Array = stringToRewardParam(growthItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_REWARD) - - growthItemData.receiveRewardCount = 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex, type }, - item: growthItemData, - })); - } - - /** - * @description 成长任务每天奖章兑换奖励 - * @param {{ activityId: number, id: number}} msg - * @param {BackendSession} session - * @memberof SevenDaysHandler - */ - async getGrowthDayReward(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerSevenDaysGrowthData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let pointItemData: SevenDaysPointRewardItem = playerData.growth.findPointItem(id); - if (!pointItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (playerData.growth.getTotalPoint() < pointItemData.progress) { - return resResult(STATUS.ACTIVITY_NO_POINT); - } - if (pointItemData.getPointReward) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityGrowthPointModel.addRecord(serverId, activityId, roleId, id); - - let rewardParamArr: Array = stringToRewardParam(pointItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_DAY_EXCHANGE) - - - pointItemData.getPointReward = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, id }, - item: pointItemData, - })); - } - - /************************今日挑战****************************/ - - /** - * @description 获取今日挑战的单个奖励 - * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg - * @param {BackendSession} session - * @memberof SevenDaysHandler - */ - async getDailyChallengeReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex, type } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerSevenDaysDailyChallengesData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let dailyItemData: SevenDaysDailyItem = playerData.dailyChallenge.findDailyChallengesItem(dayIndex, cellIndex, type); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!dailyItemData.isComplete()) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (!dailyItemData.canReceive()) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityDailyChallengesModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_CHALLENGE_REWARD) - - dailyItemData.receiveRewardCount = 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex, type }, - item: dailyItemData, - })); - } - - - /************************每日特惠礼包****************************/ - - /** - * @description 购买每日特惠礼包 - * @param {{ activityId: number, dayIndex: number, cellIndex: number}} msg - * @param {BackendSession} session - * @memberof SevenDaysHandler - */ - async buyDailyGiftsCell(msg: { activityId: number, dayIndex: number, cellIndex: number }, session: BackendSession) { - const { activityId, dayIndex, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerSevenDaysDailyGiftsData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let dailyItemData: SevenDaysDailyGiftItem = playerData.dailyGift.findDailyGiftsItem(dayIndex, cellIndex); - if (!dailyItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!dailyItemData.canBuy()) {//最大次数 - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - if (dayIndex > playerData.today()) {//还未开启 - return resResult(STATUS.ACTIVITY_UNOPENED); - } - - //货币是否足够 - let consumeData = dailyItemData.consumeRes(); - let consumeType = consumeData.type;//购买类型 - - if (consumeType == ACTIVITY_RESOURCES_TYPE.GOODS) {//物品表,元宝、金币、体力 - let result = await handleCost(roleId, sid, [{ id: consumeData.id, count: consumeData.count }], ITEM_CHANGE_REASON.BUY_DAILY_GIFTS); - if (!result) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - } else if (consumeType == ACTIVITY_RESOURCES_TYPE.RMB) {//RMB购买 - return resResult(STATUS.ACTIVITY_NEED_PAY); - } - - await ActivityDailyGiftsModel.buyRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.BUY_DAILY_GIFTS) - - dailyItemData.buyCount += 1; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex, cellIndex }, - item: dailyItemData, - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; +import { handleCost } from '../../../services/role/rewardService'; +import { ActivityGrowthModel } from '@db/ActivityGrowth'; +import { ActivityDailyGiftsModel } from '@db/ActivityDailyGifts'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityDailyChallengesModel } from '@db/ActivityDailyChallenges'; +import { ActivityGrowthPointModel } from '@db/ActivityGrowthPoint'; +import { getPlayerSevenDaysData, getPlayerSevenDaysGrowthData, getPlayerSevenDaysDailyChallengesData, getPlayerSevenDaysDailyGiftsData } from '../../../services/activity/sevenDaysService'; +import { SevenDaysGrowthItem, SevenDaysPointRewardItem, SevenDaysDailyItem, SevenDaysDailyGiftItem } from '@domain/activityField/sevenDaysField'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new SevenDaysHandler(app); +} + +export class SevenDaysHandler { + constructor(private app: Application) { + } + + + /** + * @description 获取七天乐活动总的数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof SevenDaysHandler + */ + async getSevenDaysActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerSevenDaysData(activityId, serverId, roleId) + + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /************************成长任务****************************/ + + /** + * @description 获取成长任务每天完成的单个奖励 + * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg + * @param {BackendSession} session + * @memberof SevenDaysHandler + */ + async getGrowthCellReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerSevenDaysGrowthData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let growthItemData: SevenDaysGrowthItem = playerData.growth.findGrowthItem(dayIndex, cellIndex, type); + if (!growthItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!growthItemData.isComplete()) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (!growthItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityGrowthModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + let rewardParamArr: Array = stringToRewardParam(growthItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_REWARD) + + growthItemData.receiveRewardCount = 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex, type }, + item: growthItemData, + })); + } + + /** + * @description 成长任务每天奖章兑换奖励 + * @param {{ activityId: number, id: number}} msg + * @param {BackendSession} session + * @memberof SevenDaysHandler + */ + async getGrowthDayReward(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerSevenDaysGrowthData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let pointItemData: SevenDaysPointRewardItem = playerData.growth.findPointItem(id); + if (!pointItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (playerData.growth.getTotalPoint() < pointItemData.progress) { + return resResult(STATUS.ACTIVITY_NO_POINT); + } + if (pointItemData.getPointReward) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityGrowthPointModel.addRecord(serverId, activityId, roleId, id); + + let rewardParamArr: Array = stringToRewardParam(pointItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.GROWTH_DAY_EXCHANGE) + + + pointItemData.getPointReward = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, id }, + item: pointItemData, + })); + } + + /************************今日挑战****************************/ + + /** + * @description 获取今日挑战的单个奖励 + * @param {{ activityId: number, dayIndex: number, cellIndex: number, type: number}} msg + * @param {BackendSession} session + * @memberof SevenDaysHandler + */ + async getDailyChallengeReward(msg: { activityId: number, dayIndex: number, cellIndex: number, type: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex, type } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerSevenDaysDailyChallengesData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let dailyItemData: SevenDaysDailyItem = playerData.dailyChallenge.findDailyChallengesItem(dayIndex, cellIndex, type); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!dailyItemData.isComplete()) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (!dailyItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityDailyChallengesModel.addCellRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_CHALLENGE_REWARD) + + dailyItemData.receiveRewardCount = 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex, type }, + item: dailyItemData, + })); + } + + + /************************每日特惠礼包****************************/ + + /** + * @description 购买每日特惠礼包 + * @param {{ activityId: number, dayIndex: number, cellIndex: number}} msg + * @param {BackendSession} session + * @memberof SevenDaysHandler + */ + async buyDailyGiftsCell(msg: { activityId: number, dayIndex: number, cellIndex: number }, session: BackendSession) { + const { activityId, dayIndex, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerSevenDaysDailyGiftsData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let dailyItemData: SevenDaysDailyGiftItem = playerData.dailyGift.findDailyGiftsItem(dayIndex, cellIndex); + if (!dailyItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!dailyItemData.canBuy()) {//最大次数 + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + if (dayIndex > playerData.today()) {//还未开启 + return resResult(STATUS.ACTIVITY_UNOPENED); + } + + //货币是否足够 + let consumeData = dailyItemData.consumeRes(); + let consumeType = consumeData.type;//购买类型 + + if (consumeType == ACTIVITY_RESOURCES_TYPE.GOODS) {//物品表,元宝、金币、体力 + let result = await handleCost(roleId, sid, [{ id: consumeData.id, count: consumeData.count }], ITEM_CHANGE_REASON.BUY_DAILY_GIFTS); + if (!result) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } else if (consumeType == ACTIVITY_RESOURCES_TYPE.RMB) {//RMB购买 + return resResult(STATUS.ACTIVITY_NEED_PAY); + } + + await ActivityDailyGiftsModel.buyRecord(serverId, activityId, roleId, dayIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(dailyItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.BUY_DAILY_GIFTS) + + dailyItemData.buyCount += 1; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex, cellIndex }, + item: dailyItemData, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/signInHandler.ts b/game-server/app/servers/activity/handler/signInHandler.ts index 86c2ac86f..a73c14055 100644 --- a/game-server/app/servers/activity/handler/signInHandler.ts +++ b/game-server/app/servers/activity/handler/signInHandler.ts @@ -1,112 +1,113 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, ACTIVITY_TYPE, SERVER_OPEN_TIME, ITEM_CHANGE_REASON, } from '../../../consts'; -import { canBuyVip, getPlayerSignInData } from '../../../services/activity/signInService'; -import { handleCost } from '../../../services/role/rewardService'; -import { SignInItem } from '../../../domain/activityField/signInField'; -import { ActivitySignInModel } from '../../../db/ActivitySignIn'; -import moment = require('moment'); -import { RoleModel } from '../../../db/Role'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new SignInHandler(app); -} - -export class SignInHandler { - constructor(private app: Application) { - } - - /************************签到活动****************************/ - - /** - * @description 获取普通签到活动数据 - * @param {BackendSession} session - * @param {{ activityId: number}} msg - * @memberof SignInHandler - */ - async getSignInActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let curDate = moment(new Date()).valueOf(); - - let playerData = await getPlayerSignInData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 - return resResult(STATUS.ACTIVITY_CLOSED); - } - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 签到获得奖励 - * @param {{ activityId: number, dayIndex: number}} msg - * @param {BackendSession} session - * @memberof SignInHandler - */ - async getSignInReward(msg: { activityId: number, dayIndex: number }, session: BackendSession) { - const { activityId, dayIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerSignInData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (!playerData.canShow()) {//未开启 - return resResult(STATUS.ACTIVITY_CLOSED); - } - - if (dayIndex > playerData.todayIndex) { - return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); - } - let isDelay = false;//补签 - if(dayIndex < playerData.todayIndex) { - isDelay = true; - } - let roundIndex = playerData.roundIndex; - - //高级签到开启条件 - let { lv } = await RoleModel.findByRoleId(roleId); - if (playerData.type == ACTIVITY_TYPE.SIGN_IN_VIP) { - if (!canBuyVip(lv)) - return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); - - if (!playerData.isVip) { - return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); - } - } - if(playerData.price > 0 && !playerData.isVip) return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); - - let signinItemData: SignInItem = playerData.findDayItem(dayIndex); - if (!signinItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!signinItemData.canReceive()) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - if (isDelay) { - let consume = stringToConsumeParam(playerData.consume) - let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.REPAIRE_SIGNIN); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - await ActivitySignInModel.addSignInRecord(activityId, roleId, roundIndex, dayIndex); - - let rewardParamArr: Array = stringToRewardParam(signinItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.SIGNIN) - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, dayIndex }, - })); - } - -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS, ACTIVITY_TYPE, SERVER_OPEN_TIME, ITEM_CHANGE_REASON, } from '../../../consts'; +import { canBuyVip, getPlayerSignInData } from '../../../services/activity/signInService'; +import { handleCost } from '../../../services/role/rewardService'; +import { SignInItem } from '@domain/activityField/signInField'; +import { ActivitySignInModel } from '@db/ActivitySignIn'; +import moment = require('moment'); +import { RoleModel } from '@db/Role'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new SignInHandler(app); +} + +export class SignInHandler { + constructor(private app: Application) { + } + + /************************签到活动****************************/ + + /** + * @description 获取普通签到活动数据 + * @param {BackendSession} session + * @param {{ activityId: number}} msg + * @memberof SignInHandler + */ + async getSignInActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let curDate = moment(new Date()).valueOf(); + + let playerData = await getPlayerSignInData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 + return resResult(STATUS.ACTIVITY_CLOSED); + } + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 签到获得奖励 + * @param {{ activityId: number, dayIndex: number}} msg + * @param {BackendSession} session + * @memberof SignInHandler + */ + async getSignInReward(msg: { activityId: number, dayIndex: number }, session: BackendSession) { + const { activityId, dayIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerSignInData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (!playerData.canShow()) {//未开启 + return resResult(STATUS.ACTIVITY_CLOSED); + } + + if (dayIndex > playerData.todayIndex) { + return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + } + let isDelay = false;//补签 + if(dayIndex < playerData.todayIndex) { + isDelay = true; + } + let roundIndex = playerData.roundIndex; + + //高级签到开启条件 + let { lv } = await RoleModel.findByRoleId(roleId); + if (playerData.type == ACTIVITY_TYPE.SIGN_IN_VIP) { + if (!canBuyVip(lv)) + return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); + + if (!playerData.isVip) { + return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); + } + } + if(playerData.price > 0 && !playerData.isVip) return resResult(STATUS.ACTIVITY_SIGNIN_VIP_CONDITION); + + let signinItemData: SignInItem = playerData.findDayItem(dayIndex); + if (!signinItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!signinItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + if (isDelay) { + let consume = stringToConsumeParam(playerData.consume) + let consumeResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.REPAIRE_SIGNIN); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + await ActivitySignInModel.addSignInRecord(activityId, roleId, roundIndex, dayIndex); + + let rewardParamArr: Array = stringToRewardParam(signinItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.SIGNIN) + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, dayIndex }, + })); + } + +} + diff --git a/game-server/app/servers/activity/handler/taskPassHandler.ts b/game-server/app/servers/activity/handler/taskPassHandler.ts index 4ac0ef8d1..1312cea29 100644 --- a/game-server/app/servers/activity/handler/taskPassHandler.ts +++ b/game-server/app/servers/activity/handler/taskPassHandler.ts @@ -1,87 +1,88 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { getTaskPassData, getTaskPassDataShow } from '../../../services/activity/taskPassService'; -import { ActivityTaskPassModel, ReceivedReward } from '../../../db/ActivityTaskPass'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { nowSeconds } from '../../../pubUtils/timeUtil'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { ItemInter } from '../../../pubUtils/interface'; -import { isNumber, pick } from 'underscore'; -import { handleCost } from '../../../services/role/rewardService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new TaskPassHandler(app); -} - -export class TaskPassHandler { - constructor(private app: Application) { - } - - /************************战令系统****************************/ - // 获得战令活动数据 - public async getTaskPassData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getTaskPassDataShow(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, { playerData }); - } - - // (一键)领取 - public async receiveItems(msg: { activityId: number, pageIndex: number, lv: number }, session: BackendSession) { - - const { activityId, pageIndex, lv = 0 } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getTaskPassData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let items = playerData.receiveItems(pageIndex, lv); - if(!items) return resResult(STATUS.ACTIVITY_ITEM_CANNOT_RECEIVE); - - let records: ReceivedReward[] = [], rewards: RewardParam[] = []; - for(let item of items) { - records.push({ pageIndex: item.pageIndex, lv: item.lv, receiveTime: nowSeconds() }); - rewards.push(...stringToRewardParam(item.reward)); - } - await ActivityTaskPassModel.receiveItems(serverId, activityId, roleId, playerData.roundIndex, records); - let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_TASK_PASS); - - return resResult(STATUS.SUCCESS, { items, ...result }); - } - - // 加速 - public async speedUp(msg: { activityId: number, count: number }, session: BackendSession) { - - const { activityId, count } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getTaskPassData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let cost: ItemInter[] = []; - let consumeArr = stringToConsumeParam(playerData.spdUp.cost); - for(let consume of consumeArr) { - cost.push({ ...consume, count: consume.count * count }); - } - let consumeResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TASK_PASS_SPD_UP); - if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let addPoint = playerData.spdUp.point * count; - await ActivityTaskPassModel.addPoint(serverId, activityId, roleId, playerData.roundIndex, addPoint, count); - let result = playerData.addPoint(addPoint, count); - - return resResult(STATUS.SUCCESS, result); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { getTaskPassData, getTaskPassDataShow } from '../../../services/activity/taskPassService'; +import { ActivityTaskPassModel, ReceivedReward } from '@db/ActivityTaskPass'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { ItemInter } from '@pubUtils/interface'; +import { isNumber, pick } from 'underscore'; +import { handleCost } from '../../../services/role/rewardService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new TaskPassHandler(app); +} + +export class TaskPassHandler { + constructor(private app: Application) { + } + + /************************战令系统****************************/ + // 获得战令活动数据 + public async getTaskPassData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getTaskPassDataShow(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, { playerData }); + } + + // (一键)领取 + public async receiveItems(msg: { activityId: number, pageIndex: number, lv: number }, session: BackendSession) { + + const { activityId, pageIndex, lv = 0 } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getTaskPassData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let items = playerData.receiveItems(pageIndex, lv); + if(!items) return resResult(STATUS.ACTIVITY_ITEM_CANNOT_RECEIVE); + + let records: ReceivedReward[] = [], rewards: RewardParam[] = []; + for(let item of items) { + records.push({ pageIndex: item.pageIndex, lv: item.lv, receiveTime: nowSeconds() }); + rewards.push(...stringToRewardParam(item.reward)); + } + await ActivityTaskPassModel.receiveItems(serverId, activityId, roleId, playerData.roundIndex, records); + let result = await addReward(roleId, roleName, sid, serverId, rewards, ITEM_CHANGE_REASON.ACT_TASK_PASS); + + return resResult(STATUS.SUCCESS, { items, ...result }); + } + + // 加速 + public async speedUp(msg: { activityId: number, count: number }, session: BackendSession) { + + const { activityId, count } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getTaskPassData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let cost: ItemInter[] = []; + let consumeArr = stringToConsumeParam(playerData.spdUp.cost); + for(let consume of consumeArr) { + cost.push({ ...consume, count: consume.count * count }); + } + let consumeResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TASK_PASS_SPD_UP); + if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let addPoint = playerData.spdUp.point * count; + await ActivityTaskPassModel.addPoint(serverId, activityId, roleId, playerData.roundIndex, addPoint, count); + let result = playerData.addPoint(addPoint, count); + + return resResult(STATUS.SUCCESS, result); + } +} + diff --git a/game-server/app/servers/activity/handler/thirtyDaysHandler.ts b/game-server/app/servers/activity/handler/thirtyDaysHandler.ts index e78a7a2b7..1bb5d11e5 100644 --- a/game-server/app/servers/activity/handler/thirtyDaysHandler.ts +++ b/game-server/app/servers/activity/handler/thirtyDaysHandler.ts @@ -1,142 +1,143 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, ACTIVITY_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; -import { getPlayerThirtyDaysData } from '../../../services/activity/thirtyDaysService'; -import { ThirtyDaysData, ThirtyDaysItem, ThirtyDaysPointItem } from '../../../domain/activityField/thirtyDaysField'; -import { ActivityThirtyDaysModel } from '../../../db/ActivityThirtyDays'; -import { ActivityThirtyDaysPointRewardModel } from '../../../db/ActivityThirtyDaysPointReward'; -import { ActivityModel, ActivityModelType } from '../../../db/Activity'; -import { ServerlistModel } from '../../../db/Serverlist'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ThirtyDaysHandler(app); -} - -export class ThirtyDaysHandler { - constructor(private app: Application) { - } - - /************************30天大目标****************************/ - - /** - * @description 获取30目标活动数据 - * @param {{ }} msg - * @param {{ activityId: number}} msg - * @param {BackendSession} session - * @memberof ThirtyDaysHandler - */ - async getThirtyDaysActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_THIRTY_DAYS_END); - - return resResult(STATUS.SUCCESS, { playerData, todayIndex: playerData.todayIndex }); - } - - /** - * @description 获取30天完成任务的奖励 - * @param {{ activityId: number, pageIndex: number, cellIndex: number,tab: number}} msg - * @param {BackendSession} session - * @memberof ThirtyDaysHandler - */ - async getThirtyDaysCellReward(msg: { activityId: number, pageIndex: number, cellIndex: number, tab: number }, session: BackendSession) { - const { activityId, pageIndex, cellIndex, tab } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (tab > 1) { - let item = playerData.findThirtyDaysItem(pageIndex, cellIndex, tab - 1) - if (!item.isReceive) { - return resResult(STATUS.ACTIVITY_PRE_UNCOMPLETE); - } - } - - let thirtyDaysItemData: ThirtyDaysItem = playerData.findThirtyDaysItem(pageIndex, cellIndex, tab); - if (!thirtyDaysItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (!thirtyDaysItemData.isComplete) {//未完成任务 - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (thirtyDaysItemData.isReceive) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - if (0 < playerData.todayIndex && playerData.todayIndex <= playerData.days) {//时间正常范围内 - - } else if (playerData.todayIndex > playerData.days) {//活动已经过期 - // console.log('过期奖励') - let expiredItems: Array = playerData.needMark(); - let cells = expiredItems.map(obj => obj.cellIndex) - await ActivityThirtyDaysPointRewardModel.setExpired(activityId, roleId, cells); - } else {//活动未到开启时间 - return resResult(STATUS.ACTIVITY_TIME_ERROR); - } - - await ActivityThirtyDaysModel.addRecord(serverId, activityId, roleId, pageIndex, cellIndex, tab); - - let rewardParamArr: Array = stringToRewardParam(thirtyDaysItemData.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.THIRTHDAY_TASK) - thirtyDaysItemData.isReceive = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, pageIndex, cellIndex }, - item: thirtyDaysItemData, - })); - } - - /** - * @description 点数兑换奖励 - * @param {{ activityId: number, cellIndex: number}} msg - * @param {BackendSession} session - * @memberof ThirtyDaysHandler - */ - async getThirtyDaysPointReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { - const { activityId, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let thirtyDaysPointItemData: ThirtyDaysPointItem = playerData.findThirtyDaysPointItem(cellIndex); - if (!thirtyDaysPointItemData) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (playerData.totalPoint < thirtyDaysPointItemData.consumePoint) {//点数不足 - return resResult(STATUS.ACTIVITY_NO_POINT); - } - if (thirtyDaysPointItemData.isReceive) {//已经领取过 - return resResult(STATUS.ACTIVITY_REWARDED); - } - - await ActivityThirtyDaysPointRewardModel.addRecord(activityId, roleId, cellIndex); - - let reward = thirtyDaysPointItemData.reward - if (thirtyDaysPointItemData.isExpired && thirtyDaysPointItemData.expiredReward && thirtyDaysPointItemData.expiredReward != '') {//过期奖励 - reward = thirtyDaysPointItemData.expiredReward; - } - - let rewardParamArr: Array = stringToRewardParam(reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.THIRTHDAY_EXCHANGE) - - thirtyDaysPointItemData.isReceive = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, cellIndex }, - item: thirtyDaysPointItemData, - })); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS, ACTIVITY_TYPE, ITEM_CHANGE_REASON } from '../../../consts'; +import { getPlayerThirtyDaysData } from '../../../services/activity/thirtyDaysService'; +import { ThirtyDaysData, ThirtyDaysItem, ThirtyDaysPointItem } from '@domain/activityField/thirtyDaysField'; +import { ActivityThirtyDaysModel } from '@db/ActivityThirtyDays'; +import { ActivityThirtyDaysPointRewardModel } from '@db/ActivityThirtyDaysPointReward'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ServerlistModel } from '@db/Serverlist'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ThirtyDaysHandler(app); +} + +export class ThirtyDaysHandler { + constructor(private app: Application) { + } + + /************************30天大目标****************************/ + + /** + * @description 获取30目标活动数据 + * @param {{ }} msg + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof ThirtyDaysHandler + */ + async getThirtyDaysActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_THIRTY_DAYS_END); + + return resResult(STATUS.SUCCESS, { playerData, todayIndex: playerData.todayIndex }); + } + + /** + * @description 获取30天完成任务的奖励 + * @param {{ activityId: number, pageIndex: number, cellIndex: number,tab: number}} msg + * @param {BackendSession} session + * @memberof ThirtyDaysHandler + */ + async getThirtyDaysCellReward(msg: { activityId: number, pageIndex: number, cellIndex: number, tab: number }, session: BackendSession) { + const { activityId, pageIndex, cellIndex, tab } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (tab > 1) { + let item = playerData.findThirtyDaysItem(pageIndex, cellIndex, tab - 1) + if (!item.isReceive) { + return resResult(STATUS.ACTIVITY_PRE_UNCOMPLETE); + } + } + + let thirtyDaysItemData: ThirtyDaysItem = playerData.findThirtyDaysItem(pageIndex, cellIndex, tab); + if (!thirtyDaysItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!thirtyDaysItemData.isComplete) {//未完成任务 + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (thirtyDaysItemData.isReceive) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + if (0 < playerData.todayIndex && playerData.todayIndex <= playerData.days) {//时间正常范围内 + + } else if (playerData.todayIndex > playerData.days) {//活动已经过期 + // console.log('过期奖励') + let expiredItems: Array = playerData.needMark(); + let cells = expiredItems.map(obj => obj.cellIndex) + await ActivityThirtyDaysPointRewardModel.setExpired(activityId, roleId, cells); + } else {//活动未到开启时间 + return resResult(STATUS.ACTIVITY_TIME_ERROR); + } + + await ActivityThirtyDaysModel.addRecord(serverId, activityId, roleId, pageIndex, cellIndex, tab); + + let rewardParamArr: Array = stringToRewardParam(thirtyDaysItemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.THIRTHDAY_TASK) + thirtyDaysItemData.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, pageIndex, cellIndex }, + item: thirtyDaysItemData, + })); + } + + /** + * @description 点数兑换奖励 + * @param {{ activityId: number, cellIndex: number}} msg + * @param {BackendSession} session + * @memberof ThirtyDaysHandler + */ + async getThirtyDaysPointReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { + const { activityId, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerThirtyDaysData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let thirtyDaysPointItemData: ThirtyDaysPointItem = playerData.findThirtyDaysPointItem(cellIndex); + if (!thirtyDaysPointItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (playerData.totalPoint < thirtyDaysPointItemData.consumePoint) {//点数不足 + return resResult(STATUS.ACTIVITY_NO_POINT); + } + if (thirtyDaysPointItemData.isReceive) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivityThirtyDaysPointRewardModel.addRecord(activityId, roleId, cellIndex); + + let reward = thirtyDaysPointItemData.reward + if (thirtyDaysPointItemData.isExpired && thirtyDaysPointItemData.expiredReward && thirtyDaysPointItemData.expiredReward != '') {//过期奖励 + reward = thirtyDaysPointItemData.expiredReward; + } + + let rewardParamArr: Array = stringToRewardParam(reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.THIRTHDAY_EXCHANGE) + + thirtyDaysPointItemData.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, cellIndex }, + item: thirtyDaysPointItemData, + })); + } +} + diff --git a/game-server/app/servers/activity/handler/timeLimitRankHandler.ts b/game-server/app/servers/activity/handler/timeLimitRankHandler.ts index 197884f4e..3e53a6e70 100644 --- a/game-server/app/servers/activity/handler/timeLimitRankHandler.ts +++ b/game-server/app/servers/activity/handler/timeLimitRankHandler.ts @@ -1,100 +1,101 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { DEBUG_MAGIC_WORD, getRedisKeyByRankType, HERO_SELECT, ITEM_CHANGE_REASON, RANK_TYPE, ROLE_SELECT, STATUS } from '../../../consts'; -import { pick } from 'underscore'; -import { getTimeLimitRankData, getTimeLimitRankDataShow, sendRankMail, takeSnapshot } from '../../../services/activity/timeLimitRankService'; -import { getRankInHandler, Rank } from '../../../services/rankService'; -import { getActivityById } from '../../../services/activity/activityService'; -import { TimeLimitRankData } from '../../../domain/activityField/timeLimitRankField'; -import { getServerCreateTime, hasKey } from '../../../services/redisService'; -import { KeyName } from '../../../domain/rank'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new TimeLimitRankHandler(app); -} - -export class TimeLimitRankHandler { - constructor(private app: Application) { - } - - /************************幸运转盘****************************/ - /** - * @description 幸运转盘活动 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof TimeLimitRankHandler - */ - async getTimeLimitRankData(msg: { activityId: number }, session: BackendSession) { - const serverId = session.get('serverId'); - const { activityId } = msg; - - let playerData = await getTimeLimitRankDataShow(activityId, serverId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - - return resResult(STATUS.SUCCESS, { playerData }); - } - - /** - * @description 获得排行榜 - * @param {{ activityId: number, }} msg - * @param {BackendSession} session - * @memberof TimeLimitRankHandler - */ - async getRank(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getTimeLimitRankData(activityId, serverId); - if (!playerData) { - return resResult(STATUS.ACTIVITY_MISSING); - } - let type = playerData.rankType; - - let redisKey = getRedisKeyByRankType(type, true); - let keyName = new KeyName(redisKey, { serverId, activityId }); - if(!(await hasKey(keyName.getName()))) { - redisKey = getRedisKeyByRankType(type); - } - if (!redisKey) return resResult(STATUS.WRONG_PARMS); - - let result = await getRankInHandler(redisKey, type, { serverId, activityId: playerData.activityId }, session); - if(!result) return resResult(STATUS.WRONG_PARMS); - - return resResult(STATUS.SUCCESS, { - ...pick(playerData, ['activityId', 'tabName', 'beginTime', 'endTime', 'rankEndTime', 'rankType', 'rankRewards']), - ...result - }); - } - - - async debugSendMail(msg: { magicWord: string, activityId: number }, session: BackendSession) { - let serverId = session.get('serverId'); - const { magicWord, activityId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let playerData = await getTimeLimitRankData(activityId, serverId); - await sendRankMail(playerData, serverId); - return resResult(STATUS.SUCCESS); - } - - async debugTakeSnapshot(msg: { magicWord: string, activityId: number }, session: BackendSession) { - let serverId = session.get('serverId'); - - const { magicWord, activityId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let activityData = await getActivityById(activityId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TimeLimitRankData(activityData, 0, serverTime); - if(!playerData.needSnapshot) return resResult(STATUS.WRONG_PARMS); - await takeSnapshot(playerData, serverId); - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { DEBUG_MAGIC_WORD, getRedisKeyByRankType, HERO_SELECT, ITEM_CHANGE_REASON, RANK_TYPE, ROLE_SELECT, STATUS } from '../../../consts'; +import { pick } from 'underscore'; +import { getTimeLimitRankData, getTimeLimitRankDataShow, sendRankMail, takeSnapshot } from '../../../services/activity/timeLimitRankService'; +import { getRankInHandler, Rank } from '../../../services/rankService'; +import { getActivityById } from '../../../services/activity/activityService'; +import { TimeLimitRankData } from '@domain/activityField/timeLimitRankField'; +import { getServerCreateTime, hasKey } from '../../../services/redisService'; +import { KeyName } from '@domain/rank'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new TimeLimitRankHandler(app); +} + +export class TimeLimitRankHandler { + constructor(private app: Application) { + } + + /************************幸运转盘****************************/ + /** + * @description 幸运转盘活动 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof TimeLimitRankHandler + */ + async getTimeLimitRankData(msg: { activityId: number }, session: BackendSession) { + const serverId = session.get('serverId'); + const { activityId } = msg; + + let playerData = await getTimeLimitRankDataShow(activityId, serverId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + + return resResult(STATUS.SUCCESS, { playerData }); + } + + /** + * @description 获得排行榜 + * @param {{ activityId: number, }} msg + * @param {BackendSession} session + * @memberof TimeLimitRankHandler + */ + async getRank(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getTimeLimitRankData(activityId, serverId); + if (!playerData) { + return resResult(STATUS.ACTIVITY_MISSING); + } + let type = playerData.rankType; + + let redisKey = getRedisKeyByRankType(type, true); + let keyName = new KeyName(redisKey, { serverId, activityId }); + if(!(await hasKey(keyName.getName()))) { + redisKey = getRedisKeyByRankType(type); + } + if (!redisKey) return resResult(STATUS.WRONG_PARMS); + + let result = await getRankInHandler(redisKey, type, { serverId, activityId: playerData.activityId }, session); + if(!result) return resResult(STATUS.WRONG_PARMS); + + return resResult(STATUS.SUCCESS, { + ...pick(playerData, ['activityId', 'tabName', 'beginTime', 'endTime', 'rankEndTime', 'rankType', 'rankRewards']), + ...result + }); + } + + + async debugSendMail(msg: { magicWord: string, activityId: number }, session: BackendSession) { + let serverId = session.get('serverId'); + const { magicWord, activityId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let playerData = await getTimeLimitRankData(activityId, serverId); + await sendRankMail(playerData, serverId); + return resResult(STATUS.SUCCESS); + } + + async debugTakeSnapshot(msg: { magicWord: string, activityId: number }, session: BackendSession) { + let serverId = session.get('serverId'); + + const { magicWord, activityId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let activityData = await getActivityById(activityId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TimeLimitRankData(activityData, 0, serverTime); + if(!playerData.needSnapshot) return resResult(STATUS.WRONG_PARMS); + await takeSnapshot(playerData, serverId); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/activity/handler/treasureHuntHandler.ts b/game-server/app/servers/activity/handler/treasureHuntHandler.ts index 3e39a5baf..07bdfde10 100644 --- a/game-server/app/servers/activity/handler/treasureHuntHandler.ts +++ b/game-server/app/servers/activity/handler/treasureHuntHandler.ts @@ -1,232 +1,233 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { getPlayerTreasureHuntData, getPlayerTreasureHuntShopData, getPlayerTreasureHuntTaskData, getPlayerTreasureHuntTreasureShopData, getPlayerTreasureHuntChallengeData, getPlayerTreasureHuntFirstPageData } from '../../../services/activity/treasureHuntService'; -import { ActivityTreasureHuntShopModel } from '../../../db/ActivityTreasureHuntShop'; -import { ActivityTreasureHuntTaskModel } from '../../../db/ActivityTreasureHuntTask'; -import { handleCost } from '../../../services/role/rewardService'; -import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityTreasureHuntTreasureShopModel } from '../../../db/ActivityTreasureHuntTreasureShop'; -import { ActivityTreasureHuntFirstPageModel } from '../../../db/ActivityTreasureHuntFirstPage'; -import { CheckMeterial } from '../../../services/role/checkMaterial'; -import { ActivityTreasureHuntChallengeModel } from '../../../db/ActivityTreasureHuntChallenge'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new TreasureHuntHandler(app); -} - -export class TreasureHuntHandler { - constructor(private app: Application) { - } - - /************************寻宝骑兵活动****************************/ - - /** - * 每日物资:商店 - 寻宝备战:完成任务获得奖励,(奖品达到一定数量后开启 “寻宝大冒险”) - 寻宝大冒险:完成战棋关卡获得奖励 - 天子宝库:物品兑换奖励 - * @description 获取寻宝骑兵活动的数据 - * @param {BackendSession} session - * @memberof TreasureHuntHandler - */ - async getTreasureHuntActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - let playerData = await getPlayerTreasureHuntData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** -* @description 寻宝骑兵获取首页的奖励 -* @param {BackendSession} session -* @memberof TreasureHuntHandler -*/ - async getFirstPageReward(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerTreasureHuntFirstPageData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if (playerData.firstPage.isReceive) { - return resResult(STATUS.ACTIVITY_REWARDED); - } - - //添加领取记录 - await ActivityTreasureHuntFirstPageModel.receiveReward(serverId, activityId, roleId, playerData.roundIndex); - - let rewardParamArr: Array = stringToRewardParam(playerData.firstPage.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_FIRST_PAGE_REWARD) - - playerData.firstPage.isReceive = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId }, - item: playerData.firstPage, - })); - } - - /** - * @description 寻宝骑兵购买每日商店中的商品 - * @param {BackendSession} session - * @memberof TreasureHuntHandler - */ - async buyGoods(msg: { activityId: number, cellIndex: number, count: number }, session: BackendSession) { - const { activityId, cellIndex, count = 1 } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerTreasureHuntShopData(activityId, serverId, roleId,); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let item = playerData.shop.getItem(cellIndex); - if (!item) { - return resResult(STATUS.ACTIVITY_MISSING, {}); - } - if (item.price > 0) { - return resResult(STATUS.ACTIVITY_NEED_PAY, {}); - } - if (item.buyCount + count > item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT, {}); - } - - let consumeStr = item.getConsume(count); - let consume = stringToConsumeParam(...consumeStr); - let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY); - if (!resourceResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - //添加购买记录 - await ActivityTreasureHuntShopModel.buyShopRecord(activityId, roleId, playerData.roundIndex, playerData.todayIndex, cellIndex, count); - - let rewardParamArr: Array = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count })); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY) - - item.buyCount += count; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, cellIndex }, - item: item, - })); - } - - /** - * @description 寻宝骑兵获取寻宝备战的任务奖励 - * @param {BackendSession} session - * @memberof TreasureHuntHandler - */ - async getTaskReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { - const { activityId, cellIndex } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerTreasureHuntTaskData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let item = playerData.tasks.getItem(cellIndex); - if (!item) { - return resResult(STATUS.ACTIVITY_MISSING, {}); - } - if (item.condition > item.totalCount) { - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED, {}); - } - if (item.isReceive) { - return resResult(STATUS.ACTIVITY_REWARDED, {}); - } - - //添加购买记录 - await ActivityTreasureHuntTaskModel.receiveReward(serverId, activityId, roleId, playerData.roundIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_TASK_REWARD) - - item.isReceive = true; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, cellIndex }, - item: item, - })); - } - - /** - * @description 寻宝骑兵寻宝大冒险挑战 - * @param {BackendSession} session - * @memberof TreasureHuntHandler - */ - async challenge(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerTreasureHuntChallengeData(activityId, serverId, roleId,); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let challengeData = playerData.challenge; - //消耗资源 - let consumeStr = challengeData.consume; - let consume = stringToConsumeParam(consumeStr) - - let check = new CheckMeterial(roleId); - let isEnough = await check.decrease(consume); - if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let warId = playerData.challenge.resultWarId; - if(!warId) { - warId = playerData.challenge.randomGK(); - await ActivityTreasureHuntChallengeModel.setWarId(serverId, activityId, roleId, playerData.roundIndex, warId); - } - - return resResult(STATUS.SUCCESS, Object.assign({ warId }, { - param: { activityId }, - })); - } - - /** - * @description 寻宝骑兵购买天子宝库商店中的商品 - * @param {BackendSession} session - * @memberof TreasureHuntHandler - */ - async buyTreasureShopGoods(msg: { activityId: number, cellIndex: number, count: number }, session: BackendSession) { - const { activityId, cellIndex, count = 1 } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - let playerData = await getPlayerTreasureHuntTreasureShopData(activityId, serverId, roleId,); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - let item = playerData.treasureShop.getItem(cellIndex); - if (!item) { - return resResult(STATUS.ACTIVITY_MISSING, {}); - } - if (item.buyCount + count > item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT, {}); - } - - let consumeStrs = new Array(count).fill(item.consume); - let consume = stringToConsumeParam(...consumeStrs); - let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_SP_SHOP_BUY); - if (!resourceResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - //添加购买记录 - await ActivityTreasureHuntTreasureShopModel.addRecord(activityId, roleId, playerData.roundIndex, cellIndex, count); - - let rewardParamArr: Array = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count})); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SP_SHOP_BUY) - - item.buyCount += count; - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, cellIndex }, - item: item, - })); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { getPlayerTreasureHuntData, getPlayerTreasureHuntShopData, getPlayerTreasureHuntTaskData, getPlayerTreasureHuntTreasureShopData, getPlayerTreasureHuntChallengeData, getPlayerTreasureHuntFirstPageData } from '../../../services/activity/treasureHuntService'; +import { ActivityTreasureHuntShopModel } from '@db/ActivityTreasureHuntShop'; +import { ActivityTreasureHuntTaskModel } from '@db/ActivityTreasureHuntTask'; +import { handleCost } from '../../../services/role/rewardService'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityTreasureHuntTreasureShopModel } from '@db/ActivityTreasureHuntTreasureShop'; +import { ActivityTreasureHuntFirstPageModel } from '@db/ActivityTreasureHuntFirstPage'; +import { CheckMeterial } from '../../../services/role/checkMaterial'; +import { ActivityTreasureHuntChallengeModel } from '@db/ActivityTreasureHuntChallenge'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new TreasureHuntHandler(app); +} + +export class TreasureHuntHandler { + constructor(private app: Application) { + } + + /************************寻宝骑兵活动****************************/ + + /** + * 每日物资:商店 + 寻宝备战:完成任务获得奖励,(奖品达到一定数量后开启 “寻宝大冒险”) + 寻宝大冒险:完成战棋关卡获得奖励 + 天子宝库:物品兑换奖励 + * @description 获取寻宝骑兵活动的数据 + * @param {BackendSession} session + * @memberof TreasureHuntHandler + */ + async getTreasureHuntActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + let playerData = await getPlayerTreasureHuntData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** +* @description 寻宝骑兵获取首页的奖励 +* @param {BackendSession} session +* @memberof TreasureHuntHandler +*/ + async getFirstPageReward(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerTreasureHuntFirstPageData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if (playerData.firstPage.isReceive) { + return resResult(STATUS.ACTIVITY_REWARDED); + } + + //添加领取记录 + await ActivityTreasureHuntFirstPageModel.receiveReward(serverId, activityId, roleId, playerData.roundIndex); + + let rewardParamArr: Array = stringToRewardParam(playerData.firstPage.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_FIRST_PAGE_REWARD) + + playerData.firstPage.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId }, + item: playerData.firstPage, + })); + } + + /** + * @description 寻宝骑兵购买每日商店中的商品 + * @param {BackendSession} session + * @memberof TreasureHuntHandler + */ + async buyGoods(msg: { activityId: number, cellIndex: number, count: number }, session: BackendSession) { + const { activityId, cellIndex, count = 1 } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerTreasureHuntShopData(activityId, serverId, roleId,); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let item = playerData.shop.getItem(cellIndex); + if (!item) { + return resResult(STATUS.ACTIVITY_MISSING, {}); + } + if (item.price > 0) { + return resResult(STATUS.ACTIVITY_NEED_PAY, {}); + } + if (item.buyCount + count > item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT, {}); + } + + let consumeStr = item.getConsume(count); + let consume = stringToConsumeParam(...consumeStr); + let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY); + if (!resourceResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + //添加购买记录 + await ActivityTreasureHuntShopModel.buyShopRecord(activityId, roleId, playerData.roundIndex, playerData.todayIndex, cellIndex, count); + + let rewardParamArr: Array = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count })); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY) + + item.buyCount += count; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, cellIndex }, + item: item, + })); + } + + /** + * @description 寻宝骑兵获取寻宝备战的任务奖励 + * @param {BackendSession} session + * @memberof TreasureHuntHandler + */ + async getTaskReward(msg: { activityId: number, cellIndex: number }, session: BackendSession) { + const { activityId, cellIndex } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerTreasureHuntTaskData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let item = playerData.tasks.getItem(cellIndex); + if (!item) { + return resResult(STATUS.ACTIVITY_MISSING, {}); + } + if (item.condition > item.totalCount) { + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED, {}); + } + if (item.isReceive) { + return resResult(STATUS.ACTIVITY_REWARDED, {}); + } + + //添加购买记录 + await ActivityTreasureHuntTaskModel.receiveReward(serverId, activityId, roleId, playerData.roundIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_TASK_REWARD) + + item.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, cellIndex }, + item: item, + })); + } + + /** + * @description 寻宝骑兵寻宝大冒险挑战 + * @param {BackendSession} session + * @memberof TreasureHuntHandler + */ + async challenge(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerTreasureHuntChallengeData(activityId, serverId, roleId,); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let challengeData = playerData.challenge; + //消耗资源 + let consumeStr = challengeData.consume; + let consume = stringToConsumeParam(consumeStr) + + let check = new CheckMeterial(roleId); + let isEnough = await check.decrease(consume); + if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let warId = playerData.challenge.resultWarId; + if(!warId) { + warId = playerData.challenge.randomGK(); + await ActivityTreasureHuntChallengeModel.setWarId(serverId, activityId, roleId, playerData.roundIndex, warId); + } + + return resResult(STATUS.SUCCESS, Object.assign({ warId }, { + param: { activityId }, + })); + } + + /** + * @description 寻宝骑兵购买天子宝库商店中的商品 + * @param {BackendSession} session + * @memberof TreasureHuntHandler + */ + async buyTreasureShopGoods(msg: { activityId: number, cellIndex: number, count: number }, session: BackendSession) { + const { activityId, cellIndex, count = 1 } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + let playerData = await getPlayerTreasureHuntTreasureShopData(activityId, serverId, roleId,); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + let item = playerData.treasureShop.getItem(cellIndex); + if (!item) { + return resResult(STATUS.ACTIVITY_MISSING, {}); + } + if (item.buyCount + count > item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT, {}); + } + + let consumeStrs = new Array(count).fill(item.consume); + let consume = stringToConsumeParam(...consumeStrs); + let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_SP_SHOP_BUY); + if (!resourceResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + //添加购买记录 + await ActivityTreasureHuntTreasureShopModel.addRecord(activityId, roleId, playerData.roundIndex, cellIndex, count); + + let rewardParamArr: Array = stringToRewardParam(item.reward).map(cur => ({...cur, count: cur.count * count})); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SP_SHOP_BUY) + + item.buyCount += count; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, cellIndex }, + item: item, + })); + } +} + diff --git a/game-server/app/servers/activity/handler/vipRechargeMoneyHandler.ts b/game-server/app/servers/activity/handler/vipRechargeMoneyHandler.ts index fbd3b5569..66c868edd 100644 --- a/game-server/app/servers/activity/handler/vipRechargeMoneyHandler.ts +++ b/game-server/app/servers/activity/handler/vipRechargeMoneyHandler.ts @@ -1,111 +1,112 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; -import { getPlayerVipRechargeMoneyData, } from '../../../services/activity/vipRechargeMoneyService'; -import { VipRechargeMoneyItem } from '../../../domain/activityField/vipRechargeMoneyField'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; -import { RewardParam } from '../../../domain/activityField/rewardField'; -import { ActivityVipRechargeMoneyModel } from '../../../db/ActivityVipRechargeMoney'; -import { UserOrderModel } from '../../../db/UserOrder'; -import { dicRMB } from '../../../pubUtils/dictionary/DicRMB'; -import moment = require('moment'); - - -export default function (app: Application) { - new HandlerService(app, {}); - return new VipRechargeMoneyHandler(app); -} - -export class VipRechargeMoneyHandler { - constructor(private app: Application) { - } - - /************************vip累计充值奖励****************************/ - - /** - * @description 获取活动数据 - * @param {BackendSession} session - * @memberof VipRechargeMoneyHandler - */ - async getVipRechargeMoneyActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 获取奖励 - * @param {BackendSession} session - * @memberof VipRechargeMoneyHandler - */ - async getVipRechargeMoneyReward(msg: { activityId: number, id: number }, session: BackendSession) { - const { activityId, id } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let playerData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - let item: VipRechargeMoneyItem = playerData.findItem(id); - if (!item) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - if (playerData.totalRMB < item.condition) { - return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); - } - if (item.receiveCount >= item.countMax) { - return resResult(STATUS.ACTIVITY_MAX_COUNT); - } - - await ActivityVipRechargeMoneyModel.addRecord(serverId, activityId, roleId, id); - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.VIP_RECHARGE_MONEY) - item.receiveCount += 1; - - return resResult(STATUS.SUCCESS, Object.assign(result, { - param: { activityId, id }, - item: item - })); - } - - - /** - * @description 获取订单记录 - * @param {BackendSession} session - * @memberof VipRechargeMoneyHandler - */ - async getOrderList(msg: { begin: number, count: number }, session: BackendSession) { - const { begin, count } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - if (begin > 0 && count > 0) { - let orders = await UserOrderModel.findOrderList(serverId, roleId, begin - 1, count) - - for (let order of orders) { - let productInfo = dicRMB.get(order.productID) - if (productInfo) { - order['message'] = productInfo.message; - } - order['time'] = moment(order.createdAt).valueOf(); - delete order.createdAt; - delete order.productID; - delete order._id; - } - return resResult(STATUS.SUCCESS, { orders }); - } - return resResult(STATUS.WRONG_PARMS); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS, } from '../../../consts'; +import { getPlayerVipRechargeMoneyData, } from '../../../services/activity/vipRechargeMoneyService'; +import { VipRechargeMoneyItem } from '@domain/activityField/vipRechargeMoneyField'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { ActivityVipRechargeMoneyModel } from '@db/ActivityVipRechargeMoney'; +import { UserOrderModel } from '@db/UserOrder'; +import { dicRMB } from '@pubUtils/dictionary/DicRMB'; +import moment = require('moment'); + + +export default function (app: Application) { + new HandlerService(app, {}); + return new VipRechargeMoneyHandler(app); +} + +export class VipRechargeMoneyHandler { + constructor(private app: Application) { + } + + /************************vip累计充值奖励****************************/ + + /** + * @description 获取活动数据 + * @param {BackendSession} session + * @memberof VipRechargeMoneyHandler + */ + async getVipRechargeMoneyActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 获取奖励 + * @param {BackendSession} session + * @memberof VipRechargeMoneyHandler + */ + async getVipRechargeMoneyReward(msg: { activityId: number, id: number }, session: BackendSession) { + const { activityId, id } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let playerData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let item: VipRechargeMoneyItem = playerData.findItem(id); + if (!item) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (playerData.totalRMB < item.condition) { + return resResult(STATUS.ACTIVITY_TASK_UNCOMPLETED); + } + if (item.receiveCount >= item.countMax) { + return resResult(STATUS.ACTIVITY_MAX_COUNT); + } + + await ActivityVipRechargeMoneyModel.addRecord(serverId, activityId, roleId, id); + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.VIP_RECHARGE_MONEY) + item.receiveCount += 1; + + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, id }, + item: item + })); + } + + + /** + * @description 获取订单记录 + * @param {BackendSession} session + * @memberof VipRechargeMoneyHandler + */ + async getOrderList(msg: { begin: number, count: number }, session: BackendSession) { + const { begin, count } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + if (begin > 0 && count > 0) { + let orders = await UserOrderModel.findOrderList(serverId, roleId, begin - 1, count) + + for (let order of orders) { + let productInfo = dicRMB.get(order.productID) + if (productInfo) { + order['message'] = productInfo.message; + } + order['time'] = moment(order.createdAt).valueOf(); + delete order.createdAt; + delete order.productID; + delete order._id; + } + return resResult(STATUS.SUCCESS, { orders }); + } + return resResult(STATUS.WRONG_PARMS); + } +} + diff --git a/game-server/app/servers/activity/handler/weeklyFundHandler.ts b/game-server/app/servers/activity/handler/weeklyFundHandler.ts index b2421a6e7..d96aea3dc 100644 --- a/game-server/app/servers/activity/handler/weeklyFundHandler.ts +++ b/game-server/app/servers/activity/handler/weeklyFundHandler.ts @@ -1,68 +1,69 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; -import { getWeeklyFundDataShow, getWeeklyFundData } from '../../../services/activity/weeklyFundService'; -import { ActivityWeeklyFundModel } from '../../../db/ActivityWeeklyFund'; -import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new WeeklyFundHandler(app); -} - -export class WeeklyFundHandler { - constructor(private app: Application) { - } - - /************************周基金****************************/ - - /** - * @description 获取数据 - * @param {BackendSession} session - * @memberof WeeklyFundHandler - */ - async getData(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getWeeklyFundDataShow(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } - - /** - * @description 签到 - * @param {BackendSession} session - * @memberof WeeklyFundHandler - */ - async sign(msg: { activityId: number, dayIndex: number }, session: BackendSession) { - - const { activityId, dayIndex } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - let playerData = await getWeeklyFundData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - if(!playerData.hasBought) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_NOT_BOUGHT); - let signReward = playerData.findSignReward(dayIndex); - if(!signReward) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_NOT_FOUND); - if(signReward.hasReceived) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_HAS_SIGN); - if(signReward.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_LOCK); - - let record = await ActivityWeeklyFundModel.sign(serverId, activityId, roleId, dayIndex, playerData.todayIndex); - if(!record) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_HAS_SIGN); - - let rewardParamArr = stringToRewardParam(signReward.reward); - let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_SIGN); - - return resResult(STATUS.SUCCESS, { - activityId, dayIndex, goods, addHeros - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, STATUS } from '../../../consts'; +import { getWeeklyFundDataShow, getWeeklyFundData } from '../../../services/activity/weeklyFundService'; +import { ActivityWeeklyFundModel } from '@db/ActivityWeeklyFund'; +import { addReward, stringToRewardParam } from '../../../services/activity/giftPackageService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new WeeklyFundHandler(app); +} + +export class WeeklyFundHandler { + constructor(private app: Application) { + } + + /************************周基金****************************/ + + /** + * @description 获取数据 + * @param {BackendSession} session + * @memberof WeeklyFundHandler + */ + async getData(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getWeeklyFundDataShow(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } + + /** + * @description 签到 + * @param {BackendSession} session + * @memberof WeeklyFundHandler + */ + async sign(msg: { activityId: number, dayIndex: number }, session: BackendSession) { + + const { activityId, dayIndex } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + let playerData = await getWeeklyFundData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + if(!playerData.hasBought) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_NOT_BOUGHT); + let signReward = playerData.findSignReward(dayIndex); + if(!signReward) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_NOT_FOUND); + if(signReward.hasReceived) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_HAS_SIGN); + if(signReward.dayIndex > playerData.todayIndex) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_LOCK); + + let record = await ActivityWeeklyFundModel.sign(serverId, activityId, roleId, dayIndex, playerData.todayIndex); + if(!record) return resResult(STATUS.ACTIVITY_WEEKLY_FUND_HAS_SIGN); + + let rewardParamArr = stringToRewardParam(signReward.reward); + let { goods, addHeros } = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_SIGN); + + return resResult(STATUS.SUCCESS, { + activityId, dayIndex, goods, addHeros + }); + } +} + diff --git a/game-server/app/servers/activity/handler/yuanbaoShopHandler.ts b/game-server/app/servers/activity/handler/yuanbaoShopHandler.ts index 688a0d574..be30e5b9d 100644 --- a/game-server/app/servers/activity/handler/yuanbaoShopHandler.ts +++ b/game-server/app/servers/activity/handler/yuanbaoShopHandler.ts @@ -1,33 +1,34 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; -import { getPlayerYuanbaoShopData } from '../../../services/activity/yuanbaoService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new YuanbaoShopHandler(app); -} - -export class YuanbaoShopHandler { - constructor(private app: Application) { - } - - /************************元宝商店****************************/ - - /** - * @description 获取商店活动数据 - * @param {BackendSession} session - * @memberof YuanbaoShopHandler - */ - async getShopActivity(msg: { activityId: number }, session: BackendSession) { - const { activityId } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - - let playerData = await getPlayerYuanbaoShopData(activityId, serverId, roleId); - if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); - - return resResult(STATUS.SUCCESS, playerData); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '../../../consts'; +import { getPlayerYuanbaoShopData } from '../../../services/activity/yuanbaoService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new YuanbaoShopHandler(app); +} + +export class YuanbaoShopHandler { + constructor(private app: Application) { + } + + /************************元宝商店****************************/ + + /** + * @description 获取商店活动数据 + * @param {BackendSession} session + * @memberof YuanbaoShopHandler + */ + async getShopActivity(msg: { activityId: number }, session: BackendSession) { + const { activityId } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let playerData = await getPlayerYuanbaoShopData(activityId, serverId, roleId); + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + return resResult(STATUS.SUCCESS, playerData); + } +} + diff --git a/game-server/app/servers/activity/remote/activityRemote.ts b/game-server/app/servers/activity/remote/activityRemote.ts index 6acf8bb18..02e739636 100644 --- a/game-server/app/servers/activity/remote/activityRemote.ts +++ b/game-server/app/servers/activity/remote/activityRemote.ts @@ -1,212 +1,213 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { ActivityModel, ActivityModelType } from '../../../db/Activity'; -import { ServerlistModel } from '../../../db/Serverlist'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { taflush } from '../../../services/sdkService'; -import { ActivityInRemote } from '../../../domain/activityField/activityField'; -import { errlogger } from '../../../util/logger'; -import { ActivityGroupModel } from '../../../db/ActivityGroup'; -import { deleteActivities, loadActivities, saveActivitiesToGroup, updateActivities, _getActivityById, _getActivitiesByType, _getActivities, _getActivitiesByServerId, saveGroupToServer, addServerToGroup } from '../../../services/memoryCache/activityData'; -import { saveActivityMemory } from '../../../services/log/memoryLogService'; -import { setApiIsClose } from '../../../services/chatService'; -import { setKvToMemory } from '../../../services/pushService'; -import { sendPublicAccountGift } from '../../../services/activity/bindPhoneService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ActivityRemote(app); -} - -export class ActivityRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - - /** - * 重载json资源 - */ - public reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async updateActivities(activities: ActivityInRemote[]) { - try { - // console.log('******* activities', activities) - updateActivities(activities); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async deleteActivities(activityIds: number[]) { - try { - deleteActivities(activityIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async saveGroupToServer(groupId: number[], serverIds: number[]) { - try { - saveGroupToServer(groupId, serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async addServerToGroup(groupId: number[], serverIds: number[]) { - try { - addServerToGroup(groupId, serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async saveActivitiesToGroup(groupId: number, activities: number[]) { - try { - saveActivitiesToGroup(groupId, activities); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getActivityById(activityId: number) { - try { - return _getActivityById(activityId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getActivitiesByType(serverId: number, type: number) { - try { - return _getActivitiesByType(serverId, type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getActivitiesByServerId(serverId: number) { - try { - return _getActivitiesByServerId(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getActivities() { - try { - return _getActivities(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public saveActivityMemory() { - try { - return saveActivityMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async sendPublicAccountGift(message: string) { - try { - await sendPublicAccountGift(message); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ServerlistModel } from '@db/Serverlist'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { taflush } from '../../../services/sdkService'; +import { ActivityInRemote } from '@domain/activityField/activityField'; +import { errlogger } from '../../../util/logger'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { deleteActivities, loadActivities, saveActivitiesToGroup, updateActivities, _getActivityById, _getActivitiesByType, _getActivities, _getActivitiesByServerId, saveGroupToServer, addServerToGroup } from '../../../services/memoryCache/activityData'; +import { saveActivityMemory } from '../../../services/log/memoryLogService'; +import { setApiIsClose } from '../../../services/chatService'; +import { setKvToMemory } from '../../../services/pushService'; +import { sendPublicAccountGift } from '../../../services/activity/bindPhoneService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ActivityRemote(app); +} + +export class ActivityRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + + /** + * 重载json资源 + */ + public reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async updateActivities(activities: ActivityInRemote[]) { + try { + // console.log('******* activities', activities) + updateActivities(activities); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async deleteActivities(activityIds: number[]) { + try { + deleteActivities(activityIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async saveGroupToServer(groupId: number[], serverIds: number[]) { + try { + saveGroupToServer(groupId, serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async addServerToGroup(groupId: number[], serverIds: number[]) { + try { + addServerToGroup(groupId, serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async saveActivitiesToGroup(groupId: number, activities: number[]) { + try { + saveActivitiesToGroup(groupId, activities); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getActivityById(activityId: number) { + try { + return _getActivityById(activityId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getActivitiesByType(serverId: number, type: number) { + try { + return _getActivitiesByType(serverId, type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getActivitiesByServerId(serverId: number) { + try { + return _getActivitiesByServerId(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getActivities() { + try { + return _getActivities(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public saveActivityMemory() { + try { + return saveActivityMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async sendPublicAccountGift(message: string) { + try { + await sendPublicAccountGift(message); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/battle/handler/barrageHandler.ts b/game-server/app/servers/battle/handler/barrageHandler.ts index de96a5900..d03d2496f 100644 --- a/game-server/app/servers/battle/handler/barrageHandler.ts +++ b/game-server/app/servers/battle/handler/barrageHandler.ts @@ -1,55 +1,56 @@ -import { Application, BackendSession } from "pinus"; -import { ScriptBarrageModel } from "../../../db/ScriptBarrage"; -import { BarrageReturn } from '../../../domain/roleField/barrage'; -import { resResult, getRandEelm } from "../../../pubUtils/util"; -import { STATUS } from "../../../consts"; -import { closeScriptBarrage } from "../../../pubUtils/sdkUtil"; - -export default function(app: Application) { - return new BarrageHandler(app); -} - -export class BarrageHandler { - constructor(private app: Application) { - } - - public async sendBarrage(msg: { warId: number, rid: string, index: string, content: string }, session: BackendSession) { - if(closeScriptBarrage()) return resResult(STATUS.FUNCTION_CLOSE); - - const roleId: string = session.get('roleId'); - const { warId, rid, index, content } = msg; - const result = await ScriptBarrageModel.createBarrage(roleId, warId, rid, index, content); - let barrageList: BarrageReturn[] = []; - let bs = new BarrageReturn(result); - barrageList.push(bs); - return resResult(STATUS.SUCCESS, { barrageList }); - } - - public async getBarrageList(msg: {rid: string}, session: BackendSession) { - if(closeScriptBarrage()) return resResult(STATUS.SUCCESS, { barrageList: [] }); - - // const roleId: string = session.get('roleId'); - const { rid } = msg; - const result = await ScriptBarrageModel.getBarrageList(rid, 1000); - const perMax = 10, max = 50; // 每个对话最大数量,每个剧本最大数量 - let map = new Map(); // index => BarrageReturn[] - for(let barrage of result) { - let { index } = barrage; - if(!map.has(index)) { - map.set(index, []); - } - map.get(index).push(new BarrageReturn(barrage)); - } - let ratio = result.length > max? max/result.length: 1; - - let barrageList: BarrageReturn[] = []; - for(let [_, barrages] of map) { - let count = Math.ceil(barrages.length * ratio); - if(count > perMax) count = perMax; - - let curBarrages = getRandEelm(barrages, count); - barrageList = barrageList.concat(curBarrages); - } - return resResult(STATUS.SUCCESS, { barrageList }); - } -} \ No newline at end of file +import { Application, BackendSession } from "pinus"; +import { ScriptBarrageModel } from "@db/ScriptBarrage"; +import { BarrageReturn } from '@domain/roleField/barrage'; +import { resResult, getRandEelm } from "@pubUtils/util"; +import { STATUS } from "../../../consts"; +import { closeScriptBarrage } from "@pubUtils/sdkUtil"; + +export default function(app: Application) { + return new BarrageHandler(app); +} + +export class BarrageHandler { + constructor(private app: Application) { + } + + public async sendBarrage(msg: { warId: number, rid: string, index: string, content: string }, session: BackendSession) { + if(closeScriptBarrage()) return resResult(STATUS.FUNCTION_CLOSE); + + const roleId: string = session.get('roleId'); + const { warId, rid, index, content } = msg; + const result = await ScriptBarrageModel.createBarrage(roleId, warId, rid, index, content); + let barrageList: BarrageReturn[] = []; + let bs = new BarrageReturn(result); + barrageList.push(bs); + return resResult(STATUS.SUCCESS, { barrageList }); + } + + public async getBarrageList(msg: {rid: string}, session: BackendSession) { + if(closeScriptBarrage()) return resResult(STATUS.SUCCESS, { barrageList: [] }); + + // const roleId: string = session.get('roleId'); + const { rid } = msg; + const result = await ScriptBarrageModel.getBarrageList(rid, 1000); + const perMax = 10, max = 50; // 每个对话最大数量,每个剧本最大数量 + let map = new Map(); // index => BarrageReturn[] + for(let barrage of result) { + let { index } = barrage; + if(!map.has(index)) { + map.set(index, []); + } + map.get(index).push(new BarrageReturn(barrage)); + } + let ratio = result.length > max? max/result.length: 1; + + let barrageList: BarrageReturn[] = []; + for(let [_, barrages] of map) { + let count = Math.ceil(barrages.length * ratio); + if(count > perMax) count = perMax; + + let curBarrages = getRandEelm(barrages, count); + barrageList = barrageList.concat(curBarrages); + } + return resResult(STATUS.SUCCESS, { barrageList }); + } +} + diff --git a/game-server/app/servers/battle/handler/dailyBattleHandler.ts b/game-server/app/servers/battle/handler/dailyBattleHandler.ts index 8792cc2ff..69b0f75f8 100644 --- a/game-server/app/servers/battle/handler/dailyBattleHandler.ts +++ b/game-server/app/servers/battle/handler/dailyBattleHandler.ts @@ -1,70 +1,71 @@ -import { Application, BackendSession } from 'pinus'; -import { DailyRecordModel } from '../../../db/DailyRecord'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult } from '../../../pubUtils/util'; -import { RoleModel } from '../../../db/Role'; -import { getDailyNum, getDailyBattleList, getDailyBuyCountCost } from '../../../services/dailyBattleService'; -import { getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { gameData } from '../../../pubUtils/data'; -import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts'; - -export default function(app: Application) { - return new DailyBattleHandler(app); -} - -export class DailyBattleHandler { - constructor(private app: Application) { - } - - // 获取关卡列表 - async getData(msg: { }, session: BackendSession) { - let roleId = session.get('roleId'); - - let role = await RoleModel.findByRoleId(roleId); - let result = await getDailyBattleList(role); - - return resResult(STATUS.SUCCESS, { list: result }); - } - - // 购买每日次数 - async buyNum(msg: { type: number, count: number }, session: BackendSession) { - let {type, count} = msg; - if( !count || count < 0) return resResult(STATUS.WRONG_PARMS); - const roleId = session.get('roleId'); - const sid = session.get('sid'); - - const curDaily = gameData.daily.find(cur => cur.dailyType == type); - if(!curDaily) return resResult(STATUS.DAILY_TYPE_NOT_FOUND); - - let { buyCount = 0 } = await DailyRecordModel.refreshRecord(roleId, type); - - if(buyCount + count > curDaily.timesCanBuy ) { - return resResult(STATUS.DAILY_REFRESH_TIMES_LACK) - } - let buyCost = 0; - for(let i = 1; i <= count; i++) { - let num = buyCount + i; - buyCost += getDailyBuyCountCost(num); - } - let role = await RoleModel.findByRoleId(roleId); - if(buyCost > role.gold) { - return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); - } - - await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DAILY_BATTLE_BUY_CNT); - let newDailyRecord = await DailyRecordModel.increseBuyCount(roleId, type, count); - - let checkDailyResult = await getDailyNum(newDailyRecord, role); - return resResult(STATUS.SUCCESS, { type, ...checkDailyResult, buyCost}); - } - - async debugResetNum(msg: { magicWord: string, type: number }, session: BackendSession) { - const { magicWord, type } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await DailyRecordModel.deleteAccount(roleId); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession } from 'pinus'; +import { DailyRecordModel } from '@db/DailyRecord'; +import { STATUS } from '@consts/statusCode'; +import { resResult } from '@pubUtils/util'; +import { RoleModel } from '@db/Role'; +import { getDailyNum, getDailyBattleList, getDailyBuyCountCost } from '../../../services/dailyBattleService'; +import { getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { gameData } from '@pubUtils/data'; +import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts'; + +export default function(app: Application) { + return new DailyBattleHandler(app); +} + +export class DailyBattleHandler { + constructor(private app: Application) { + } + + // 获取关卡列表 + async getData(msg: { }, session: BackendSession) { + let roleId = session.get('roleId'); + + let role = await RoleModel.findByRoleId(roleId); + let result = await getDailyBattleList(role); + + return resResult(STATUS.SUCCESS, { list: result }); + } + + // 购买每日次数 + async buyNum(msg: { type: number, count: number }, session: BackendSession) { + let {type, count} = msg; + if( !count || count < 0) return resResult(STATUS.WRONG_PARMS); + const roleId = session.get('roleId'); + const sid = session.get('sid'); + + const curDaily = gameData.daily.find(cur => cur.dailyType == type); + if(!curDaily) return resResult(STATUS.DAILY_TYPE_NOT_FOUND); + + let { buyCount = 0 } = await DailyRecordModel.refreshRecord(roleId, type); + + if(buyCount + count > curDaily.timesCanBuy ) { + return resResult(STATUS.DAILY_REFRESH_TIMES_LACK) + } + let buyCost = 0; + for(let i = 1; i <= count; i++) { + let num = buyCount + i; + buyCost += getDailyBuyCountCost(num); + } + let role = await RoleModel.findByRoleId(roleId); + if(buyCost > role.gold) { + return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); + } + + await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DAILY_BATTLE_BUY_CNT); + let newDailyRecord = await DailyRecordModel.increseBuyCount(roleId, type, count); + + let checkDailyResult = await getDailyNum(newDailyRecord, role); + return resResult(STATUS.SUCCESS, { type, ...checkDailyResult, buyCost}); + } + + async debugResetNum(msg: { magicWord: string, type: number }, session: BackendSession) { + const { magicWord, type } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await DailyRecordModel.deleteAccount(roleId); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/dungeonBattleHandler.ts b/game-server/app/servers/battle/handler/dungeonBattleHandler.ts index a1ef2ef40..c632b7082 100644 --- a/game-server/app/servers/battle/handler/dungeonBattleHandler.ts +++ b/game-server/app/servers/battle/handler/dungeonBattleHandler.ts @@ -1,87 +1,88 @@ -import { Application, BackendSession } from 'pinus'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult, shouldRefresh } from '../../../pubUtils/util'; -import { RoleModel } from '../../../db/Role'; -import { getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { getDungeonData, getDungeonBuyCountCost } from '../../../services/dungeonService'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { DungeonFirstModel } from '../../../db/DungeonFirst'; -import { DungeonResultParam } from '../../../domain/battleField/dungeon'; -import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts'; -import { getVipDungeonCnt } from '../../../services/activity/monthlyTicketService'; - -export default function(app: Application) { - return new DungeonBattleHandler(app); -} - -export class DungeonBattleHandler { - constructor(private app: Application) { - } - - // 获取关卡列表 - async getData(msg: { }, session: BackendSession) { - let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId); - let res = await getDungeonData(role); - return resResult(STATUS.SUCCESS, res); - } - - // 购买每日次数 - async buyNum(msg: { count: number }, session: BackendSession) { - let { count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - - let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime } = await RoleModel.findByRoleId(roleId); - let curTime = new Date(); - let needRefresh = shouldRefresh(dungeonRefTime, curTime); - if(needRefresh) { - dungeonCnt = 0; dungeonBuyCnt = 0; - } - - let timesCanBuy = dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY; - if(dungeonBuyCnt + count > timesCanBuy ) { - return resResult(STATUS.DUNGEON_REFRESH_TIMES_LACK) - } - let buyCost = 0; - for(let i = 1; i <= count; i++) { - buyCost += getDungeonBuyCountCost(dungeonBuyCnt + i); - } - let {gold} = await RoleModel.findByRoleId(roleId); - if(buyCost > gold) { - return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); - } - await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DUNGEON_BATTLE_BUY_CNT); - await RoleModel.buyCnt(roleId, needRefresh, count, curTime); - - let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + count + 1); - let freeCount = getVipDungeonCnt(session.get('vipStartTime')); - return resResult(STATUS.SUCCESS, { - costGold: buyCost, - nextCostGold, - battleCount: freeCount + dungeonBuyCnt + count - dungeonCnt, - buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - count - }); - } - - // 购买每日次数 - async getFirstInfo(msg: { movePoint: number }, session: BackendSession) { - const { movePoint } = msg; - const serverId: number = session.get('serverId'); - const firstInfos = await DungeonFirstModel.findByMovePoint(serverId, movePoint); - let result: DungeonResultParam[] = firstInfos.map(firstInfo => { - return new DungeonResultParam(firstInfo); - }); - return resResult(STATUS.SUCCESS, { infos: result }); - } - - async debugResetRefTime(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await RoleModel.updateRoleInfo(roleId, { dungeonRefTime: new Date(Date.now() - 86400000) }); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession } from 'pinus'; +import { STATUS } from '@consts/statusCode'; +import { resResult, shouldRefresh } from '@pubUtils/util'; +import { RoleModel } from '@db/Role'; +import { getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { getDungeonData, getDungeonBuyCountCost } from '../../../services/dungeonService'; +import * as dicParam from '@pubUtils/dicParam'; +import { DungeonFirstModel } from '@db/DungeonFirst'; +import { DungeonResultParam } from '@domain/battleField/dungeon'; +import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts'; +import { getVipDungeonCnt } from '../../../services/activity/monthlyTicketService'; + +export default function(app: Application) { + return new DungeonBattleHandler(app); +} + +export class DungeonBattleHandler { + constructor(private app: Application) { + } + + // 获取关卡列表 + async getData(msg: { }, session: BackendSession) { + let roleId = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId); + let res = await getDungeonData(role); + return resResult(STATUS.SUCCESS, res); + } + + // 购买每日次数 + async buyNum(msg: { count: number }, session: BackendSession) { + let { count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + + let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime } = await RoleModel.findByRoleId(roleId); + let curTime = new Date(); + let needRefresh = shouldRefresh(dungeonRefTime, curTime); + if(needRefresh) { + dungeonCnt = 0; dungeonBuyCnt = 0; + } + + let timesCanBuy = dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY; + if(dungeonBuyCnt + count > timesCanBuy ) { + return resResult(STATUS.DUNGEON_REFRESH_TIMES_LACK) + } + let buyCost = 0; + for(let i = 1; i <= count; i++) { + buyCost += getDungeonBuyCountCost(dungeonBuyCnt + i); + } + let {gold} = await RoleModel.findByRoleId(roleId); + if(buyCost > gold) { + return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); + } + await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DUNGEON_BATTLE_BUY_CNT); + await RoleModel.buyCnt(roleId, needRefresh, count, curTime); + + let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + count + 1); + let freeCount = getVipDungeonCnt(session.get('vipStartTime')); + return resResult(STATUS.SUCCESS, { + costGold: buyCost, + nextCostGold, + battleCount: freeCount + dungeonBuyCnt + count - dungeonCnt, + buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - count + }); + } + + // 购买每日次数 + async getFirstInfo(msg: { movePoint: number }, session: BackendSession) { + const { movePoint } = msg; + const serverId: number = session.get('serverId'); + const firstInfos = await DungeonFirstModel.findByMovePoint(serverId, movePoint); + let result: DungeonResultParam[] = firstInfos.map(firstInfo => { + return new DungeonResultParam(firstInfo); + }); + return resResult(STATUS.SUCCESS, { infos: result }); + } + + async debugResetRefTime(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await RoleModel.updateRoleInfo(roleId, { dungeonRefTime: new Date(Date.now() - 86400000) }); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/eventBattleHandler.ts b/game-server/app/servers/battle/handler/eventBattleHandler.ts index 61e5eddc5..e5b151486 100644 --- a/game-server/app/servers/battle/handler/eventBattleHandler.ts +++ b/game-server/app/servers/battle/handler/eventBattleHandler.ts @@ -1,161 +1,162 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { EventRecordModel } from '../../../db/EventRecord'; -import { RoleModel } from '../../../db/Role'; -import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_ANSWER_STATUS, TASK_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, EVENT_TYPE, EVENT_QUIZ_NUM } from '../../../consts'; -import { checkEventStatus, getEventSuccessStatus, getEvent, checkQuiz, startEvent, refreshEvent, getEventTime, randomPosition, randomQuestion } from '../../../services/eventSercive'; -import { addItems } from '../../../services/role/rewardService'; -import { STATUS } from '../../../consts/statusCode'; -import { genCode, resResult } from '../../../pubUtils/util'; -import { checkTask } from '../../../services/task/taskService'; -import { gameData } from '../../../pubUtils/data'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new EventBattleHandler(app); -} - -export class EventBattleHandler { - constructor(private app: Application) { - } - - // 主动获取奇遇事件 - async getEvents(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let eventStatus = session.get('eventStatus'); - - let event = eventStatus == EVENT_STATUS.WAITING? await startEvent(session): await getEvent(eventStatus, roleId, roleName); - - return resResult(STATUS.SUCCESS, { list: event }); - } - - // 回答问题 - async checkAnswer(msg: { eventId: number, eventCode: string, questionId: number, answer: number }, session: BackendSession) { - const { eventId, eventCode, questionId, answer } = msg; - let roleId = session.get('roleId'); - // let roleName = session.get('roleName'); - // let eventStatus = session.get('eventStatus'); - - let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode); - if (!event) { - return resResult(STATUS.EVENT_RECORD_NOT_FOUND); - } - let { status, type, eventId: dataEventId, question } = event; - - if (status != EVENT_RECORD_STATUS.WAITING) { - return resResult(STATUS.EVENT_STATUS_ERROR); - } - if (dataEventId != eventId) { - return resResult(STATUS.EVENT_WRONG_ID); - } - let curQuestion = question.find(cur => cur.id == questionId); - if (!curQuestion) return resResult(STATUS.EVENT_QUESTION_NOT_FOUND); - - let { isCorrect, answerNo } = checkQuiz(questionId, answer); - let result = await EventRecordModel.saveEventAnswer(eventCode, questionId, isCorrect ? EVENT_ANSWER_STATUS.CORRECT : EVENT_ANSWER_STATUS.WRONG); - if (!result) { - return resResult(STATUS.EVENT_RECORD_NOT_FOUND); - } - let { question: newQuestion } = result; - let isClear = true, allCorrect = true; - for (let { status } of newQuestion) { - if (status) { - if (status == EVENT_ANSWER_STATUS.WRONG) { - allCorrect = false; - } - } else { - isClear = false; allCorrect = false; - } - } - if (isClear) { - await EventRecordModel.setStatusByCode(roleId, eventCode, allCorrect ? EVENT_RECORD_STATUS.BATTLE_SUCCESS : EVENT_RECORD_STATUS.BATTLE_FAIL); - } - - return resResult(STATUS.SUCCESS, { eventCode, eventId, questionId, isCorrect, answerNo }); - } - - // 获取关卡列表 - async receiveEventReward(msg: { eventId: number, eventCode: string }, session: BackendSession) { - const { eventId, eventCode } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let eventStatus = session.get('eventStatus'); - let sid = session.get('sid'); - const serverId = session.get('serverId'); - - - let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode); - if (!event) { - return resResult(STATUS.EVENT_RECORD_NOT_FOUND); - } - let { status, type, eventId: dataEventId, question } = event; - - let flag = checkEventStatus(type, status); - if (!flag) { - return resResult(STATUS.EVENT_STATUS_ERROR); - } - - let checkResult = getEventSuccessStatus(type, status, question); - if (checkResult.status == -1) { - return resResult(STATUS.EVENT_QUESTION_NO_ANSWER); - } - let isSuccess = checkResult.isSuccess; - - if (dataEventId != eventId) { - return resResult(STATUS.EVENT_WRONG_ID); - } - let dicEvent = gameData.event.get(eventId); - if (!dicEvent) { - return resResult(STATUS.EVENT_INFO_NOT_FOUND); - } - - // 保存状态 - let result = await EventRecordModel.setStatusByCode(roleId, eventCode, isSuccess ? EVENT_RECORD_STATUS.SUCCESS_RECEIVED : EVENT_RECORD_STATUS.FAIL_RECEIVED); - // 保存奖励 - let reward = isSuccess ? dicEvent.winReward : dicEvent.loseReward; - let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.EVENT_REWARD); - if (eventStatus == EVENT_STATUS.STARTING) { // 如果是第一次开启的挑战,保存成开启状态 - await RoleModel.setEventStatus(roleId, EVENT_STATUS.OPEN); - // 第一场时间挑战完,开始正常刷新事件,所以刷新时间也重置起来 - session.set('eventStatus', EVENT_STATUS.OPEN); - session.push('eventStatus', () => { }); - } - // 推送消息刷新 - // await checkEvent(session, true); - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EVENT, { eventType: dicEvent.eventType }); - return resResult(STATUS.SUCCESS, { - isSuccess, - eventCode: result.eventCode, - eventId: result.eventId, - status: result.status, - goods - }); - } - - async debugRefEvent(msg: { magicWord: string, eventId: number }, session: BackendSession) { - const { magicWord, eventId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let now = new Date(); - let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18 - await EventRecordModel.updateMany({ roleId }, { $set: {status: -1} }); - let dic = gameData.event.get(eventId); - let point = randomPosition(dic.movePointArray, [], []); - if(!point) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined; - let eventCode = genCode(8); - await EventRecordModel.saveEventRecord(eventCode, { - roleId, refTime: curTime, eventId: dic.eventID, - roleName, turn: 1, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, - status: EVENT_RECORD_STATUS.WAITING, - point, question - }); - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { EventRecordModel } from '@db/EventRecord'; +import { RoleModel } from '@db/Role'; +import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_ANSWER_STATUS, TASK_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, EVENT_TYPE, EVENT_QUIZ_NUM } from '../../../consts'; +import { checkEventStatus, getEventSuccessStatus, getEvent, checkQuiz, startEvent, refreshEvent, getEventTime, randomPosition, randomQuestion } from '../../../services/eventSercive'; +import { addItems } from '../../../services/role/rewardService'; +import { STATUS } from '@consts/statusCode'; +import { genCode, resResult } from '@pubUtils/util'; +import { checkTask } from '../../../services/task/taskService'; +import { gameData } from '@pubUtils/data'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new EventBattleHandler(app); +} + +export class EventBattleHandler { + constructor(private app: Application) { + } + + // 主动获取奇遇事件 + async getEvents(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let eventStatus = session.get('eventStatus'); + + let event = eventStatus == EVENT_STATUS.WAITING? await startEvent(session): await getEvent(eventStatus, roleId, roleName); + + return resResult(STATUS.SUCCESS, { list: event }); + } + + // 回答问题 + async checkAnswer(msg: { eventId: number, eventCode: string, questionId: number, answer: number }, session: BackendSession) { + const { eventId, eventCode, questionId, answer } = msg; + let roleId = session.get('roleId'); + // let roleName = session.get('roleName'); + // let eventStatus = session.get('eventStatus'); + + let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode); + if (!event) { + return resResult(STATUS.EVENT_RECORD_NOT_FOUND); + } + let { status, type, eventId: dataEventId, question } = event; + + if (status != EVENT_RECORD_STATUS.WAITING) { + return resResult(STATUS.EVENT_STATUS_ERROR); + } + if (dataEventId != eventId) { + return resResult(STATUS.EVENT_WRONG_ID); + } + let curQuestion = question.find(cur => cur.id == questionId); + if (!curQuestion) return resResult(STATUS.EVENT_QUESTION_NOT_FOUND); + + let { isCorrect, answerNo } = checkQuiz(questionId, answer); + let result = await EventRecordModel.saveEventAnswer(eventCode, questionId, isCorrect ? EVENT_ANSWER_STATUS.CORRECT : EVENT_ANSWER_STATUS.WRONG); + if (!result) { + return resResult(STATUS.EVENT_RECORD_NOT_FOUND); + } + let { question: newQuestion } = result; + let isClear = true, allCorrect = true; + for (let { status } of newQuestion) { + if (status) { + if (status == EVENT_ANSWER_STATUS.WRONG) { + allCorrect = false; + } + } else { + isClear = false; allCorrect = false; + } + } + if (isClear) { + await EventRecordModel.setStatusByCode(roleId, eventCode, allCorrect ? EVENT_RECORD_STATUS.BATTLE_SUCCESS : EVENT_RECORD_STATUS.BATTLE_FAIL); + } + + return resResult(STATUS.SUCCESS, { eventCode, eventId, questionId, isCorrect, answerNo }); + } + + // 获取关卡列表 + async receiveEventReward(msg: { eventId: number, eventCode: string }, session: BackendSession) { + const { eventId, eventCode } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let eventStatus = session.get('eventStatus'); + let sid = session.get('sid'); + const serverId = session.get('serverId'); + + + let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode); + if (!event) { + return resResult(STATUS.EVENT_RECORD_NOT_FOUND); + } + let { status, type, eventId: dataEventId, question } = event; + + let flag = checkEventStatus(type, status); + if (!flag) { + return resResult(STATUS.EVENT_STATUS_ERROR); + } + + let checkResult = getEventSuccessStatus(type, status, question); + if (checkResult.status == -1) { + return resResult(STATUS.EVENT_QUESTION_NO_ANSWER); + } + let isSuccess = checkResult.isSuccess; + + if (dataEventId != eventId) { + return resResult(STATUS.EVENT_WRONG_ID); + } + let dicEvent = gameData.event.get(eventId); + if (!dicEvent) { + return resResult(STATUS.EVENT_INFO_NOT_FOUND); + } + + // 保存状态 + let result = await EventRecordModel.setStatusByCode(roleId, eventCode, isSuccess ? EVENT_RECORD_STATUS.SUCCESS_RECEIVED : EVENT_RECORD_STATUS.FAIL_RECEIVED); + // 保存奖励 + let reward = isSuccess ? dicEvent.winReward : dicEvent.loseReward; + let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.EVENT_REWARD); + if (eventStatus == EVENT_STATUS.STARTING) { // 如果是第一次开启的挑战,保存成开启状态 + await RoleModel.setEventStatus(roleId, EVENT_STATUS.OPEN); + // 第一场时间挑战完,开始正常刷新事件,所以刷新时间也重置起来 + session.set('eventStatus', EVENT_STATUS.OPEN); + session.push('eventStatus', () => { }); + } + // 推送消息刷新 + // await checkEvent(session, true); + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EVENT, { eventType: dicEvent.eventType }); + return resResult(STATUS.SUCCESS, { + isSuccess, + eventCode: result.eventCode, + eventId: result.eventId, + status: result.status, + goods + }); + } + + async debugRefEvent(msg: { magicWord: string, eventId: number }, session: BackendSession) { + const { magicWord, eventId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let now = new Date(); + let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18 + await EventRecordModel.updateMany({ roleId }, { $set: {status: -1} }); + let dic = gameData.event.get(eventId); + let point = randomPosition(dic.movePointArray, [], []); + if(!point) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined; + let eventCode = genCode(8); + await EventRecordModel.saveEventRecord(eventCode, { + roleId, refTime: curTime, eventId: dic.eventID, + roleName, turn: 1, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, + status: EVENT_RECORD_STATUS.WAITING, + point, question + }); + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/expeditionBattleHandler.ts b/game-server/app/servers/battle/handler/expeditionBattleHandler.ts index da218bb55..760424f33 100644 --- a/game-server/app/servers/battle/handler/expeditionBattleHandler.ts +++ b/game-server/app/servers/battle/handler/expeditionBattleHandler.ts @@ -1,420 +1,421 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { ExpeditionRecordModel } from '../../../db/ExpeditionRecord'; -import { ExpeditionWarRecordModel } from '../../../db/ExpeditionWarRecord'; -import { ExpeditionPointModel } from '../../../db/ExpeditionPoint'; -import { RoleModel } from '../../../db/Role'; -import { genCode, getWarTypeName } from '../../../pubUtils/util'; -import { getPointRewardStatus, getResetRemainCnt, findOrCreateEnemies, getExpeditionStatus } from '../../../services/expeditionService'; -import { DEBUG_MAGIC_WORD, EXPEDITION_WAR_RECORD_STATUS, ITEM_CHANGE_REASON, KING_EXP_RATIO_TYPE, TASK_TYPE, TA_EVENT } from '../../../consts'; -import { WarReward } from '../../../services/warRewardService'; -import { addItems } from '../../../services/role/rewardService'; -import { getAp, setAp } from '../../../services/actionPointService'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult } from '../../../pubUtils/util'; -import { calculateWarStar, checkBattleHeroes, getBattleRecordParam, roleLevelup } from '../../../services/normalBattleService'; -import { checkTask, checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInSkipExpedition } from '../../../services/task/taskService'; -import { gameData } from '../../../pubUtils/data'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; -import { reportTAEvent } from '../../../services/sdkService'; -import { getSumCe } from '../../../services/playerCeService'; -import { vipCanSkipExpedition } from '../../../services/activity/monthlyTicketService'; -import { isHeroHidden } from '../../../services/dataService'; -import { pvpEndParamInter } from '../../../pubUtils/interface'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ExpeditionBattleHandler(app); -} - -export class ExpeditionBattleHandler { - constructor(private app: Application) { - } - - /** - * 获取初始数据 - * 获取当前远征挑战情况,远征点数,点数宝箱领取情况 */ - async getStatus(msg: {}, session: BackendSession) { - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - - let res = await getExpeditionStatus(roleId, roleName); - if (!res) return resResult(STATUS.ROLE_IS_NOT_INIT); - - return resResult(STATUS.SUCCESS, res); - } - - /** - * 重置远征本 - * 每天5点可以重置远征本 */ - async resetStatus(msg: {}, session: BackendSession) { - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - - let curTime = new Date(); - let { needRefresh, resetCnt } = await getResetRemainCnt(curTime, roleId); - if (resetCnt <= 0) { - return resResult(STATUS.EXPEDITION_RESET_NUM_NOT_ENOUGH) - } - - await ExpeditionRecordModel.hideRecord(roleId); // 刷掉旧关卡 - - // 我方战力 - let myCe = await getSumCe(roleId); - // 每一关的挑战状态 - let { expeditionCode, heroes } = await ExpeditionRecordModel.createRecord({ - roleId, roleName, heroes: [], myCe - }); - await findOrCreateEnemies(roleId, myCe, expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); - await RoleModel.increaseExpeditionResetCnt(roleId, needRefresh, curTime); - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode); - let curLv = 0; - if (expeditionWarRecord.length > 0) { - curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId; - } - - return resResult(STATUS.SUCCESS, { - expeditionCode, - curLv, - expeditionWarRecord, - heroes, - resetCnt: resetCnt - 1 - }); - } - - /** - * 获取敌军数据 - * 匹配其他玩家,或机器人数据 - */ - async getEnemies(msg: { expeditionCode: string, expeditionId: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - // const roleName = session.get('roleName'); - const { expeditionCode, expeditionId } = msg; - - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); - if (expeditionWarRecord && (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS)) { - return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); - } - - let { myCe } = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); - - let curExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING); - if (!curExpeditionWarRecord) { - return resResult(STATUS.EXPEDITION_MATCH_NO_PLAYER); - } - let { battleId, mapseid, enemyFrom, enemies, battleStatus, ce: curCe } = curExpeditionWarRecord; - let nextCe = 0; // 下一关战力 - - if (gameData.expedition.has(expeditionId + 1)) { - let nextExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.HIDE); - if (nextExpeditionWarRecord) nextCe = nextExpeditionWarRecord.ce; - } - - return resResult(STATUS.SUCCESS, { - expeditionCode, expeditionId, battleId, mapseid, - battleStatus, - enemyFrom, - enemies, - curCe, - nextCe - }); - } - - /** - * 进入战斗 - * 记录我军数据,生成战斗唯一表示,记录状态 - */ - async checkBattle(msg: { expeditionCode: string, expeditionId: number, battleId: number, heroes: number[] }, session: BackendSession) { - const { expeditionCode, expeditionId, battleId, heroes: seqIds = [] } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let ip = session.get('ip'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - let warInfo = gameData.war.get(battleId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - - let role = await RoleModel.findByRoleId(roleId, 'lv warStar'); - let apJson = await getAp(roleId, ip, role.lv); - let { ap } = apJson; - if (ap < warInfo.cost) { - return resResult(STATUS.BATTLE_ACTION_POINT_LACK); - } - - // 前置关卡是否挑战过 - let previousGk = warInfo.previousGk; - if (previousGk) { - let preBattle = role.warStar.findIndex(cur => cur.id == previousGk); - if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); - } - - let { isOK, hids } = await checkBattleHeroes(roleId, seqIds); - if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); - - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); - if (!expeditionWarRecord) { - return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); - } - if (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { - return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); - } - - const battleCode = genCode(8); - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId, - status: 0, - warName: warInfo.gk_name, - warType: warInfo.warType, - record: { heroes: hids, seqIds } - } - }, true); - - let result = await ExpeditionWarRecordModel.updateBattleCode(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING, battleCode); - await checkTaskInBattleStart(serverId, roleId, sid, battleId); - - return resResult(STATUS.SUCCESS, { - expeditionCode, - expeditionId, - battleId, - battleCode, - battleStatus: result.battleStatus - }); - } - - /** - * 跳过 - */ - async skipExpedition(msg: { expeditionCode: string, expeditionId: number, battleId: number }, session: BackendSession) { - const { expeditionCode, expeditionId, battleId } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - - let dicExpedition = gameData.expedition.get(expeditionId); - if(dicExpedition.warId != battleId) return resResult(STATUS.WRONG_PARMS); - - let dicWar = gameData.war.get(battleId); - if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - // 前置关卡是否挑战过 - let role = await RoleModel.findByRoleId(roleId, 'warStar topLineupCe vipStartTime') - let { warStar, topLineupCe, vipStartTime } = role; - let previousGk = dicWar.previousGk; - if (previousGk) { - let preBattle = warStar.findIndex(cur => cur.id == previousGk); - if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); - } - - // 检查record - let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); - if (!expeditionRecord || !expeditionWarRecord) { - return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); - } - if(expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { - return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); - } - - // 检查战力是否足够 - if(!vipCanSkipExpedition(expeditionWarRecord.ce, topLineupCe, vipStartTime)) { - return resResult(STATUS.EXPEDITION_SKIP_POWER_NOT_ENOUGH) - } - - // 更新敌人剩余状态及战斗状态 - expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.SUCCESS, []); - // 更新点数 - role = await RoleModel.increaseExpeditionPoint(roleId, dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS); - - // 关卡奖励 - let warReward = new WarReward(roleId, roleName, sid, battleId, true); - let reward = await warReward.saveReward(1); - - let curWarStar = warStar.find(cur => cur.id == battleId); - let { newWarStars, newStar } = calculateWarStar(warStar, battleId, []); - if (!curWarStar || newStar > curWarStar.star) { - role = await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); - } - - // 更新下一关状态 - if (gameData.expedition.has(expeditionId + 1)) { - await findOrCreateEnemies(roleId, expeditionRecord.myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); - } - await checkTaskInSkipExpedition(serverId, roleId, sid, battleId); - - return resResult(STATUS.SUCCESS, { - expeditionCode, - expeditionId, - battleId, - goods: reward, - expeditionPoint: role.expeditionPoint - }); - } - - /** - * 战斗结算 - * 结算战斗奖励,更新远征状态 - */ - async battleEnd(msg: { expeditionCode: string, expeditionId: number, battleCode: string, battleId: number, isSuccess: boolean, heroes: Array<{ dataId: number, hp: number, ap: number, shield: number, others: string }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[], damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - - const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies, damageRecords, round } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - const serverId = session.get('serverId'); - let sid = session.get('sid'); - let ip = session.get('ip'); - - let warInfo = gameData.war.get(battleId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - - const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); - if (!BattleRecord || BattleRecord.status != 0) { - return resResult(STATUS.BATTLE_STATUS_WRONG); - } - - let flag = 1; // 对比hero信息 - let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord; - for (let { dataId } of heroes) { - if (dbSeqIds.indexOf(dataId) == -1) flag = 0; - } - if (!flag) { - return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); - } - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess?-1 * warInfo.cost: 0, sid, ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END); // 扣除体力 - if (!apJson) { - return resResult(STATUS.BATTLE_ACTION_POINT_LACK); - } - - // 检查record - let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); - if (!expeditionRecord || !expeditionWarRecord) { - return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); - } - // 更新我方剩余血量 - await ExpeditionRecordModel.updateHeroStatus(expeditionCode, expeditionRecord.heroes, heroes); - // 更新敌人剩余状态及战斗状态 - let battleStatus = isSuccess ? EXPEDITION_WAR_RECORD_STATUS.SUCCESS : EXPEDITION_WAR_RECORD_STATUS.FAIL; - expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, battleStatus, enemies); - // 更新battleRecord状态 - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { status: isSuccess ? 1 : 2, star, ...getBattleRecordParam(damageRecords, round) } - }, true); - // 更新点数 - role = await RoleModel.increaseExpeditionPoint(roleId, isSuccess ? dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS : 0); - let { expeditionPoint = 0, warStar = [] } = role; - - // 关卡奖励 - let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); - let reward = await warReward.saveReward(1); - - let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 - - let curWarStar = warStar.find(cur => cur.id == battleId); - let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars); - - if (isSuccess) { - // 更新下一关状态 - await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); - if(!curWarStar) { // 首通 - reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes }); - } - if (!curWarStar || newStar > curWarStar.star) { - await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); - } - } - await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, star, isSuccess); - - return resResult(STATUS.SUCCESS, { - expeditionCode, expeditionId, - battleCode, battleId, - battleStatus: expeditionWarRecord.battleStatus, - battleGoods: reward, - expeditionPoint, - createdAt: getSeconds(createdAt), - ...actordata - }); - } - - /** - * 领取点数宝箱 - * 领取点数宝箱,不扣除点数,那么就需要记录领取状态并且有返回 - */ - async pointReward(msg: { point: number }, session: BackendSession) { - - const { point } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - const serverId = session.get('serverId'); - - let role = await RoleModel.findByRoleId(roleId); - let { expeditionPoint } = role; - let dicExpeditionPoint = gameData.expeditionPoint; - let curDicExpeditionPoint = dicExpeditionPoint.get(point); - if (!curDicExpeditionPoint) { - return resResult(STATUS.EXPEDITION_MISS_POINT_INFO); - } - - if (point > expeditionPoint) { - return resResult(STATUS.EXPEDITION_POINT_NOT_ENOUGH); - } - let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId); - if (pointStatusInDatabase) { - let { rewards } = pointStatusInDatabase; - let curReward = rewards.find(cur => cur.point == point); - if (curReward && curReward.received) { - return resResult(STATUS.EXPEDITION_WRONG_RECEIVE_STATUS); - } - } - - // 标记状态 - let { rewards: resultRewards } = await ExpeditionPointModel.updatePointStatus(roleId, point, curDicExpeditionPoint.reward); - let hasReceivedAll = true, maxPoint = 0; - for (let [point] of dicExpeditionPoint) { - let curReward = resultRewards.find(cur => cur.point == point); - if (!curReward || !curReward.received) { - hasReceivedAll = false; - } - if (point > maxPoint) maxPoint = point; - } - if (hasReceivedAll) { // 全部领取了,刷新 - await ExpeditionPointModel.completeStatus(roleId); - await RoleModel.increaseExpeditionPoint(roleId, maxPoint * -1); - } - let pointRewards = await getPointRewardStatus(roleId); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EXPEDITION_BOX, { point }); - - let goods = await addItems(roleId, roleName, sid, curDicExpeditionPoint.reward, ITEM_CHANGE_REASON.EXPEDITION_POINT_REWARD); - - return resResult(STATUS.SUCCESS, { - costPoint: hasReceivedAll ? maxPoint : 0, - pointRewards, - goods - }) - } - - async debugResetResetNum(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await RoleModel.updateRoleInfo(roleId, { expeditionResetCnt: 0 }); - return resResult(STATUS.SUCCESS); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { ExpeditionRecordModel } from '@db/ExpeditionRecord'; +import { ExpeditionWarRecordModel } from '@db/ExpeditionWarRecord'; +import { ExpeditionPointModel } from '@db/ExpeditionPoint'; +import { RoleModel } from '@db/Role'; +import { genCode, getWarTypeName } from '@pubUtils/util'; +import { getPointRewardStatus, getResetRemainCnt, findOrCreateEnemies, getExpeditionStatus } from '../../../services/expeditionService'; +import { DEBUG_MAGIC_WORD, EXPEDITION_WAR_RECORD_STATUS, ITEM_CHANGE_REASON, KING_EXP_RATIO_TYPE, TASK_TYPE, TA_EVENT } from '../../../consts'; +import { WarReward } from '../../../services/warRewardService'; +import { addItems } from '../../../services/role/rewardService'; +import { getAp, setAp } from '../../../services/actionPointService'; +import { STATUS } from '@consts/statusCode'; +import { resResult } from '@pubUtils/util'; +import { calculateWarStar, checkBattleHeroes, getBattleRecordParam, roleLevelup } from '../../../services/normalBattleService'; +import { checkTask, checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInSkipExpedition } from '../../../services/task/taskService'; +import { gameData } from '@pubUtils/data'; +import * as dicParam from '@pubUtils/dicParam'; +import { getSeconds, nowSeconds } from '@pubUtils/timeUtil'; +import { reportTAEvent } from '../../../services/sdkService'; +import { getSumCe } from '../../../services/playerCeService'; +import { vipCanSkipExpedition } from '../../../services/activity/monthlyTicketService'; +import { isHeroHidden } from '../../../services/dataService'; +import { pvpEndParamInter } from '@pubUtils/interface'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ExpeditionBattleHandler(app); +} + +export class ExpeditionBattleHandler { + constructor(private app: Application) { + } + + /** + * 获取初始数据 + * 获取当前远征挑战情况,远征点数,点数宝箱领取情况 */ + async getStatus(msg: {}, session: BackendSession) { + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + + let res = await getExpeditionStatus(roleId, roleName); + if (!res) return resResult(STATUS.ROLE_IS_NOT_INIT); + + return resResult(STATUS.SUCCESS, res); + } + + /** + * 重置远征本 + * 每天5点可以重置远征本 */ + async resetStatus(msg: {}, session: BackendSession) { + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + + let curTime = new Date(); + let { needRefresh, resetCnt } = await getResetRemainCnt(curTime, roleId); + if (resetCnt <= 0) { + return resResult(STATUS.EXPEDITION_RESET_NUM_NOT_ENOUGH) + } + + await ExpeditionRecordModel.hideRecord(roleId); // 刷掉旧关卡 + + // 我方战力 + let myCe = await getSumCe(roleId); + // 每一关的挑战状态 + let { expeditionCode, heroes } = await ExpeditionRecordModel.createRecord({ + roleId, roleName, heroes: [], myCe + }); + await findOrCreateEnemies(roleId, myCe, expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); + await RoleModel.increaseExpeditionResetCnt(roleId, needRefresh, curTime); + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode); + let curLv = 0; + if (expeditionWarRecord.length > 0) { + curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId; + } + + return resResult(STATUS.SUCCESS, { + expeditionCode, + curLv, + expeditionWarRecord, + heroes, + resetCnt: resetCnt - 1 + }); + } + + /** + * 获取敌军数据 + * 匹配其他玩家,或机器人数据 + */ + async getEnemies(msg: { expeditionCode: string, expeditionId: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + // const roleName = session.get('roleName'); + const { expeditionCode, expeditionId } = msg; + + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); + if (expeditionWarRecord && (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS)) { + return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); + } + + let { myCe } = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); + + let curExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING); + if (!curExpeditionWarRecord) { + return resResult(STATUS.EXPEDITION_MATCH_NO_PLAYER); + } + let { battleId, mapseid, enemyFrom, enemies, battleStatus, ce: curCe } = curExpeditionWarRecord; + let nextCe = 0; // 下一关战力 + + if (gameData.expedition.has(expeditionId + 1)) { + let nextExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.HIDE); + if (nextExpeditionWarRecord) nextCe = nextExpeditionWarRecord.ce; + } + + return resResult(STATUS.SUCCESS, { + expeditionCode, expeditionId, battleId, mapseid, + battleStatus, + enemyFrom, + enemies, + curCe, + nextCe + }); + } + + /** + * 进入战斗 + * 记录我军数据,生成战斗唯一表示,记录状态 + */ + async checkBattle(msg: { expeditionCode: string, expeditionId: number, battleId: number, heroes: number[] }, session: BackendSession) { + const { expeditionCode, expeditionId, battleId, heroes: seqIds = [] } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let ip = session.get('ip'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + let warInfo = gameData.war.get(battleId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + + let role = await RoleModel.findByRoleId(roleId, 'lv warStar'); + let apJson = await getAp(roleId, ip, role.lv); + let { ap } = apJson; + if (ap < warInfo.cost) { + return resResult(STATUS.BATTLE_ACTION_POINT_LACK); + } + + // 前置关卡是否挑战过 + let previousGk = warInfo.previousGk; + if (previousGk) { + let preBattle = role.warStar.findIndex(cur => cur.id == previousGk); + if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); + } + + let { isOK, hids } = await checkBattleHeroes(roleId, seqIds); + if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); + + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); + if (!expeditionWarRecord) { + return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); + } + if (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { + return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); + } + + const battleCode = genCode(8); + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId, + status: 0, + warName: warInfo.gk_name, + warType: warInfo.warType, + record: { heroes: hids, seqIds } + } + }, true); + + let result = await ExpeditionWarRecordModel.updateBattleCode(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING, battleCode); + await checkTaskInBattleStart(serverId, roleId, sid, battleId); + + return resResult(STATUS.SUCCESS, { + expeditionCode, + expeditionId, + battleId, + battleCode, + battleStatus: result.battleStatus + }); + } + + /** + * 跳过 + */ + async skipExpedition(msg: { expeditionCode: string, expeditionId: number, battleId: number }, session: BackendSession) { + const { expeditionCode, expeditionId, battleId } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + + let dicExpedition = gameData.expedition.get(expeditionId); + if(dicExpedition.warId != battleId) return resResult(STATUS.WRONG_PARMS); + + let dicWar = gameData.war.get(battleId); + if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // 前置关卡是否挑战过 + let role = await RoleModel.findByRoleId(roleId, 'warStar topLineupCe vipStartTime') + let { warStar, topLineupCe, vipStartTime } = role; + let previousGk = dicWar.previousGk; + if (previousGk) { + let preBattle = warStar.findIndex(cur => cur.id == previousGk); + if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); + } + + // 检查record + let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); + if (!expeditionRecord || !expeditionWarRecord) { + return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); + } + if(expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) { + return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE); + } + + // 检查战力是否足够 + if(!vipCanSkipExpedition(expeditionWarRecord.ce, topLineupCe, vipStartTime)) { + return resResult(STATUS.EXPEDITION_SKIP_POWER_NOT_ENOUGH) + } + + // 更新敌人剩余状态及战斗状态 + expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.SUCCESS, []); + // 更新点数 + role = await RoleModel.increaseExpeditionPoint(roleId, dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS); + + // 关卡奖励 + let warReward = new WarReward(roleId, roleName, sid, battleId, true); + let reward = await warReward.saveReward(1); + + let curWarStar = warStar.find(cur => cur.id == battleId); + let { newWarStars, newStar } = calculateWarStar(warStar, battleId, []); + if (!curWarStar || newStar > curWarStar.star) { + role = await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); + } + + // 更新下一关状态 + if (gameData.expedition.has(expeditionId + 1)) { + await findOrCreateEnemies(roleId, expeditionRecord.myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); + } + await checkTaskInSkipExpedition(serverId, roleId, sid, battleId); + + return resResult(STATUS.SUCCESS, { + expeditionCode, + expeditionId, + battleId, + goods: reward, + expeditionPoint: role.expeditionPoint + }); + } + + /** + * 战斗结算 + * 结算战斗奖励,更新远征状态 + */ + async battleEnd(msg: { expeditionCode: string, expeditionId: number, battleCode: string, battleId: number, isSuccess: boolean, heroes: Array<{ dataId: number, hp: number, ap: number, shield: number, others: string }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[], damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + + const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies, damageRecords, round } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + const serverId = session.get('serverId'); + let sid = session.get('sid'); + let ip = session.get('ip'); + + let warInfo = gameData.war.get(battleId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + + const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); + if (!BattleRecord || BattleRecord.status != 0) { + return resResult(STATUS.BATTLE_STATUS_WRONG); + } + + let flag = 1; // 对比hero信息 + let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord; + for (let { dataId } of heroes) { + if (dbSeqIds.indexOf(dataId) == -1) flag = 0; + } + if (!flag) { + return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); + } + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess?-1 * warInfo.cost: 0, sid, ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END); // 扣除体力 + if (!apJson) { + return resResult(STATUS.BATTLE_ACTION_POINT_LACK); + } + + // 检查record + let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode); + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId); + if (!expeditionRecord || !expeditionWarRecord) { + return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD); + } + // 更新我方剩余血量 + await ExpeditionRecordModel.updateHeroStatus(expeditionCode, expeditionRecord.heroes, heroes); + // 更新敌人剩余状态及战斗状态 + let battleStatus = isSuccess ? EXPEDITION_WAR_RECORD_STATUS.SUCCESS : EXPEDITION_WAR_RECORD_STATUS.FAIL; + expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, battleStatus, enemies); + // 更新battleRecord状态 + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { status: isSuccess ? 1 : 2, star, ...getBattleRecordParam(damageRecords, round) } + }, true); + // 更新点数 + role = await RoleModel.increaseExpeditionPoint(roleId, isSuccess ? dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS : 0); + let { expeditionPoint = 0, warStar = [] } = role; + + // 关卡奖励 + let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); + let reward = await warReward.saveReward(1); + + let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 + + let curWarStar = warStar.find(cur => cur.id == battleId); + let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars); + + if (isSuccess) { + // 更新下一关状态 + await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); + if(!curWarStar) { // 首通 + reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes }); + } + if (!curWarStar || newStar > curWarStar.star) { + await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); + } + } + await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, star, isSuccess); + + return resResult(STATUS.SUCCESS, { + expeditionCode, expeditionId, + battleCode, battleId, + battleStatus: expeditionWarRecord.battleStatus, + battleGoods: reward, + expeditionPoint, + createdAt: getSeconds(createdAt), + ...actordata + }); + } + + /** + * 领取点数宝箱 + * 领取点数宝箱,不扣除点数,那么就需要记录领取状态并且有返回 + */ + async pointReward(msg: { point: number }, session: BackendSession) { + + const { point } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + const serverId = session.get('serverId'); + + let role = await RoleModel.findByRoleId(roleId); + let { expeditionPoint } = role; + let dicExpeditionPoint = gameData.expeditionPoint; + let curDicExpeditionPoint = dicExpeditionPoint.get(point); + if (!curDicExpeditionPoint) { + return resResult(STATUS.EXPEDITION_MISS_POINT_INFO); + } + + if (point > expeditionPoint) { + return resResult(STATUS.EXPEDITION_POINT_NOT_ENOUGH); + } + let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId); + if (pointStatusInDatabase) { + let { rewards } = pointStatusInDatabase; + let curReward = rewards.find(cur => cur.point == point); + if (curReward && curReward.received) { + return resResult(STATUS.EXPEDITION_WRONG_RECEIVE_STATUS); + } + } + + // 标记状态 + let { rewards: resultRewards } = await ExpeditionPointModel.updatePointStatus(roleId, point, curDicExpeditionPoint.reward); + let hasReceivedAll = true, maxPoint = 0; + for (let [point] of dicExpeditionPoint) { + let curReward = resultRewards.find(cur => cur.point == point); + if (!curReward || !curReward.received) { + hasReceivedAll = false; + } + if (point > maxPoint) maxPoint = point; + } + if (hasReceivedAll) { // 全部领取了,刷新 + await ExpeditionPointModel.completeStatus(roleId); + await RoleModel.increaseExpeditionPoint(roleId, maxPoint * -1); + } + let pointRewards = await getPointRewardStatus(roleId); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EXPEDITION_BOX, { point }); + + let goods = await addItems(roleId, roleName, sid, curDicExpeditionPoint.reward, ITEM_CHANGE_REASON.EXPEDITION_POINT_REWARD); + + return resResult(STATUS.SUCCESS, { + costPoint: hasReceivedAll ? maxPoint : 0, + pointRewards, + goods + }) + } + + async debugResetResetNum(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await RoleModel.updateRoleInfo(roleId, { expeditionResetCnt: 0 }); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/friendBattleHandler.ts b/game-server/app/servers/battle/handler/friendBattleHandler.ts index 3ba4dd22e..a98323e03 100644 --- a/game-server/app/servers/battle/handler/friendBattleHandler.ts +++ b/game-server/app/servers/battle/handler/friendBattleHandler.ts @@ -1,61 +1,62 @@ -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { LadderMatchModel } from '../../../db/LadderMatch'; -import { HeroModel, HeroType } from '../../../db/Hero'; -import { ArtifactModel } from '../../../db/Artifact'; -import { getHeroesAttributes } from '../../../services/playerCeService'; -import { gameData } from '../../../pubUtils/data'; -import { LadderOppDetailHeroReturn } from '../../../domain/battleField/ladder'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { RoleType } from '../../../db/Role'; -import { FRIEND_BATTLE_DISPATCH_JSONID } from '../../../consts'; -import { getLadderDefCe } from '../../../services/redisService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new FriendBattleHandler(app); -} - -export class FriendBattleHandler { - constructor(private app: Application) { - } - - async getFriendOpp(msg: { roleId: string }, session: BackendSession) { - const { roleId: targetRoleId, } = msg; - - let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(targetRoleId); - if (!hisLadderData || !hisLadderData.defense || !hisLadderData.defense.heroes) return resResult(STATUS.LADDER_NOT_OPEN); - - let artifactSeids = [], subHids: number[] = []; - for (let { hero, subHid } of hisLadderData.defense.heroes) { - let dbHero = hero; - if (dbHero) artifactSeids.push(dbHero.artifact); - if (subHid) subHids.push(subHid); - } - - let artifacts = await ArtifactModel.findbySeqIds(targetRoleId, artifactSeids); - let subHeroes = await HeroModel.findByHidRange(subHids, targetRoleId, 'hid skinId'); - let attrByHid = await getHeroesAttributes(targetRoleId); - let dicWarJson = gameData.warJson.get(FRIEND_BATTLE_DISPATCH_JSONID); - let result: LadderOppDetailHeroReturn[] = []; - for (let obj of hisLadderData.defense.heroes) { - const { dataId, subHid, actorId } = obj; - let warJson = dicWarJson.find(cur => cur.dataId == dataId); - if (warJson) { - let subHero = subHeroes.find(sub => sub.hid == subHid); - let rec = new LadderOppDetailHeroReturn(warJson, obj, artifacts, subHero); - let attr = attrByHid.get(actorId); - if (attr) { - rec.setAttribute(attr.getAttributesToString()); - } - result.push(rec); - } - } - const role = hisLadderData.role; - const title = role?.title || 1; - const combo = hisLadderData.defense.combo || []; - const defCe = await getLadderDefCe(targetRoleId); - - return resResult(STATUS.SUCCESS, { title, combo, defCe, heroes: result }) - } -} \ No newline at end of file +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { LadderMatchModel } from '@db/LadderMatch'; +import { HeroModel, HeroType } from '@db/Hero'; +import { ArtifactModel } from '@db/Artifact'; +import { getHeroesAttributes } from '../../../services/playerCeService'; +import { gameData } from '@pubUtils/data'; +import { LadderOppDetailHeroReturn } from '@domain/battleField/ladder'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { RoleType } from '@db/Role'; +import { FRIEND_BATTLE_DISPATCH_JSONID } from '../../../consts'; +import { getLadderDefCe } from '../../../services/redisService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new FriendBattleHandler(app); +} + +export class FriendBattleHandler { + constructor(private app: Application) { + } + + async getFriendOpp(msg: { roleId: string }, session: BackendSession) { + const { roleId: targetRoleId, } = msg; + + let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(targetRoleId); + if (!hisLadderData || !hisLadderData.defense || !hisLadderData.defense.heroes) return resResult(STATUS.LADDER_NOT_OPEN); + + let artifactSeids = [], subHids: number[] = []; + for (let { hero, subHid } of hisLadderData.defense.heroes) { + let dbHero = hero; + if (dbHero) artifactSeids.push(dbHero.artifact); + if (subHid) subHids.push(subHid); + } + + let artifacts = await ArtifactModel.findbySeqIds(targetRoleId, artifactSeids); + let subHeroes = await HeroModel.findByHidRange(subHids, targetRoleId, 'hid skinId'); + let attrByHid = await getHeroesAttributes(targetRoleId); + let dicWarJson = gameData.warJson.get(FRIEND_BATTLE_DISPATCH_JSONID); + let result: LadderOppDetailHeroReturn[] = []; + for (let obj of hisLadderData.defense.heroes) { + const { dataId, subHid, actorId } = obj; + let warJson = dicWarJson.find(cur => cur.dataId == dataId); + if (warJson) { + let subHero = subHeroes.find(sub => sub.hid == subHid); + let rec = new LadderOppDetailHeroReturn(warJson, obj, artifacts, subHero); + let attr = attrByHid.get(actorId); + if (attr) { + rec.setAttribute(attr.getAttributesToString()); + } + result.push(rec); + } + } + const role = hisLadderData.role; + const title = role?.title || 1; + const combo = hisLadderData.defense.combo || []; + const defCe = await getLadderDefCe(targetRoleId); + + return resResult(STATUS.SUCCESS, { title, combo, defCe, heroes: result }) + } +} + diff --git a/game-server/app/servers/battle/handler/ladderHandler.ts b/game-server/app/servers/battle/handler/ladderHandler.ts index 7f1c0f31e..135b2e5da 100644 --- a/game-server/app/servers/battle/handler/ladderHandler.ts +++ b/game-server/app/servers/battle/handler/ladderHandler.ts @@ -1,455 +1,456 @@ - -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { isArray, pick } from 'underscore'; -import { gameData } from '../../../pubUtils/data'; -import { STATUS } from '../../../consts/statusCode'; -import { arrToMap, resResult } from '../../../pubUtils/util'; -import { getTimeFunM } from '../../../pubUtils/timeUtil'; -import { LadderMatchModel, LadderUpdateInter } from '../../../db/LadderMatch'; -import { battleEndWhenChange, checkRank, generateInitRecInfo, generateOppPlayers, getBuyCntCost, getLadderData, getLadderEnemies, getLadderOppDetailData, getLadderOppStatus, getNumberArr, ladderBattleEndReward, pushLadderIconShow, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward, uniqueArr } from '../../../services/ladderService'; -import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '../../../domain/battleField/ladder'; -import { LadderMatchRecModel } from '../../../db/LadderMatchRec'; -import { HeroModel } from '../../../db/Hero'; -import { LADDER } from '../../../pubUtils/dicParam'; -import { handleCost } from '../../../services/role/rewardService'; -import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY, WAR_TYPE } from '../../../consts'; -import { checkBattleHeroesByHid, getBattleRecordParam } from '../../../services/normalBattleService'; -import { ServerlistModel } from '../../../db/Serverlist'; -import { saveLadderDefCeByData } from '../../../services/redisService'; -import { pushLadderTopChangeMsg } from '../../../services/sysChatService'; -import { checkTaskInLadderEnd, checkTaskInLadderStart, checkTaskInLadderSweep } from '../../../services/task/taskService'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { isHeroHidden } from '../../../services/dataService'; -import { getRemoteRplFilePath, getRemoteRplPrefix } from '../../../pubUtils/battleUtils'; -import { pvpEndParamInter } from '../../../pubUtils/interface'; -import { Combo } from '../../../domain/battleField/pvp'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new LadderHandler(app); -} - -export class LadderHandler { - constructor(private app: Application) { - } - - // 1. 获取主界面 - async getData(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - - let result = await getLadderData(roleId, true) - return resResult(STATUS.SUCCESS, result); - } - - // 2. 获取对手阵容信息 - async getOppLineup(msg: { roleId: string, rank: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let { roleId: targetRoleId, rank } = msg; - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - - let isRobot = targetRoleId.startsWith('robot'); - let result = new LadderOppLineupReturn(); - result.setMyRank(ladderData.rank); - if(isRobot) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); - let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); - let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); - result.setRobot(dicLadderDifficultRatio, dicWarJson); - } else { - let hisLadderData = await LadderMatchModel.findOne({ roleId: targetRoleId }) - .populate('role', 'roleId roleName head frame spine heads frames spines title lv guildName updatedAt') - .populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid subActorId') - .lean(); - result.setPlayer(hisLadderData); - } - return resResult(STATUS.SUCCESS, result); - } - - // 3. 点击挑战 - async chooseOpp(msg: { roleId: string, rank: number, myRank: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - let { roleId: targetRoleId, rank, myRank } = msg; - // 检查双方排名等,不行的刷新对手回去 - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - - if(!checkRank(myRank, rank)) return resResult(STATUS.LADDER_RANK_ERROR); - let { status, isRobot, hisLadderData } = await getLadderOppStatus(ladderData, targetRoleId, myRank, rank); - if(status != LADDER_OPP_STATUS.BATTLE) { - // await LadderMatchModel.unlock(serverId, targetRoleId); - let oppPlayers = await refreshLadderEnemies(ladderData); - return resResult(STATUS.SUCCESS, { - status, oppPlayers - }); - } - - // 刷新次数 - let refOppObj = refreshLadderDaily(ladderData); - let update: LadderUpdateInter = {}; - if(refOppObj.shouldRefOpp) { - update = { ...refOppObj }; - } - - if(refOppObj.challengeCnt + 1 > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) { - await LadderMatchModel.unlock(serverId, targetRoleId); - return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX); - } - update.challengeCnt = refOppObj.challengeCnt + 1; - ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update); - - - // 创建ladderMatchRec,发行battleCode - let attackInfo = await generateInitRecInfo(false, false, ladderData.rank, ladderData); - let defenseInfo = await generateInitRecInfo(isRobot, true, rank, hisLadderData); - let rec = await LadderMatchRecModel.createRec(serverId, roleId, targetRoleId, hisLadderData?.defense, attackInfo, defenseInfo); - - // 倒计时,倒计时结束没有check设为失败并发失败通知 - pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.checkTime, LADDER_STATUS.CHECK); - - let result = await getLadderOppDetailData(rec); - await checkTaskInLadderStart(serverId, roleId, sid); - return resResult(STATUS.SUCCESS, { - status, - challengeCnt: ladderData.challengeCnt, - ...result - }); - } - - // 4. 出战撤退 - async giveupCheck(msg: { battleCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let { battleCode } = msg; - // 更新ladderMatchRec - let rec = await LadderMatchRecModel.giveup(roleId, battleCode); - if(rec) { - pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(rec.battleCode); - if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId); - } - - return resResult(STATUS.SUCCESS, { status: 0, time: 0 }); - } - - // 5. 获取对手具体战场数据 - async getOppData(msg: { battleCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let { battleCode } = msg; - - let rec = await LadderMatchRecModel.findByBattleCode(battleCode); - if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); - if(rec.status == LADDER_STATUS.COMPLETE || rec.status == LADDER_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE); - - let result = await getLadderOppDetailData(rec); - return resResult(STATUS.SUCCESS, result); - } - - // 6. 布完阵开始挑战 - async checkBattle(msg: { battleCode: string, battleId: number, heroes: { actorId: number, order: number }[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleId'); - let { battleId, battleCode, heroes } = msg; - - let rec = await LadderMatchRecModel.findByBattleCode(battleCode); - if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); - if(rec.status != LADDER_STATUS.CHECK) return resResult(STATUS.LADDER_REC_STATUS_ERR); - - for(let { actorId } of heroes) { - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - } - let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); - if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - - let attackHeroes = dbHeroes.map(hero => { - let heroInfo = new LadderOppPlayerHeroInfo(); - heroInfo.setByDefenseHero(hero); - return heroInfo; - }); - let warInfo = gameData.war.get(battleId); - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId, - status: 0, - warName: warInfo?.gk_name, - warType: warInfo?.warType, - } - }); - rec = await LadderMatchRecModel.startBattle(battleCode, attackHeroes); - pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.battleTime, LADDER_STATUS.BATTLE); - - return resResult(STATUS.SUCCESS, { - time: Math.floor(rec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN, - battleCode: rec.battleCode - }) - } - - // 7. 挑战结算 - async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - let { battleCode, isSuccess, damageRecords, round } = msg; - - let rec = await LadderMatchRecModel.findByBattleCode(battleCode); - if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); - if(rec.status != LADDER_STATUS.BATTLE) return resResult(STATUS.LADDER_REC_STATUS_ERR); - let rank = rec.defenseInfo.oldRank; - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - - // 取消 checkBattle 的倒计时 - pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(battleCode); - - let result = new LadderDataReturn(); - // 交换双方排名, transaction - let { isChange, atkLadderMatch, defLadderMatch, endTime } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo); - - if(isChange) { - let oppPlayers = await battleEndWhenChange(atkLadderMatch, defLadderMatch, true); - result.setOppPlayers(oppPlayers); - rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank); - if(atkLadderMatch.rank == 1) { - pushLadderTopChangeMsg(roleId, roleName, serverId); - } - } else { - rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime); - let oppPlayers = await getLadderEnemies(atkLadderMatch); - result.setOppPlayers(oppPlayers); - } - await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } }); - if(defLadderMatch) { - await LadderMatchModel.unlock(defLadderMatch.serverId, defLadderMatch.roleId); - } - - let historyRank = ladderData.historyRank; - ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: (historyRank > atkLadderMatch.rank || historyRank == 0)? atkLadderMatch.rank: historyRank }); - - result.setLadderData(ladderData, rec); - // 获取奖励 - let rewardResult = await ladderBattleEndReward(roleId, roleName, sid, ladderData.historyRank, isSuccess, historyRank, 1); - let { battleGoods = [], breakGoods = [] } = rewardResult||{}; - - await checkTaskInLadderEnd(serverId, roleId, sid, isSuccess, historyRank, atkLadderMatch.rank); - - if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushLadderIconShow(rec.roleId2, true); - return resResult(STATUS.SUCCESS, {...pick(result, ['rank', 'historyRank', 'challengeCnt','status', 'time', 'oppPlayers']), battleGoods, breakGoods}); - } - - // 8. 战5次(扫荡) - async battleSweep(msg: { roleId: string, rank: number, count: number }, session: BackendSession) { - let serverId = session.get('serverId'); - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let { roleId: targetRoleId, rank, count } = msg; - if(count > LADDER.LADDER_INITIAL_CHALLENGE_TIMES) { - return resResult(STATUS.LADDER_SWEEP_TIMES_OVER); - } - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - - if(ladderData.rank >= rank) return resResult(STATUS.LADDER_RANK_ERR); - - // 刷新次数 - let refOppObj = refreshLadderDaily(ladderData); - let update: LadderUpdateInter = {}; - if(refOppObj.shouldRefOpp) { - update = { ...refOppObj }; - } - - if(refOppObj.challengeCnt + count > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) { - return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX); - } - update.challengeCnt = refOppObj.challengeCnt + count; - ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update); - - // 获取奖励 - let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, rank, count); - await checkTaskInLadderSweep(serverId, roleId, sid, count) - return resResult(STATUS.SUCCESS, { - challengeCnt: ladderData.challengeCnt, - battleGoods - }); - } - - // 9. 设置防守阵容 - async saveDefense(msg: { warId: number, heroes: { actorId: number, ai: number, dataId: number, order: number, subHid?: number }[], combo: Combo[] }, session: BackendSession) { - let { warId, heroes, combo } = msg; - let roleId = session.get('roleId'); - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); - - let hids: number[] = heroes.map(cur => cur.actorId); - if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); - for(let { actorId, subHid } of heroes) { - let dicHero = gameData.hero.get(actorId); - if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); - if(subHid && hids.indexOf(subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); - } - - let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true); - - let defenseHeroes = heroes.map(cur => { - let dbHero = dbHeroes.find(ccur => ccur.hid == cur.actorId); - return dbHero && new LadderDefenseHero(cur, dbHero._id, dbHero.ce); - }).filter(cur => cur); - let defense = new LadderDefense(defenseHeroes, warId, combo); - ladderData = await LadderMatchModel.updateByRoleId(roleId, { defense, hasDefense: true }); - // 返回 - let result = new LadderDataReturn(); - result.setLadderData(ladderData); - await saveLadderDefCeByData(roleId, ladderData); - - return resResult(STATUS.SUCCESS, pick(result, 'defense')); - } - - // 10. 刷新对手 - async refreshOppPlayers(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); - - let update: LadderUpdateInter = {}; - // 刷新次数 - let refOppObj = refreshLadderDaily(ladderData); - if(refOppObj.shouldRefOpp) { - update = { ...refOppObj }; - } - - if(refOppObj.refOppCnt + 1 > LADDER.LADDER_REFRESH_TIMES) { - return resResult(STATUS.LADDER_REFRESH_CNT_MAX); - } - update.refOppCnt = refOppObj.refOppCnt + 1; - let oppPlayers = await refreshLadderEnemies(ladderData, update); - - // 返回 - return resResult(STATUS.SUCCESS, { refOppCnt: update.refOppCnt, oppPlayers }); - } - - // 11. 购买次数 - async buyCnt(msg: { count: number }, session: BackendSession) { - let { count } = msg; - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); - - let update: LadderUpdateInter = {}; - // 刷新次数 - let refOppObj = refreshLadderDaily(ladderData); - if(refOppObj.shouldRefOpp) { - update = { ...refOppObj }; - } - - if(refOppObj.buyCnt + count > LADDER.LADDER_CHALLENGE_COST_TIMES) { - return resResult(STATUS.LADDER_BUY_MAX); - } - let consumes = getBuyCntCost(refOppObj.buyCnt, count); - if(!consumes) return resResult(STATUS.LADDER_BUY_MAX); - - let consumeResult = await handleCost(roleId, sid, consumes||[], ITEM_CHANGE_REASON.LADDER_BUY_CNT); - if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - update.buyCnt = refOppObj.buyCnt + count; - ladderData = await LadderMatchModel.updateByRoleId(roleId, update); - // 返回 - let result = new LadderDataReturn(); - result.setLadderData(ladderData); - return resResult(STATUS.SUCCESS, pick(result, ['buyCnt', 'challengeCnt'])); - } - - // 12. 获取战报信息(2天内) - async getRec(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let list = await LadderMatchRecModel.findRecentRec(roleId, getTimeFunM().getBeforeDay(2)); - return resResult(STATUS.SUCCESS, { - list: list.map(rec => { - const { roleId1, battleCode, hasRpl, remoteUrl } = rec; - const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; - return { ...rec, rplFileUrl }; - }), - rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) - }); - } - - // debug接口 - // 重置挑战次数 & 购买次数 - async resetCnt(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let roleId = session.get('roleId'); - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); - await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) }); - return resResult(STATUS.SUCCESS); - } - - async setMyRank(msg: { magicWord: string, rank: number }, session: BackendSession) { - const { magicWord, rank } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let atkLadderMatch = await LadderMatchModel.findByRoleId(roleId); - if(!atkLadderMatch || !atkLadderMatch.defense) return resResult(STATUS.LADDER_NOT_OPEN); - let myRank = atkLadderMatch.rank; - - let defLadderMatch = await LadderMatchModel.findByRank(serverId, rank); - if(defLadderMatch) { - atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: myRank, historyRank: rank } }, { new: true }).lean(); - defLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defLadderMatch.roleId }, { $set: { rank: myRank, oldRank: rank } }, { new: true }).lean(); - } else { - atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: atkLadderMatch.rank, historyRank: rank } }, { new: true }).lean(); - } - - await battleEndWhenChange(atkLadderMatch, defLadderMatch, true); - return resResult(STATUS.SUCCESS); - } - - async setMyOpp(msg: { magicWord: string, oppRanks: number[] }, session: BackendSession) { - const { magicWord, oppRanks } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.WRONG_PARMS); - } - if(!isArray(oppRanks) || oppRanks.length <= 0) return resResult(STATUS.WRONG_PARMS); - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); - - let topTen = getNumberArr(1, 10); - let ranks = [...topTen, ...oppRanks]; - let newRanks = uniqueArr(ranks.sort((a, b) => a - b)); - - await generateOppPlayers(newRanks, serverId, roleId); - return resResult(STATUS.SUCCESS); - } - - async sendDailyReward(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - for(let { id } of servers) { - await sendLadderDailyReward(id); - } - return resResult(STATUS.SUCCESS) - } -} \ No newline at end of file + +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { isArray, pick } from 'underscore'; +import { gameData } from '@pubUtils/data'; +import { STATUS } from '@consts/statusCode'; +import { arrToMap, resResult } from '@pubUtils/util'; +import { getTimeFunM } from '@pubUtils/timeUtil'; +import { LadderMatchModel, LadderUpdateInter } from '@db/LadderMatch'; +import { battleEndWhenChange, checkRank, generateInitRecInfo, generateOppPlayers, getBuyCntCost, getLadderData, getLadderEnemies, getLadderOppDetailData, getLadderOppStatus, getNumberArr, ladderBattleEndReward, pushLadderIconShow, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward, uniqueArr } from '../../../services/ladderService'; +import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '@domain/battleField/ladder'; +import { LadderMatchRecModel } from '@db/LadderMatchRec'; +import { HeroModel } from '@db/Hero'; +import { LADDER } from '@pubUtils/dicParam'; +import { handleCost } from '../../../services/role/rewardService'; +import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY, WAR_TYPE } from '../../../consts'; +import { checkBattleHeroesByHid, getBattleRecordParam } from '../../../services/normalBattleService'; +import { ServerlistModel } from '@db/Serverlist'; +import { saveLadderDefCeByData } from '../../../services/redisService'; +import { pushLadderTopChangeMsg } from '../../../services/sysChatService'; +import { checkTaskInLadderEnd, checkTaskInLadderStart, checkTaskInLadderSweep } from '../../../services/task/taskService'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { isHeroHidden } from '../../../services/dataService'; +import { getRemoteRplFilePath, getRemoteRplPrefix } from '@pubUtils/battleUtils'; +import { pvpEndParamInter } from '@pubUtils/interface'; +import { Combo } from '@domain/battleField/pvp'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new LadderHandler(app); +} + +export class LadderHandler { + constructor(private app: Application) { + } + + // 1. 获取主界面 + async getData(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + + let result = await getLadderData(roleId, true) + return resResult(STATUS.SUCCESS, result); + } + + // 2. 获取对手阵容信息 + async getOppLineup(msg: { roleId: string, rank: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let { roleId: targetRoleId, rank } = msg; + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); + + let isRobot = targetRoleId.startsWith('robot'); + let result = new LadderOppLineupReturn(); + result.setMyRank(ladderData.rank); + if(isRobot) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); + let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); + let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); + result.setRobot(dicLadderDifficultRatio, dicWarJson); + } else { + let hisLadderData = await LadderMatchModel.findOne({ roleId: targetRoleId }) + .populate('role', 'roleId roleName head frame spine heads frames spines title lv guildName updatedAt') + .populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid subActorId') + .lean(); + result.setPlayer(hisLadderData); + } + return resResult(STATUS.SUCCESS, result); + } + + // 3. 点击挑战 + async chooseOpp(msg: { roleId: string, rank: number, myRank: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + let { roleId: targetRoleId, rank, myRank } = msg; + // 检查双方排名等,不行的刷新对手回去 + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); + + if(!checkRank(myRank, rank)) return resResult(STATUS.LADDER_RANK_ERROR); + let { status, isRobot, hisLadderData } = await getLadderOppStatus(ladderData, targetRoleId, myRank, rank); + if(status != LADDER_OPP_STATUS.BATTLE) { + // await LadderMatchModel.unlock(serverId, targetRoleId); + let oppPlayers = await refreshLadderEnemies(ladderData); + return resResult(STATUS.SUCCESS, { + status, oppPlayers + }); + } + + // 刷新次数 + let refOppObj = refreshLadderDaily(ladderData); + let update: LadderUpdateInter = {}; + if(refOppObj.shouldRefOpp) { + update = { ...refOppObj }; + } + + if(refOppObj.challengeCnt + 1 > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) { + await LadderMatchModel.unlock(serverId, targetRoleId); + return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX); + } + update.challengeCnt = refOppObj.challengeCnt + 1; + ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update); + + + // 创建ladderMatchRec,发行battleCode + let attackInfo = await generateInitRecInfo(false, false, ladderData.rank, ladderData); + let defenseInfo = await generateInitRecInfo(isRobot, true, rank, hisLadderData); + let rec = await LadderMatchRecModel.createRec(serverId, roleId, targetRoleId, hisLadderData?.defense, attackInfo, defenseInfo); + + // 倒计时,倒计时结束没有check设为失败并发失败通知 + pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.checkTime, LADDER_STATUS.CHECK); + + let result = await getLadderOppDetailData(rec); + await checkTaskInLadderStart(serverId, roleId, sid); + return resResult(STATUS.SUCCESS, { + status, + challengeCnt: ladderData.challengeCnt, + ...result + }); + } + + // 4. 出战撤退 + async giveupCheck(msg: { battleCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let { battleCode } = msg; + // 更新ladderMatchRec + let rec = await LadderMatchRecModel.giveup(roleId, battleCode); + if(rec) { + pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(rec.battleCode); + if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId); + } + + return resResult(STATUS.SUCCESS, { status: 0, time: 0 }); + } + + // 5. 获取对手具体战场数据 + async getOppData(msg: { battleCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let { battleCode } = msg; + + let rec = await LadderMatchRecModel.findByBattleCode(battleCode); + if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); + if(rec.status == LADDER_STATUS.COMPLETE || rec.status == LADDER_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE); + + let result = await getLadderOppDetailData(rec); + return resResult(STATUS.SUCCESS, result); + } + + // 6. 布完阵开始挑战 + async checkBattle(msg: { battleCode: string, battleId: number, heroes: { actorId: number, order: number }[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleId'); + let { battleId, battleCode, heroes } = msg; + + let rec = await LadderMatchRecModel.findByBattleCode(battleCode); + if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); + if(rec.status != LADDER_STATUS.CHECK) return resResult(STATUS.LADDER_REC_STATUS_ERR); + + for(let { actorId } of heroes) { + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + } + let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + + let attackHeroes = dbHeroes.map(hero => { + let heroInfo = new LadderOppPlayerHeroInfo(); + heroInfo.setByDefenseHero(hero); + return heroInfo; + }); + let warInfo = gameData.war.get(battleId); + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId, + status: 0, + warName: warInfo?.gk_name, + warType: warInfo?.warType, + } + }); + rec = await LadderMatchRecModel.startBattle(battleCode, attackHeroes); + pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.battleTime, LADDER_STATUS.BATTLE); + + return resResult(STATUS.SUCCESS, { + time: Math.floor(rec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN, + battleCode: rec.battleCode + }) + } + + // 7. 挑战结算 + async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + let { battleCode, isSuccess, damageRecords, round } = msg; + + let rec = await LadderMatchRecModel.findByBattleCode(battleCode); + if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); + if(rec.status != LADDER_STATUS.BATTLE) return resResult(STATUS.LADDER_REC_STATUS_ERR); + let rank = rec.defenseInfo.oldRank; + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); + + // 取消 checkBattle 的倒计时 + pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(battleCode); + + let result = new LadderDataReturn(); + // 交换双方排名, transaction + let { isChange, atkLadderMatch, defLadderMatch, endTime } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo); + + if(isChange) { + let oppPlayers = await battleEndWhenChange(atkLadderMatch, defLadderMatch, true); + result.setOppPlayers(oppPlayers); + rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank); + if(atkLadderMatch.rank == 1) { + pushLadderTopChangeMsg(roleId, roleName, serverId); + } + } else { + rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime); + let oppPlayers = await getLadderEnemies(atkLadderMatch); + result.setOppPlayers(oppPlayers); + } + await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } }); + if(defLadderMatch) { + await LadderMatchModel.unlock(defLadderMatch.serverId, defLadderMatch.roleId); + } + + let historyRank = ladderData.historyRank; + ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: (historyRank > atkLadderMatch.rank || historyRank == 0)? atkLadderMatch.rank: historyRank }); + + result.setLadderData(ladderData, rec); + // 获取奖励 + let rewardResult = await ladderBattleEndReward(roleId, roleName, sid, ladderData.historyRank, isSuccess, historyRank, 1); + let { battleGoods = [], breakGoods = [] } = rewardResult||{}; + + await checkTaskInLadderEnd(serverId, roleId, sid, isSuccess, historyRank, atkLadderMatch.rank); + + if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushLadderIconShow(rec.roleId2, true); + return resResult(STATUS.SUCCESS, {...pick(result, ['rank', 'historyRank', 'challengeCnt','status', 'time', 'oppPlayers']), battleGoods, breakGoods}); + } + + // 8. 战5次(扫荡) + async battleSweep(msg: { roleId: string, rank: number, count: number }, session: BackendSession) { + let serverId = session.get('serverId'); + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let { roleId: targetRoleId, rank, count } = msg; + if(count > LADDER.LADDER_INITIAL_CHALLENGE_TIMES) { + return resResult(STATUS.LADDER_SWEEP_TIMES_OVER); + } + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); + + if(ladderData.rank >= rank) return resResult(STATUS.LADDER_RANK_ERR); + + // 刷新次数 + let refOppObj = refreshLadderDaily(ladderData); + let update: LadderUpdateInter = {}; + if(refOppObj.shouldRefOpp) { + update = { ...refOppObj }; + } + + if(refOppObj.challengeCnt + count > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) { + return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX); + } + update.challengeCnt = refOppObj.challengeCnt + count; + ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update); + + // 获取奖励 + let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, rank, count); + await checkTaskInLadderSweep(serverId, roleId, sid, count) + return resResult(STATUS.SUCCESS, { + challengeCnt: ladderData.challengeCnt, + battleGoods + }); + } + + // 9. 设置防守阵容 + async saveDefense(msg: { warId: number, heroes: { actorId: number, ai: number, dataId: number, order: number, subHid?: number }[], combo: Combo[] }, session: BackendSession) { + let { warId, heroes, combo } = msg; + let roleId = session.get('roleId'); + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + + let hids: number[] = heroes.map(cur => cur.actorId); + if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); + for(let { actorId, subHid } of heroes) { + let dicHero = gameData.hero.get(actorId); + if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); + if(subHid && hids.indexOf(subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); + } + + let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true); + + let defenseHeroes = heroes.map(cur => { + let dbHero = dbHeroes.find(ccur => ccur.hid == cur.actorId); + return dbHero && new LadderDefenseHero(cur, dbHero._id, dbHero.ce); + }).filter(cur => cur); + let defense = new LadderDefense(defenseHeroes, warId, combo); + ladderData = await LadderMatchModel.updateByRoleId(roleId, { defense, hasDefense: true }); + // 返回 + let result = new LadderDataReturn(); + result.setLadderData(ladderData); + await saveLadderDefCeByData(roleId, ladderData); + + return resResult(STATUS.SUCCESS, pick(result, 'defense')); + } + + // 10. 刷新对手 + async refreshOppPlayers(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN); + + let update: LadderUpdateInter = {}; + // 刷新次数 + let refOppObj = refreshLadderDaily(ladderData); + if(refOppObj.shouldRefOpp) { + update = { ...refOppObj }; + } + + if(refOppObj.refOppCnt + 1 > LADDER.LADDER_REFRESH_TIMES) { + return resResult(STATUS.LADDER_REFRESH_CNT_MAX); + } + update.refOppCnt = refOppObj.refOppCnt + 1; + let oppPlayers = await refreshLadderEnemies(ladderData, update); + + // 返回 + return resResult(STATUS.SUCCESS, { refOppCnt: update.refOppCnt, oppPlayers }); + } + + // 11. 购买次数 + async buyCnt(msg: { count: number }, session: BackendSession) { + let { count } = msg; + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + + let update: LadderUpdateInter = {}; + // 刷新次数 + let refOppObj = refreshLadderDaily(ladderData); + if(refOppObj.shouldRefOpp) { + update = { ...refOppObj }; + } + + if(refOppObj.buyCnt + count > LADDER.LADDER_CHALLENGE_COST_TIMES) { + return resResult(STATUS.LADDER_BUY_MAX); + } + let consumes = getBuyCntCost(refOppObj.buyCnt, count); + if(!consumes) return resResult(STATUS.LADDER_BUY_MAX); + + let consumeResult = await handleCost(roleId, sid, consumes||[], ITEM_CHANGE_REASON.LADDER_BUY_CNT); + if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + update.buyCnt = refOppObj.buyCnt + count; + ladderData = await LadderMatchModel.updateByRoleId(roleId, update); + // 返回 + let result = new LadderDataReturn(); + result.setLadderData(ladderData); + return resResult(STATUS.SUCCESS, pick(result, ['buyCnt', 'challengeCnt'])); + } + + // 12. 获取战报信息(2天内) + async getRec(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let list = await LadderMatchRecModel.findRecentRec(roleId, getTimeFunM().getBeforeDay(2)); + return resResult(STATUS.SUCCESS, { + list: list.map(rec => { + const { roleId1, battleCode, hasRpl, remoteUrl } = rec; + const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; + return { ...rec, rplFileUrl }; + }), + rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) + }); + } + + // debug接口 + // 重置挑战次数 & 购买次数 + async resetCnt(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let roleId = session.get('roleId'); + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) }); + return resResult(STATUS.SUCCESS); + } + + async setMyRank(msg: { magicWord: string, rank: number }, session: BackendSession) { + const { magicWord, rank } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let atkLadderMatch = await LadderMatchModel.findByRoleId(roleId); + if(!atkLadderMatch || !atkLadderMatch.defense) return resResult(STATUS.LADDER_NOT_OPEN); + let myRank = atkLadderMatch.rank; + + let defLadderMatch = await LadderMatchModel.findByRank(serverId, rank); + if(defLadderMatch) { + atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: myRank, historyRank: rank } }, { new: true }).lean(); + defLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defLadderMatch.roleId }, { $set: { rank: myRank, oldRank: rank } }, { new: true }).lean(); + } else { + atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: atkLadderMatch.rank, historyRank: rank } }, { new: true }).lean(); + } + + await battleEndWhenChange(atkLadderMatch, defLadderMatch, true); + return resResult(STATUS.SUCCESS); + } + + async setMyOpp(msg: { magicWord: string, oppRanks: number[] }, session: BackendSession) { + const { magicWord, oppRanks } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.WRONG_PARMS); + } + if(!isArray(oppRanks) || oppRanks.length <= 0) return resResult(STATUS.WRONG_PARMS); + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN); + + let topTen = getNumberArr(1, 10); + let ranks = [...topTen, ...oppRanks]; + let newRanks = uniqueArr(ranks.sort((a, b) => a - b)); + + await generateOppPlayers(newRanks, serverId, roleId); + return resResult(STATUS.SUCCESS); + } + + async sendDailyReward(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + for(let { id } of servers) { + await sendLadderDailyReward(id); + } + return resResult(STATUS.SUCCESS) + } +} + diff --git a/game-server/app/servers/battle/handler/normalBattleHandler.ts b/game-server/app/servers/battle/handler/normalBattleHandler.ts index bb7fb35aa..748eb7dd8 100644 --- a/game-server/app/servers/battle/handler/normalBattleHandler.ts +++ b/game-server/app/servers/battle/handler/normalBattleHandler.ts @@ -1,655 +1,656 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { BattleSweepRecordModel } from '../../../db/BattleSweepRecord'; -import { BattleCheatRecModel } from '../../../db/BattleCheatRec'; -import { genCode, getReasonByWarType, getWarTypeName } from '../../../pubUtils/util'; -import { WAR_TYPE, EVENT_STATUS, REDIS_KEY, KING_EXP_RATIO_TYPE, TA_EVENT, ITEM_CHANGE_REASON, BLOCK_TYPE, CHECT_BLOCK_TYPE, CHECT_BATTLE_TYPE, CHECT_BATTLE_TYPE_HIDE, CHECT_BATTLE_TYPE_ATK_LIMIT } from '../../../consts'; -import { checkDaily, checkDailyAndIncrease } from '../../../services/dailyBattleService'; -import { checkTowerWar, towerBattleEnd } from '../../../services/battleService'; -import { WarReward } from '../../../services/warRewardService'; -import { getAp, setAp } from '../../../services/actionPointService'; -import { setBattleStatus, checkEventBattle } from '../../../services/eventSercive'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult } from '../../../pubUtils/util'; -import { RoleModel } from '../../../db/Role'; -import { RScriptRecordModel } from '../../../db/RScriptRecord'; -import { checkBattleHeroes, roleLevelup, calculateWarStar, getBattleListOfTypes, getMainChapter, getStarOfChapter, checkWarCountAndInc, getBattleRecordParam } from '../../../services/normalBattleService'; -import { checkDungeonNum, checkDungeonAndIncrease, saveDungeonFirst } from '../../../services/dungeonService'; -// import { switchOnFunc } from '../../../services/funcSwitchService'; -import { gameData } from '../../../pubUtils/data'; -import { pushMysteryFirstMsg, pushVestigeFirstMsg } from '../../../services/chatService'; -import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; -import { Rank } from '../../../services/rankService'; -import { checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInBattleSweep } from '../../../services/task/taskService'; -import { ActivitySelfServiceModel } from '../../../db/ActivitySelfService'; -import { getSelfServiceShopActivityData } from '../../../services/activity/selfServiceShopActivityService'; -import { challengeDailyGK } from '../../../services/activity/dailyGKService'; -import { challengeNewHeroGK } from '../../../services/activity/newHeroService'; -import { reportTAEvent } from '../../../services/sdkService'; -import { getVipRegretCnt } from '../../../services/activity/monthlyTicketService'; -import { isArray, isNumber } from 'underscore'; -import { RewardInter, pvpEndParamInter } from '../../../pubUtils/interface'; -import { addItems } from '../../../services/role/rewardService'; -import { treasureHuntChallengeConsume } from '../../../services/activity/treasureHuntService'; -import { combineItems } from '../../../services/role/util'; -import { isHeroHidden } from '../../../services/dataService'; -import { getRoleOnlineInfo, redisClient, roleLeave } from '../../../services/redisService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new NormalBattleHandler(app); -} - -export class NormalBattleHandler { - constructor(private app: Application) { - } - - // 获取关卡列表 - async checkBattle(msg: { battleId: number, heroes: Array }, session: BackendSession) { - const { battleId, heroes: seqIds = [] } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - let ip = session.get('ip'); - let warInfo = gameData.war.get(battleId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - let role = await RoleModel.findByRoleId(roleId, 'lv warStar warCount roleId refWarCount'); - let apJson = await getAp(roleId, ip, role.lv); - let { ap } = apJson; - if (ap < warInfo.cost) { - return resResult(STATUS.BATTLE_ACTION_POINT_LACK); - } - if (role.lv < warInfo.lvLimited) { - return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - } - // 前置关卡是否挑战过 - let { warStar } = role; - - let previousGk = warInfo.previousGk; - if (previousGk) { - let preBattle = warStar.findIndex(cur => cur.id == previousGk); - if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); - } - - let { isOK, hids, heroes, lineup } = await checkBattleHeroes(roleId, seqIds); - if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - if (isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); - - const battleCode = genCode(8); // 关卡唯一值 - let dailyNum = {}; - let towerData = {}; - let dungeonNum = {}; - if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { - let checkResult = await checkWarCountAndInc(battleId, 0, role, true); - if (checkResult.code != 0) { - return checkResult - } - } else if (warInfo.warType == WAR_TYPE.DAILY) { - let checkResult = await checkDaily(roleId, battleId, 1); - if (checkResult.status == -1) { - return checkResult.resResult - } - dailyNum = Object.assign(dailyNum, checkResult.data); - } else if (warInfo.warType == WAR_TYPE.TOWER) { - let checkResult = await checkTowerWar(roleId, battleId, seqIds, heroes); - if (checkResult.status == -1) { - return checkResult.resResult - } - towerData = Object.assign(towerData, checkResult.data); - } else if (warInfo.warType == WAR_TYPE.EVENT) { - // 记录事件状态 - let eventStatus = session.get('eventStatus') || EVENT_STATUS.WAITING; - let checkResult = await checkEventBattle(roleId, eventStatus, battleId, battleCode); - if (checkResult.status == -1) { - return checkResult.resResult - } - } else if (warInfo.warType == WAR_TYPE.MYSTERY) { - let checkResult = await checkDungeonNum(roleId, 1, battleId); - if (checkResult.status == -1) { - return checkResult.resResult - } - dungeonNum = Object.assign(dungeonNum, checkResult.data); - } - - const BattleRecord = await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId, - status: 0, - warName: warInfo.gk_name, - warType: warInfo.warType, - record: { heroes: hids, seqIds, lineup } - } - }, true); - - let { status } = BattleRecord; - - await checkTaskInBattleStart(serverId, roleId, sid, battleId); - return resResult(STATUS.SUCCESS, { - battleId, battleCode, status, dailyNum, towerData, dungeonNum - }); - } - - // 关卡列表 - async getBattleList(msg: { types: number[] }, session: BackendSession) { - const { types } = msg; - let roleId = session.get('roleId'); - - let role = await RoleModel.findByRoleId(roleId); - let result = await getBattleListOfTypes(role, types); - return resResult(STATUS.SUCCESS, { - result - }); - } - - // 关卡结算,记录使用的武将,获得奖励 - async battleEnd(msg: { battleCode: string, battleId: number, isSuccess: boolean, stars: number[], heroes: number[], activityId: number, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - const { battleCode, battleId, isSuccess, heroes = [], stars = [], activityId, damageRecords = [], round = 0 } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let ip = session.get('ip'); - let serverId = session.get('serverId'); - - let warInfo = gameData.war.get(battleId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - // 寻宝不使用通用战斗模块结算 - if (warInfo.warType == WAR_TYPE.COM_BATTLE) { - return resResult(STATUS.BATTLE_END_WRONG_TYPE); - } - // console.log('####### warInfo.warType', warInfo.warType) - - const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); - if (!BattleRecord || BattleRecord.status != 0) { - return resResult(STATUS.BATTLE_STATUS_WRONG); - } - - let flag = 1; // 对比hero信息 - let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord; - for (let seqId of dbSeqIds) { - if (dbSeqIds.indexOf(seqId) == -1) flag = 0; - } - if (!flag) { - return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); - } - - let role = await RoleModel.findByRoleId(roleId, 'lv vipStartTime warStar warCount refWarCount roleId'); - let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess ? -1 * warInfo.cost : 0, sid, getReasonByWarType(warInfo.warType)); // 扣除体力 - if (!apJson) { - return resResult(STATUS.BATTLE_ACTION_POINT_LACK); - } - - let { warStar } = role; - let isFirst = warStar.findIndex(cur => cur.id == battleId) == -1; - let curWarStar = warStar.find(cur => cur.id == battleId); - let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars); - - let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); - - let dailyNum = {}; - let towerStatus = null; - let dungeonNum = {}; - if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { - if (!isFirst) { - let checkResult = await checkWarCountAndInc(battleId, isSuccess ? 1 : 0, role, false); - if (checkResult.code != 0) { - return checkResult - } - } - } - - if (warInfo.warType == WAR_TYPE.DAILY) { - let checkResult = await checkDailyAndIncrease(roleId, warStar, battleId, isSuccess ? 1 : 0, false, stars, role); - if (checkResult.status == -1) { - return checkResult.resResult; - } - dailyNum = Object.assign(dailyNum, checkResult.data) - } else if (warInfo.warType == WAR_TYPE.EVENT) { - // 记录事件状态 - await setBattleStatus(session, roleId, battleId, isSuccess, battleCode); - } else if (warInfo.warType == WAR_TYPE.TOWER) { - let towerEndResult = await towerBattleEnd(sid, roleId, serverId, battleCode, battleId, isSuccess, dbHeroes, dbSeqIds, damageRecords); - if (towerEndResult) { - if (towerEndResult.status == -1) { - return towerEndResult.resResult; - } - towerStatus = towerEndResult.data.towerStatus; - - // console.log('##### towerReward', JSON.stringify(towerEndResult.data.towerReward)); - - if (towerEndResult.data.towerReward) - warReward.setFixReward(towerEndResult.data.towerReward) - } - } else if (warInfo.warType == WAR_TYPE.MYSTERY) { - let checkResult = await checkDungeonAndIncrease(roleId, isSuccess ? 1 : 0, false, battleId); - let role = await RoleModel.saveDungeonHero(roleId, battleId, heroes, isSuccess); - if (role) { - await saveDungeonFirst(role, battleId, BattleRecord); - } - - if (checkResult.status == -1) { - return checkResult.resResult; - } - dungeonNum = Object.assign(dungeonNum, checkResult.data) - } else if (warInfo.warType == WAR_TYPE.NORMAL) { - if (isSuccess) { - let role = await RoleModel.updateMainWarId(roleId, battleId, nowSeconds()); - if (role) { - let r = new Rank(REDIS_KEY.MAIN_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, role.mainWarId, role.mainUpdatedAt, role); - } - } - } else if (warInfo.warType == WAR_TYPE.MAIN_ELITE) { - if (isSuccess) { - let role = await RoleModel.updateMainEliteWarId(roleId, battleId, nowSeconds()); - if (role) { - let r = new Rank(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); - } - } - } else if (warInfo.warType == WAR_TYPE.ACT_SELF_SHOP) { - //糜家商队挑战成功后记录挑战次数 - if (isSuccess) { - let playerData = await getSelfServiceShopActivityData(serverId, roleId) - await ActivitySelfServiceModel.addChallengeRecord(serverId, playerData.activityId, roleId, playerData.roundIndex, 1, new Date()) - } - } else if (warInfo.warType == WAR_TYPE.ACT_DAILY_GK) { - if (isSuccess) { - await challengeDailyGK(serverId, roleId, activityId, battleId) - } - } else if (warInfo.warType == WAR_TYPE.ACT_NEW_HERO_GK) { - // console.log('##### warInfo.warType', warInfo.warType, isSuccess) - if (isSuccess) { - isFirst = await challengeNewHeroGK(serverId, roleId, activityId, battleId) - } - } else if (warInfo.warType == WAR_TYPE.ACT_TREASURE_HUNT) { - if (isSuccess) { - await treasureHuntChallengeConsume(serverId, roleId, sid); - } - } - - if (isSuccess) { // 挑战胜利 - // 是否首通 - if (isFirst) { - // await switchOnFunc(roleId, FUNC_OPT_TYPE.BATTLE_END, battleId, session); - warReward.setCondition(0, true); - reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes }); - pushMysteryFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); - pushVestigeFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); - } - // 是否首次3星 - if (newStar == 3 && (isFirst || curWarStar.star != 3)) { - warReward.setCondition(1, true); - } - - if (!curWarStar || newStar > curWarStar.star) { - await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); - } - } - - let reward = await warReward.saveReward(1); - - const updateResult = await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { status: isSuccess ? 1 : 2, star: newStar, stars, ...getBattleRecordParam(damageRecords, round, heroes) } - }, true); - let { status } = updateResult; - - let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 - - await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, newStar, isSuccess); - // 返回值: - // towerStatus: false-本层未通过, true-本层已通过 - return resResult(STATUS.SUCCESS, { - battleCode, battleId, status, - battleGoods: reward, - towerStatus, dailyNum, dungeonNum, - createdAt: getSeconds(createdAt), - ...actordata - }); - } - - async battleSweep(msg: { battleId: number, count: number }, session: BackendSession) { - - const { battleId, count } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let ip = session.get('ip'); - - let warInfo = gameData.war.get(battleId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - // 校验是否三星通关过 - let { warStar } = await RoleModel.findByRoleId(roleId); - let curWar = warStar.find(cur => cur.id == battleId); - if (!curWar || curWar.star < 3) { - return resResult(STATUS.BATTLE_SWEEP_CONDITION_STAR); - } - let role = await RoleModel.findByRoleId(roleId, 'lv warCount refWarCount roleId'); - if (role.lv < warInfo.lvLimited) { - return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - } - // 扫荡次数 - let dailyNum = {}; - let dungeonNum = {}; - if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { - let checkResult = await checkWarCountAndInc(battleId, count, role, true); - if (checkResult.code != 0) { - return checkResult - } - } else if (warInfo.warType == WAR_TYPE.DAILY) { - let checkResult = await checkDailyAndIncrease(roleId, warStar, battleId, count, true); - if (checkResult.status == -1) { - return checkResult.resResult - } - dailyNum = Object.assign(dailyNum, checkResult.data) - } else if (warInfo.warType == WAR_TYPE.MYSTERY) { - let checkResult = await checkDungeonAndIncrease(roleId, count, true, battleId); - if (checkResult.status == -1) { - return checkResult.resResult - } - dungeonNum = Object.assign(dungeonNum, checkResult.data) - } - - - // 扣体力 - let apJson = await setAp(serverId, roleId, ip, role.lv, -1 * warInfo.cost * count, sid, getReasonByWarType(warInfo.warType)); // 扣除体力 - if (!apJson) { - return resResult(STATUS.BATTLE_ACTION_POINT_LACK); - } - - // 发奖励 - let warReward = new WarReward(roleId, roleName, sid, battleId, true); - let result = await warReward.saveReward(count, true); - - let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, warInfo.kingExp * count, session)// 主公升级经验 - - // 扫荡记录 - await BattleSweepRecordModel.saveBattleSweepRecordById(roleId, battleId, { - $set: { - roleName, - warName: warInfo.gk_name, - warType: warInfo.warType - }, - $inc: { count } - }); - - await checkTaskInBattleSweep(serverId, roleId, sid, battleId, count); - - return resResult(STATUS.SUCCESS, { - battleId, count, - battleGoods: result, - dailyNum, dungeonNum, - ...actordata - }); - } - - async saveScript(msg: { battleId: number, type: number, script: string }, session: BackendSession) { - - const { battleId, type, script } = msg; - let roleId = session.get('roleId'); - let warInfo = gameData.war.get(battleId); - let result = await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, type, script); - if (result) { - if (!result.scriptBefore) result.scriptBefore = ''; - if (!result.scriptAfter) result.scriptAfter = ''; - return resResult(STATUS.SUCCESS, result); - } else { - console.error('script not created'); - return resResult(STATUS.INTERNAL_ERR); - } - - } - - async getScriptByBattle(msg: { battleIds: Array }, session: BackendSession) { - - const { battleIds } = msg; - let roleId = session.get('roleId'); - let list = new Array(); - for (let battleId of battleIds) { - let result = await RScriptRecordModel.findbyRoleAndBattle(roleId, battleId); - if (result) { - let { scriptBefore = '', scriptAfter = '' } = result; - - list.push({ battleId, scriptBefore, scriptAfter }); - } else { - list.push({ battleId, scriptBefore: '', scriptAfter: '' }); - } - } - return resResult(STATUS.SUCCESS, { list }); - } - - // 获取悔棋次数 - async getRegretCnt(msg: { warId: number, battleCode: string }, session: BackendSession) { - - const { warId, battleCode } = msg; - let roleId: string = session.get('roleId'); - let vipStartTime: number = session.get('vipStartTime'); - - let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); - if (!battleRecord || battleRecord.roleId != roleId || battleRecord.battleId != warId) { - return resResult(STATUS.WRONG_PARMS); - } - let maxRegretCnt = getVipRegretCnt(vipStartTime); - return resResult(STATUS.SUCCESS, { regretCnt: battleRecord.regretCnt || 0, maxRegretCnt }); - } - - // 记录悔棋次数 - async incRegretCnt(msg: { warId: number, battleCode: string, count: number }, session: BackendSession) { - - const { warId, battleCode, count } = msg; - let roleId: string = session.get('roleId'); - let vipStartTime: number = session.get('vipStartTime'); - - let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); - if (!battleRecord || battleRecord.roleId != roleId || battleRecord.battleId != warId) { - return resResult(STATUS.WRONG_PARMS); - } - let maxRegretCnt = getVipRegretCnt(vipStartTime); - let regretCnt = battleRecord.regretCnt || 0; - if (regretCnt + count > maxRegretCnt) { - return resResult(STATUS.BATTLE_REGRET_MAX); - } - battleRecord = await BattleRecordModel.incRegretCnt(battleCode, count); - - return resResult(STATUS.SUCCESS, { regretCnt: battleRecord.regretCnt || 0, maxRegretCnt }); - } - - async getMainStarBox(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId, 'warStar receivedBox'); - - let result = getMainChapter(role); - return resResult(STATUS.SUCCESS, result); - } - - // 关卡列表 - async receiveChapterBox(msg: { chapter: number, id: number, warType: number }, session: BackendSession) { - const { id, chapter, warType } = msg; - if (!isNumber(id)) return resResult(STATUS.WRONG_PARMS); - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - let role = await RoleModel.findByRoleId(roleId, 'warStar receivedBox'); - let ids: number[] = []; - let rewards: RewardInter[] = []; - let star = getStarOfChapter(role.warStar, warType, chapter); - - let boxIds = id == 0 ? gameData.mainBoxByChapter.get(`${warType}_${chapter}`) : [id]; - - for (let id of boxIds) { - let dicBox = gameData.mainBox.get(id); - if (dicBox && dicBox.chapter == chapter && dicBox.warType == warType) { - if (star >= dicBox.star && role.receivedBox.indexOf(id) == -1) { - rewards.push(...dicBox.reward); - ids.push(id); - } - } - } - if (ids.length <= 0) return resResult(STATUS.BATTLE_NO_BOX_CAN_RECEIVE); - role = await RoleModel.receivedBox(roleId, ids); - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RECEIVE_CHAPTER_BOX) - - let result = getMainChapter(role); - return resResult(STATUS.SUCCESS, { - ...result, goods - }); - } - - // 关卡列表 - async receiveWarReward(msg: { chapter: number, warType: number }, session: BackendSession) { - const { chapter, warType } = msg; - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - let role = await RoleModel.findByRoleId(roleId, 'receivedWarIds warStar'); - let { warStar, receivedWarIds = [] } = role; - let warIds: number[] = []; - let rewards: RewardInter[] = []; - let mainWarRewards = gameData.mainWarReward.get(`${warType}_${chapter}`) ?? []; - - for (let { warId, cityReward } of mainWarRewards) { - let index = warStar.findIndex(cur => cur.id == warId); - if (index != -1 && receivedWarIds.indexOf(warId) == -1) { - rewards.push(...cityReward); - warIds.push(warId); - } - } - if (warIds.length <= 0) return resResult(STATUS.BATTLE_NO_WAR_REWARD_CAN_RECEIVE); - role = await RoleModel.receiveWarRewards(roleId, warIds); - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RECEIVE_CHAPTER_BOX) - - return resResult(STATUS.SUCCESS, { - receivedWarIds: warIds, goods: combineItems(goods) - }); - } - - // 记录战场校验异常数据 - async recordBattleCheat(msg: { dataId: number, type: number, iKey: number, value: number, secV: number }, session: BackendSession) { - const { dataId, type, iKey, value, secV } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - const rec = await BattleCheatRecModel.createRecord(dataId || 0, type, iKey || 0, value || 0, secV || 0, roleId, roleName); - if (!rec) { - return resResult(STATUS.BATTLE_CHECK_REC_SAVE_ERR); - } - - await this.blockByRecordBattleCheat(roleId, type, sid); - - return resResult(STATUS.SUCCESS); - } - - - /** - * 防破解实时封号 - * @param {string} roleId - * @param {number} type 查封类型(封除类型不为200) - * @returns - */ - async blockByRecordBattleCheat(roleId: string, type: number, sid: string) { - if (roleId == undefined || type == undefined || sid == undefined) { - return; - } - if (type && (type === CHECT_BATTLE_TYPE || type === CHECT_BATTLE_TYPE_HIDE || type === CHECT_BATTLE_TYPE_ATK_LIMIT || type === 203 || ( type >= 300 && type <= 400 && type != 321 ))) { - // console.log("blockByRecordBattleCheat----type=", type); - return; - } - - // 设置redis开关 - let isCheckBlock = await redisClient().getAsync(REDIS_KEY.IS_CHECT_BLOCK); - if (!isCheckBlock || isCheckBlock == undefined) { - //首次写入 默认是关 - await redisClient().setAsync(REDIS_KEY.IS_CHECT_BLOCK, `${CHECT_BLOCK_TYPE.CLOSE}`); - isCheckBlock = CHECT_BLOCK_TYPE.CLOSE.toString(); - } - - // 仅当为open状态才执行封号 - if (isCheckBlock && parseInt(isCheckBlock) == CHECT_BLOCK_TYPE.OPEN) { - const blockType: BLOCK_TYPE = BLOCK_TYPE.BLOCK; - const blockReason: string = "使用第三方软件, 封停账号, 封停时间为:" + new Date();; - let role = await RoleModel.updateRoleInfo(roleId, { blockType, blockReason }); - if (!role) return resResult(STATUS.ROLE_NOT_FOUND); - - await this.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid, [{ roleId, blockType }]); - await this.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId, STATUS.BLOCKED); - await roleLeave(roleId); - } else { - console.log("blockByRecordBattleCheat-防破解查封功能已关闭!!!"); - } - - return; - } - - // 是否可以跳过 - async checkSkip(msg: { battleCode: string }, session: BackendSession) { - const { battleCode } = msg; - let roleId = session.get('roleId'); - - let role = await RoleModel.findByRoleId(roleId, 'warStar vipStartTime'); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - let { warStar, vipStartTime } = role; - - if((!vipStartTime || vipStartTime == 0) && role.lv <= 30) { - return resResult(STATUS.SUCCESS, { - battleCode, - canSkip: false - }); - } - - let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); - if(!battleRecord || battleRecord.roleId != roleId) return resResult(STATUS.BATTLE_NOT_FOUND); - let battleId = battleRecord.battleId; - let dicWar = gameData.war.get(battleId); - if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hasPass = warStar.findIndex(cur => cur.id == battleId) != -1; // 是否首通过 - let canSkip = false; - switch (dicWar.warType) { - case WAR_TYPE.VESTIGE: - case WAR_TYPE.BRANCH_ELITE: - case WAR_TYPE.ACT_DAILY_GK: - case WAR_TYPE.ACT_NEW_HERO_GK: - canSkip = false; - break; - case WAR_TYPE.NORMAL: - canSkip = dicWar.isCity? (dicWar.chapter != 0 && hasPass): true; - break; - case WAR_TYPE.MAIN_ELITE: - case WAR_TYPE.MYSTERY: - canSkip = dicWar.isCity? hasPass: true; - break; - case WAR_TYPE.ACT_TREASURE_HUNT: - case WAR_TYPE.ACT_SELF_SHOP: - case WAR_TYPE.TOWER: - case WAR_TYPE.LADDER: - case WAR_TYPE.GUILD_TRAIN: - case WAR_TYPE.PVP: - case WAR_TYPE.DAILY: - case WAR_TYPE.EVENT: - case WAR_TYPE.EXPEDITION: - case WAR_TYPE.GVG_VESTIGE: - case WAR_TYPE.GVG_BATTLE: - case WAR_TYPE.ROUGE: - case WAR_TYPE.FRIEND_BATTLE: - canSkip = true; - break; - } - - - return resResult(STATUS.SUCCESS, { - battleCode, canSkip - }); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { BattleSweepRecordModel } from '@db/BattleSweepRecord'; +import { BattleCheatRecModel } from '@db/BattleCheatRec'; +import { genCode, getReasonByWarType, getWarTypeName } from '@pubUtils/util'; +import { WAR_TYPE, EVENT_STATUS, REDIS_KEY, KING_EXP_RATIO_TYPE, TA_EVENT, ITEM_CHANGE_REASON, BLOCK_TYPE, CHECT_BLOCK_TYPE, CHECT_BATTLE_TYPE, CHECT_BATTLE_TYPE_HIDE, CHECT_BATTLE_TYPE_ATK_LIMIT } from '../../../consts'; +import { checkDaily, checkDailyAndIncrease } from '../../../services/dailyBattleService'; +import { checkTowerWar, towerBattleEnd } from '../../../services/battleService'; +import { WarReward } from '../../../services/warRewardService'; +import { getAp, setAp } from '../../../services/actionPointService'; +import { setBattleStatus, checkEventBattle } from '../../../services/eventSercive'; +import { STATUS } from '@consts/statusCode'; +import { resResult } from '@pubUtils/util'; +import { RoleModel } from '@db/Role'; +import { RScriptRecordModel } from '@db/RScriptRecord'; +import { checkBattleHeroes, roleLevelup, calculateWarStar, getBattleListOfTypes, getMainChapter, getStarOfChapter, checkWarCountAndInc, getBattleRecordParam } from '../../../services/normalBattleService'; +import { checkDungeonNum, checkDungeonAndIncrease, saveDungeonFirst } from '../../../services/dungeonService'; +// import { switchOnFunc } from '../../../services/funcSwitchService'; +import { gameData } from '@pubUtils/data'; +import { pushMysteryFirstMsg, pushVestigeFirstMsg } from '../../../services/chatService'; +import { getSeconds, nowSeconds } from '@pubUtils/timeUtil'; +import { Rank } from '../../../services/rankService'; +import { checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInBattleSweep } from '../../../services/task/taskService'; +import { ActivitySelfServiceModel } from '@db/ActivitySelfService'; +import { getSelfServiceShopActivityData } from '../../../services/activity/selfServiceShopActivityService'; +import { challengeDailyGK } from '../../../services/activity/dailyGKService'; +import { challengeNewHeroGK } from '../../../services/activity/newHeroService'; +import { reportTAEvent } from '../../../services/sdkService'; +import { getVipRegretCnt } from '../../../services/activity/monthlyTicketService'; +import { isArray, isNumber } from 'underscore'; +import { RewardInter, pvpEndParamInter } from '@pubUtils/interface'; +import { addItems } from '../../../services/role/rewardService'; +import { treasureHuntChallengeConsume } from '../../../services/activity/treasureHuntService'; +import { combineItems } from '../../../services/role/util'; +import { isHeroHidden } from '../../../services/dataService'; +import { getRoleOnlineInfo, redisClient, roleLeave } from '../../../services/redisService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new NormalBattleHandler(app); +} + +export class NormalBattleHandler { + constructor(private app: Application) { + } + + // 获取关卡列表 + async checkBattle(msg: { battleId: number, heroes: Array }, session: BackendSession) { + const { battleId, heroes: seqIds = [] } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + let ip = session.get('ip'); + let warInfo = gameData.war.get(battleId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + let role = await RoleModel.findByRoleId(roleId, 'lv warStar warCount roleId refWarCount'); + let apJson = await getAp(roleId, ip, role.lv); + let { ap } = apJson; + if (ap < warInfo.cost) { + return resResult(STATUS.BATTLE_ACTION_POINT_LACK); + } + if (role.lv < warInfo.lvLimited) { + return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); + } + // 前置关卡是否挑战过 + let { warStar } = role; + + let previousGk = warInfo.previousGk; + if (previousGk) { + let preBattle = warStar.findIndex(cur => cur.id == previousGk); + if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); + } + + let { isOK, hids, heroes, lineup } = await checkBattleHeroes(roleId, seqIds); + if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + if (isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); + + const battleCode = genCode(8); // 关卡唯一值 + let dailyNum = {}; + let towerData = {}; + let dungeonNum = {}; + if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { + let checkResult = await checkWarCountAndInc(battleId, 0, role, true); + if (checkResult.code != 0) { + return checkResult + } + } else if (warInfo.warType == WAR_TYPE.DAILY) { + let checkResult = await checkDaily(roleId, battleId, 1); + if (checkResult.status == -1) { + return checkResult.resResult + } + dailyNum = Object.assign(dailyNum, checkResult.data); + } else if (warInfo.warType == WAR_TYPE.TOWER) { + let checkResult = await checkTowerWar(roleId, battleId, seqIds, heroes); + if (checkResult.status == -1) { + return checkResult.resResult + } + towerData = Object.assign(towerData, checkResult.data); + } else if (warInfo.warType == WAR_TYPE.EVENT) { + // 记录事件状态 + let eventStatus = session.get('eventStatus') || EVENT_STATUS.WAITING; + let checkResult = await checkEventBattle(roleId, eventStatus, battleId, battleCode); + if (checkResult.status == -1) { + return checkResult.resResult + } + } else if (warInfo.warType == WAR_TYPE.MYSTERY) { + let checkResult = await checkDungeonNum(roleId, 1, battleId); + if (checkResult.status == -1) { + return checkResult.resResult + } + dungeonNum = Object.assign(dungeonNum, checkResult.data); + } + + const BattleRecord = await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId, + status: 0, + warName: warInfo.gk_name, + warType: warInfo.warType, + record: { heroes: hids, seqIds, lineup } + } + }, true); + + let { status } = BattleRecord; + + await checkTaskInBattleStart(serverId, roleId, sid, battleId); + return resResult(STATUS.SUCCESS, { + battleId, battleCode, status, dailyNum, towerData, dungeonNum + }); + } + + // 关卡列表 + async getBattleList(msg: { types: number[] }, session: BackendSession) { + const { types } = msg; + let roleId = session.get('roleId'); + + let role = await RoleModel.findByRoleId(roleId); + let result = await getBattleListOfTypes(role, types); + return resResult(STATUS.SUCCESS, { + result + }); + } + + // 关卡结算,记录使用的武将,获得奖励 + async battleEnd(msg: { battleCode: string, battleId: number, isSuccess: boolean, stars: number[], heroes: number[], activityId: number, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + const { battleCode, battleId, isSuccess, heroes = [], stars = [], activityId, damageRecords = [], round = 0 } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let ip = session.get('ip'); + let serverId = session.get('serverId'); + + let warInfo = gameData.war.get(battleId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + // 寻宝不使用通用战斗模块结算 + if (warInfo.warType == WAR_TYPE.COM_BATTLE) { + return resResult(STATUS.BATTLE_END_WRONG_TYPE); + } + // console.log('####### warInfo.warType', warInfo.warType) + + const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); + if (!BattleRecord || BattleRecord.status != 0) { + return resResult(STATUS.BATTLE_STATUS_WRONG); + } + + let flag = 1; // 对比hero信息 + let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord; + for (let seqId of dbSeqIds) { + if (dbSeqIds.indexOf(seqId) == -1) flag = 0; + } + if (!flag) { + return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); + } + + let role = await RoleModel.findByRoleId(roleId, 'lv vipStartTime warStar warCount refWarCount roleId'); + let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess ? -1 * warInfo.cost : 0, sid, getReasonByWarType(warInfo.warType)); // 扣除体力 + if (!apJson) { + return resResult(STATUS.BATTLE_ACTION_POINT_LACK); + } + + let { warStar } = role; + let isFirst = warStar.findIndex(cur => cur.id == battleId) == -1; + let curWarStar = warStar.find(cur => cur.id == battleId); + let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars); + + let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); + + let dailyNum = {}; + let towerStatus = null; + let dungeonNum = {}; + if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { + if (!isFirst) { + let checkResult = await checkWarCountAndInc(battleId, isSuccess ? 1 : 0, role, false); + if (checkResult.code != 0) { + return checkResult + } + } + } + + if (warInfo.warType == WAR_TYPE.DAILY) { + let checkResult = await checkDailyAndIncrease(roleId, warStar, battleId, isSuccess ? 1 : 0, false, stars, role); + if (checkResult.status == -1) { + return checkResult.resResult; + } + dailyNum = Object.assign(dailyNum, checkResult.data) + } else if (warInfo.warType == WAR_TYPE.EVENT) { + // 记录事件状态 + await setBattleStatus(session, roleId, battleId, isSuccess, battleCode); + } else if (warInfo.warType == WAR_TYPE.TOWER) { + let towerEndResult = await towerBattleEnd(sid, roleId, serverId, battleCode, battleId, isSuccess, dbHeroes, dbSeqIds, damageRecords); + if (towerEndResult) { + if (towerEndResult.status == -1) { + return towerEndResult.resResult; + } + towerStatus = towerEndResult.data.towerStatus; + + // console.log('##### towerReward', JSON.stringify(towerEndResult.data.towerReward)); + + if (towerEndResult.data.towerReward) + warReward.setFixReward(towerEndResult.data.towerReward) + } + } else if (warInfo.warType == WAR_TYPE.MYSTERY) { + let checkResult = await checkDungeonAndIncrease(roleId, isSuccess ? 1 : 0, false, battleId); + let role = await RoleModel.saveDungeonHero(roleId, battleId, heroes, isSuccess); + if (role) { + await saveDungeonFirst(role, battleId, BattleRecord); + } + + if (checkResult.status == -1) { + return checkResult.resResult; + } + dungeonNum = Object.assign(dungeonNum, checkResult.data) + } else if (warInfo.warType == WAR_TYPE.NORMAL) { + if (isSuccess) { + let role = await RoleModel.updateMainWarId(roleId, battleId, nowSeconds()); + if (role) { + let r = new Rank(REDIS_KEY.MAIN_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, role.mainWarId, role.mainUpdatedAt, role); + } + } + } else if (warInfo.warType == WAR_TYPE.MAIN_ELITE) { + if (isSuccess) { + let role = await RoleModel.updateMainEliteWarId(roleId, battleId, nowSeconds()); + if (role) { + let r = new Rank(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); + } + } + } else if (warInfo.warType == WAR_TYPE.ACT_SELF_SHOP) { + //糜家商队挑战成功后记录挑战次数 + if (isSuccess) { + let playerData = await getSelfServiceShopActivityData(serverId, roleId) + await ActivitySelfServiceModel.addChallengeRecord(serverId, playerData.activityId, roleId, playerData.roundIndex, 1, new Date()) + } + } else if (warInfo.warType == WAR_TYPE.ACT_DAILY_GK) { + if (isSuccess) { + await challengeDailyGK(serverId, roleId, activityId, battleId) + } + } else if (warInfo.warType == WAR_TYPE.ACT_NEW_HERO_GK) { + // console.log('##### warInfo.warType', warInfo.warType, isSuccess) + if (isSuccess) { + isFirst = await challengeNewHeroGK(serverId, roleId, activityId, battleId) + } + } else if (warInfo.warType == WAR_TYPE.ACT_TREASURE_HUNT) { + if (isSuccess) { + await treasureHuntChallengeConsume(serverId, roleId, sid); + } + } + + if (isSuccess) { // 挑战胜利 + // 是否首通 + if (isFirst) { + // await switchOnFunc(roleId, FUNC_OPT_TYPE.BATTLE_END, battleId, session); + warReward.setCondition(0, true); + reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes }); + pushMysteryFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); + pushVestigeFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); + } + // 是否首次3星 + if (newStar == 3 && (isFirst || curWarStar.star != 3)) { + warReward.setCondition(1, true); + } + + if (!curWarStar || newStar > curWarStar.star) { + await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars }); + } + } + + let reward = await warReward.saveReward(1); + + const updateResult = await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { status: isSuccess ? 1 : 2, star: newStar, stars, ...getBattleRecordParam(damageRecords, round, heroes) } + }, true); + let { status } = updateResult; + + let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 + + await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, newStar, isSuccess); + // 返回值: + // towerStatus: false-本层未通过, true-本层已通过 + return resResult(STATUS.SUCCESS, { + battleCode, battleId, status, + battleGoods: reward, + towerStatus, dailyNum, dungeonNum, + createdAt: getSeconds(createdAt), + ...actordata + }); + } + + async battleSweep(msg: { battleId: number, count: number }, session: BackendSession) { + + const { battleId, count } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let ip = session.get('ip'); + + let warInfo = gameData.war.get(battleId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + // 校验是否三星通关过 + let { warStar } = await RoleModel.findByRoleId(roleId); + let curWar = warStar.find(cur => cur.id == battleId); + if (!curWar || curWar.star < 3) { + return resResult(STATUS.BATTLE_SWEEP_CONDITION_STAR); + } + let role = await RoleModel.findByRoleId(roleId, 'lv warCount refWarCount roleId'); + if (role.lv < warInfo.lvLimited) { + return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); + } + // 扫荡次数 + let dailyNum = {}; + let dungeonNum = {}; + if (warInfo.warType == WAR_TYPE.NORMAL || warInfo.warType == WAR_TYPE.MAIN_ELITE) { + let checkResult = await checkWarCountAndInc(battleId, count, role, true); + if (checkResult.code != 0) { + return checkResult + } + } else if (warInfo.warType == WAR_TYPE.DAILY) { + let checkResult = await checkDailyAndIncrease(roleId, warStar, battleId, count, true); + if (checkResult.status == -1) { + return checkResult.resResult + } + dailyNum = Object.assign(dailyNum, checkResult.data) + } else if (warInfo.warType == WAR_TYPE.MYSTERY) { + let checkResult = await checkDungeonAndIncrease(roleId, count, true, battleId); + if (checkResult.status == -1) { + return checkResult.resResult + } + dungeonNum = Object.assign(dungeonNum, checkResult.data) + } + + + // 扣体力 + let apJson = await setAp(serverId, roleId, ip, role.lv, -1 * warInfo.cost * count, sid, getReasonByWarType(warInfo.warType)); // 扣除体力 + if (!apJson) { + return resResult(STATUS.BATTLE_ACTION_POINT_LACK); + } + + // 发奖励 + let warReward = new WarReward(roleId, roleName, sid, battleId, true); + let result = await warReward.saveReward(count, true); + + let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, warInfo.kingExp * count, session)// 主公升级经验 + + // 扫荡记录 + await BattleSweepRecordModel.saveBattleSweepRecordById(roleId, battleId, { + $set: { + roleName, + warName: warInfo.gk_name, + warType: warInfo.warType + }, + $inc: { count } + }); + + await checkTaskInBattleSweep(serverId, roleId, sid, battleId, count); + + return resResult(STATUS.SUCCESS, { + battleId, count, + battleGoods: result, + dailyNum, dungeonNum, + ...actordata + }); + } + + async saveScript(msg: { battleId: number, type: number, script: string }, session: BackendSession) { + + const { battleId, type, script } = msg; + let roleId = session.get('roleId'); + let warInfo = gameData.war.get(battleId); + let result = await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, type, script); + if (result) { + if (!result.scriptBefore) result.scriptBefore = ''; + if (!result.scriptAfter) result.scriptAfter = ''; + return resResult(STATUS.SUCCESS, result); + } else { + console.error('script not created'); + return resResult(STATUS.INTERNAL_ERR); + } + + } + + async getScriptByBattle(msg: { battleIds: Array }, session: BackendSession) { + + const { battleIds } = msg; + let roleId = session.get('roleId'); + let list = new Array(); + for (let battleId of battleIds) { + let result = await RScriptRecordModel.findbyRoleAndBattle(roleId, battleId); + if (result) { + let { scriptBefore = '', scriptAfter = '' } = result; + + list.push({ battleId, scriptBefore, scriptAfter }); + } else { + list.push({ battleId, scriptBefore: '', scriptAfter: '' }); + } + } + return resResult(STATUS.SUCCESS, { list }); + } + + // 获取悔棋次数 + async getRegretCnt(msg: { warId: number, battleCode: string }, session: BackendSession) { + + const { warId, battleCode } = msg; + let roleId: string = session.get('roleId'); + let vipStartTime: number = session.get('vipStartTime'); + + let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); + if (!battleRecord || battleRecord.roleId != roleId || battleRecord.battleId != warId) { + return resResult(STATUS.WRONG_PARMS); + } + let maxRegretCnt = getVipRegretCnt(vipStartTime); + return resResult(STATUS.SUCCESS, { regretCnt: battleRecord.regretCnt || 0, maxRegretCnt }); + } + + // 记录悔棋次数 + async incRegretCnt(msg: { warId: number, battleCode: string, count: number }, session: BackendSession) { + + const { warId, battleCode, count } = msg; + let roleId: string = session.get('roleId'); + let vipStartTime: number = session.get('vipStartTime'); + + let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); + if (!battleRecord || battleRecord.roleId != roleId || battleRecord.battleId != warId) { + return resResult(STATUS.WRONG_PARMS); + } + let maxRegretCnt = getVipRegretCnt(vipStartTime); + let regretCnt = battleRecord.regretCnt || 0; + if (regretCnt + count > maxRegretCnt) { + return resResult(STATUS.BATTLE_REGRET_MAX); + } + battleRecord = await BattleRecordModel.incRegretCnt(battleCode, count); + + return resResult(STATUS.SUCCESS, { regretCnt: battleRecord.regretCnt || 0, maxRegretCnt }); + } + + async getMainStarBox(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId, 'warStar receivedBox'); + + let result = getMainChapter(role); + return resResult(STATUS.SUCCESS, result); + } + + // 关卡列表 + async receiveChapterBox(msg: { chapter: number, id: number, warType: number }, session: BackendSession) { + const { id, chapter, warType } = msg; + if (!isNumber(id)) return resResult(STATUS.WRONG_PARMS); + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + let role = await RoleModel.findByRoleId(roleId, 'warStar receivedBox'); + let ids: number[] = []; + let rewards: RewardInter[] = []; + let star = getStarOfChapter(role.warStar, warType, chapter); + + let boxIds = id == 0 ? gameData.mainBoxByChapter.get(`${warType}_${chapter}`) : [id]; + + for (let id of boxIds) { + let dicBox = gameData.mainBox.get(id); + if (dicBox && dicBox.chapter == chapter && dicBox.warType == warType) { + if (star >= dicBox.star && role.receivedBox.indexOf(id) == -1) { + rewards.push(...dicBox.reward); + ids.push(id); + } + } + } + if (ids.length <= 0) return resResult(STATUS.BATTLE_NO_BOX_CAN_RECEIVE); + role = await RoleModel.receivedBox(roleId, ids); + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RECEIVE_CHAPTER_BOX) + + let result = getMainChapter(role); + return resResult(STATUS.SUCCESS, { + ...result, goods + }); + } + + // 关卡列表 + async receiveWarReward(msg: { chapter: number, warType: number }, session: BackendSession) { + const { chapter, warType } = msg; + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + let role = await RoleModel.findByRoleId(roleId, 'receivedWarIds warStar'); + let { warStar, receivedWarIds = [] } = role; + let warIds: number[] = []; + let rewards: RewardInter[] = []; + let mainWarRewards = gameData.mainWarReward.get(`${warType}_${chapter}`) ?? []; + + for (let { warId, cityReward } of mainWarRewards) { + let index = warStar.findIndex(cur => cur.id == warId); + if (index != -1 && receivedWarIds.indexOf(warId) == -1) { + rewards.push(...cityReward); + warIds.push(warId); + } + } + if (warIds.length <= 0) return resResult(STATUS.BATTLE_NO_WAR_REWARD_CAN_RECEIVE); + role = await RoleModel.receiveWarRewards(roleId, warIds); + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RECEIVE_CHAPTER_BOX) + + return resResult(STATUS.SUCCESS, { + receivedWarIds: warIds, goods: combineItems(goods) + }); + } + + // 记录战场校验异常数据 + async recordBattleCheat(msg: { dataId: number, type: number, iKey: number, value: number, secV: number }, session: BackendSession) { + const { dataId, type, iKey, value, secV } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + const rec = await BattleCheatRecModel.createRecord(dataId || 0, type, iKey || 0, value || 0, secV || 0, roleId, roleName); + if (!rec) { + return resResult(STATUS.BATTLE_CHECK_REC_SAVE_ERR); + } + + await this.blockByRecordBattleCheat(roleId, type, sid); + + return resResult(STATUS.SUCCESS); + } + + + /** + * 防破解实时封号 + * @param {string} roleId + * @param {number} type 查封类型(封除类型不为200) + * @returns + */ + async blockByRecordBattleCheat(roleId: string, type: number, sid: string) { + if (roleId == undefined || type == undefined || sid == undefined) { + return; + } + if (type && (type === CHECT_BATTLE_TYPE || type === CHECT_BATTLE_TYPE_HIDE || type === CHECT_BATTLE_TYPE_ATK_LIMIT || type === 203 || ( type >= 300 && type <= 400 && type != 321 ))) { + // console.log("blockByRecordBattleCheat----type=", type); + return; + } + + // 设置redis开关 + let isCheckBlock = await redisClient().getAsync(REDIS_KEY.IS_CHECT_BLOCK); + if (!isCheckBlock || isCheckBlock == undefined) { + //首次写入 默认是关 + await redisClient().setAsync(REDIS_KEY.IS_CHECT_BLOCK, `${CHECT_BLOCK_TYPE.CLOSE}`); + isCheckBlock = CHECT_BLOCK_TYPE.CLOSE.toString(); + } + + // 仅当为open状态才执行封号 + if (isCheckBlock && parseInt(isCheckBlock) == CHECT_BLOCK_TYPE.OPEN) { + const blockType: BLOCK_TYPE = BLOCK_TYPE.BLOCK; + const blockReason: string = "使用第三方软件, 封停账号, 封停时间为:" + new Date();; + let role = await RoleModel.updateRoleInfo(roleId, { blockType, blockReason }); + if (!role) return resResult(STATUS.ROLE_NOT_FOUND); + + await this.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid, [{ roleId, blockType }]); + await this.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId, STATUS.BLOCKED); + await roleLeave(roleId); + } else { + console.log("blockByRecordBattleCheat-防破解查封功能已关闭!!!"); + } + + return; + } + + // 是否可以跳过 + async checkSkip(msg: { battleCode: string }, session: BackendSession) { + const { battleCode } = msg; + let roleId = session.get('roleId'); + + let role = await RoleModel.findByRoleId(roleId, 'warStar vipStartTime'); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + let { warStar, vipStartTime } = role; + + if((!vipStartTime || vipStartTime == 0) && role.lv <= 30) { + return resResult(STATUS.SUCCESS, { + battleCode, + canSkip: false + }); + } + + let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); + if(!battleRecord || battleRecord.roleId != roleId) return resResult(STATUS.BATTLE_NOT_FOUND); + let battleId = battleRecord.battleId; + let dicWar = gameData.war.get(battleId); + if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hasPass = warStar.findIndex(cur => cur.id == battleId) != -1; // 是否首通过 + let canSkip = false; + switch (dicWar.warType) { + case WAR_TYPE.VESTIGE: + case WAR_TYPE.BRANCH_ELITE: + case WAR_TYPE.ACT_DAILY_GK: + case WAR_TYPE.ACT_NEW_HERO_GK: + canSkip = false; + break; + case WAR_TYPE.NORMAL: + canSkip = dicWar.isCity? (dicWar.chapter != 0 && hasPass): true; + break; + case WAR_TYPE.MAIN_ELITE: + case WAR_TYPE.MYSTERY: + canSkip = dicWar.isCity? hasPass: true; + break; + case WAR_TYPE.ACT_TREASURE_HUNT: + case WAR_TYPE.ACT_SELF_SHOP: + case WAR_TYPE.TOWER: + case WAR_TYPE.LADDER: + case WAR_TYPE.GUILD_TRAIN: + case WAR_TYPE.PVP: + case WAR_TYPE.DAILY: + case WAR_TYPE.EVENT: + case WAR_TYPE.EXPEDITION: + case WAR_TYPE.GVG_VESTIGE: + case WAR_TYPE.GVG_BATTLE: + case WAR_TYPE.ROUGE: + case WAR_TYPE.FRIEND_BATTLE: + canSkip = true; + break; + } + + + return resResult(STATUS.SUCCESS, { + battleCode, canSkip + }); + } +} + diff --git a/game-server/app/servers/battle/handler/pvpHandler.ts b/game-server/app/servers/battle/handler/pvpHandler.ts index 23cc33b78..1ff960a8f 100644 --- a/game-server/app/servers/battle/handler/pvpHandler.ts +++ b/game-server/app/servers/battle/handler/pvpHandler.ts @@ -1,929 +1,930 @@ -import { WAR_TYPE } from './../../../consts/constModules/battleConst'; - -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { findIndex } from 'underscore'; -import { gameData, getPvpBoxBySeasonNumAndIndex } from '../../../pubUtils/data'; -import { refreshEnemies, getEnemies, refChallengeCnt, generPVPOppRecInfo, generMyRecInfo, sendLastSeasonRewardIfNotSent, refreshRefOppCnt, generPvpLineupCe, calLineupScore, checkPvpSeasonIsStart, checkPvpSeasonIsSummit, getPvpSeasonStatus, checkPvpSeasonIsWaiting, refreshBuyChallengeCnt } from '../../../services/pvpService'; -import { RoleModel, RoleType } from '../../../db/Role'; -import { STATUS } from '../../../consts/statusCode'; -import { resResult, genCode, checkRoleIsRobot, robotIdComBack, parseGoodStr } from '../../../pubUtils/util'; -import { PvpDefenseModel, pvpUpdateInter } from '../../../db/PvpDefense'; -import { PvpSeasonResultModel } from '../../../db/PvpSeasonResult'; -import { Rank } from '../../../services/rankService'; -import { checkTask, checkTaskInPvpEnd } from '../../../services/task/taskService'; -import { Attack, Combo, Defense, DefenseHero, PvpDataReturn, pvpSaveDataReturn } from '../../../domain/battleField/pvp'; -import { DEBUG_MAGIC_WORD, FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, LINEUP_NUM, REDIS_KEY, TASK_TYPE } from '../../../consts'; -import { PVP } from '../../../pubUtils/dicParam'; -import { addItems, getGoldObject, handleCost, unlockFigure } from '../../../services/role/rewardService'; -import { pick } from "underscore"; -import { HeroModel } from '../../../db/Hero'; -import PvpHistoryOpp, { PvpHistoryOppModel, PvpHistoryOppType } from '../../../db/PvpHistoryOpp'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { PvpRecordModel, PvpRecordParam, PvpRecordType } from '../../../db/PvpRecord'; -import { pvpEndParamInter } from '../../../pubUtils/interface'; -import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; -import { getRemoteRplPrefix, getRemoteRplFilePath } from '../../../pubUtils/battleUtils'; -import { PlayerDetail, PlayerDetailHero } from '../../../domain/battleField/guild'; -import { PvpSaveDataModel } from '../../../db/PvpSaveData'; -import { PVPConfigModel } from '../../../db/PvpConfig'; -import { getAllServerName, getServerName } from '../../../services/redisService'; -import { RoleRankInfo } from '../../../domain/rank'; -import { isHeroHidden } from '../../../services/dataService'; -import { getPVPGroupIdOfServer } from '../../../services/serverService'; -import { getBattleRecordParam } from '../../../services/normalBattleService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new PvpHandler(app); -} - -export class PvpHandler { - constructor(private app: Application) { - } - - //1获取主界面 - async getData(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonStartTime: number = this.app.get('pvpSeasonStartTime'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let seasonRewardTime: number = this.app.get('pvpSeasonRewardTime'); - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if(!pvpDefense) { - let role = await RoleModel.findByRoleId(roleId); - pvpDefense = await PvpDefenseModel.createPvpDefense(seasonNum, { serverId: role.serverId, roleId: role.roleId, roleName: role.roleName, role: role._id }); - } else { - // 如果没有发过,将上赛季的奖励发下 - pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense); - } - - let update: pvpUpdateInter = { }; - let result = new PvpDataReturn(); // 返回对象 - // 刷新次数 - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - if(refChallengeObj.hasChanged) { - update = { ...update, ...refChallengeObj } - } - let refOppObj = refreshRefOppCnt(pvpDefense); - // 每天首次打开要刷掉对手 - if(refOppObj.shouldRefOpp) { - if(pvpDefense.attack) { - let role = pvpDefense.role; - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); - update.oppPlayers = oppPlayers; - } - update = { ...update, ...refOppObj } - } - - if (refreshBuyChallengeCnt(pvpDefense.buyChallengeTime)) { - update = { ...update, buyChallengeCnt: 0, buyChallengeTime: Date.now() }; - } - - if(Object.keys(update).length > 0) { - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); - } - - result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); - result.setPvpDefense(pvpDefense); - result.calHasSaveDefense(); - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - // 赛季结算 - let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId); - if (!!pvpSeasonResult && !!pvpSeasonResult.show) { - result.setPvpSeasonResult(pvpSeasonResult); - await PvpSeasonResultModel.setShow(roleId); - } - // 排行榜 - let myRank = await r.getMyRank({ roleId });//去redis中获取排名 - result.setMyRank(myRank); - - return resResult(STATUS.SUCCESS, result); - } - - // 刷新对手 - async refreshOppPlayer(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - if(!pvpDefense.attack) return resResult(STATUS.PVP_NOT_SET_ATTACK); - - // 刷新次数及消耗 - let refOppObj = refreshRefOppCnt(pvpDefense); - if (refOppObj.refOppCnt >= gameData.maxPvpRefreshCnt.max) { - return resResult(STATUS.PVP_REFRESH_CNT_REACH_MAX); - } - - let costResult = await handleCost(roleId, sid, refOppObj.consume, ITEM_CHANGE_REASON.PVP_REFRESH_OPP); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - refOppObj.refOppCnt ++; - - // 刷新对手 - let role = pvpDefense.role; - let seasonNum: number = this.app.get('pvpSeasonNum'); - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); - - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers, ...refOppObj }); - - let result = new PvpDataReturn(); // 返回对象 - result.setPvpDefense(pvpDefense); - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - - return resResult(STATUS.SUCCESS, pick(result, ['oppPlayers', 'refOppCnt', 'buyAttackCnt', 'setAttackCnt'])); - } - - // 获取对手阵容具体信息 - async getOppPlayer(msg: { roleId: string }, session: BackendSession) { - let roleId = session.get('roleId'); - - if(!checkPvpSeasonIsStart()) { - return resResult(STATUS.PVP_SEASON_NOT_OPEN); - } - let oppoRoleId = msg.roleId; - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - let { oppPlayers } = pvpDefense; - - let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId); - if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); - - let pvpHistoryOpp = curOpp.oppDef; - - return resResult(STATUS.SUCCESS, { roleId: pvpHistoryOpp.oppRoleId, ...pick(pvpHistoryOpp, ['pos', 'title', 'warId', 'buff', 'heroes', 'combo']) }); - } - - - // 开战 - async pvpStart(msg: { warId: number, roleId: string }, session: BackendSession) { - const { warId, roleId: oppRoleId } = msg; - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - - let warInfo = gameData.war.get(warId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - const role = await RoleModel.findByRoleId(roleId, null, true); - if(!role || role.lv < 50) return resResult(STATUS.PVP_NOT_OPEN); - - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - // 检查挑战次数 - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let { challengeCnt, challengeRefTime } = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - if (challengeCnt == 0) { - return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH); - } - let curOpp = pvpDefense.oppPlayers.find(cur => cur.roleId == oppRoleId); - if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND) - - const battleCode = genCode(8); // 关卡唯一值 - let heroes = pvpDefense.attack.heroes.map(cur => cur.actorId); - - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId: warId, - status: 0, - warName: warInfo.gk_name, - warType: warInfo.warType, - record: { heroes, pos: curOpp.pos, oppRoleId, pvpSeasonNum: seasonNum } - } - }, true); - await checkTask(serverId, roleId, sid, TASK_TYPE.PVP); - // 战报记录 - await PvpRecordModel.createRec(roleId, robotIdComBack(oppRoleId), battleCode); - - // 对手记录更新 - await PvpHistoryOppModel.setStatus(curOpp.oppDef.toString(), 1); - - let update: pvpUpdateInter = { - oppBeforePlayers: pvpDefense.oppPlayers - }; - // 刷新对手 - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score ,pvpDefense.attack.score, pvpDefense.attack.pLv||1); - update.oppPlayers = oppPlayers; - - // 减少挑战次数 - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - refChallengeObj.challengeCnt--; - update = {...update, ...refChallengeObj}; - - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); - - let result = new PvpDataReturn(); // 返回对象 - result.setPvpDefense(pvpDefense); - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - - return resResult(STATUS.SUCCESS, { - battleCode, - ...pick(result, ['oppPlayers', 'challengeCnt', 'challengeRefTime']) - }); - } - - // 结算 - async pvpEnd(msg: { battleCode: string, isSuccess: boolean, myHeroes: pvpEndParamInter[], oppHeroes: pvpEndParamInter[], round: number }, session: BackendSession) { - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - const serverId = session.get('serverId'); - - const { battleCode, isSuccess, myHeroes, oppHeroes, round } = msg; - - const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); - if (!BattleRecord || BattleRecord.status != 0) { - return resResult(STATUS.BATTLE_STATUS_WRONG); - } - - let { record: { heroes: dbHeroes, oppRoleId, pos, pvpSeasonNum }, createdAt } = BattleRecord; - - let flag = 1; // 对比hero信息 - for (let { hid } of myHeroes) { - if (dbHeroes.indexOf(hid) == -1) flag = 0; - } - if (!flag) return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); - - // 更新军功 - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - let { hisWinStreakNum = 0 } = pvpDefense; - - let update: pvpUpdateInter = {}; - - const role = await RoleModel.findByRoleId(roleId, null, true); - - const myRecInfo = await generMyRecInfo(pvpDefense, role, isSuccess, pos, myHeroes); - let { attackInfo, showHeroScores, updateParam } = myRecInfo - update = { ...update, ...updateParam }; - - let curOpp = pvpDefense.oppBeforePlayers.find(cur => cur.roleId == oppRoleId && cur.pos == pos); - if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); - const defenseInfo = await generPVPOppRecInfo(isSuccess, curOpp, oppHeroes, serverId); - - let seasonNum: number = this.app.get('pvpSeasonNum'); - // 战报记录 - await PvpRecordModel.updateByBattleCode(battleCode, { warId: BattleRecord.battleId, attackInfo, defenseInfo, createTime: nowSeconds(), timeout: seasonNum != pvpSeasonNum }); - - // 更新battleRecord - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { status: isSuccess ? 1 : 2, ...getBattleRecordParam(myHeroes, round) } - }, true); - - if(seasonNum == pvpSeasonNum) { - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); - } - - let result = new PvpDataReturn(); // 返回对象 - result.setPvpDefense(pvpDefense); - - - if(seasonNum == pvpSeasonNum) { - // 加入排行榜 - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpSeasonNum, groupId }); - await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); - let myRank = await r.getMyRank({ roleId }); - result.setMyRank(myRank); - if(defenseInfo && defenseInfo.score > 0) await r.setRankWithRoleInfo(defenseInfo.roleId, defenseInfo.score, pvpDefense.updatedAt.getTime(), null, true); - } - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - - await checkTaskInPvpEnd(serverId, roleId, sid, isSuccess, pvpDefense.heroScores, pvpDefense.seasonWinNum); - if(hisWinStreakNum < pvpDefense.hisWinStreakNum) { - await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]); - } - - return resResult(STATUS.SUCCESS, { - battleCode, isSuccess, - heroScores: showHeroScores, - createdAt: getSeconds(createdAt), - ...pick(result, ['score', 'myRank', 'winStreakNum', 'attack', 'oppPlayers', 'challengeCnt', 'challengeRefTime', 'seasonWinNum']) - }); - } - - async buyAttackCnt(msg: { count: number }, session: BackendSession) { - let { count } = msg; - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let seasonNum: number = this.app.get('pvpSeasonNum'); - - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - - // 次数 - let refOppObj = refreshRefOppCnt(pvpDefense); - if(refOppObj.buyAttackCnt + count > PVP.PVP_BUY_SET_ATTACK_CNT) { - return resResult(STATUS.PVP_BUY_ATTACK_CNT_NOT_ENOUGH); - } - refOppObj.buyAttackCnt += count; - - let gold = getGoldObject(PVP.PVP_SET_ATTACK_CNT_GOLD * count); - let costResult = await handleCost(roleId, sid, [gold], ITEM_CHANGE_REASON.PVP_BUY_ATTACK_CNT); - if(!costResult) return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); - - let update: pvpUpdateInter = { ...refOppObj }; - - // 更新挑战阵容 - if(refOppObj.shouldRefOpp) { - if(pvpDefense.attack) { - let role = await RoleModel.findByRoleId(roleId); - let seasonNum: number = this.app.get('pvpSeasonNum'); - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); - update.oppPlayers = oppPlayers; - } - } - // 保存 - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); - // 返回 - let result = new PvpDataReturn(); - result.setPvpDefense(pvpDefense); - let pickParam = ['buyAttackCnt', 'setAttackCnt', 'refOppCnt']; - if(refOppObj.shouldRefOpp) { - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - pickParam.push('oppPlayers'); - } - - return resResult(STATUS.SUCCESS, pick(result, pickParam)); - } - - async saveAttack(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { - let { heroes } = msg; - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - - // 次数 - let refOppObj = refreshRefOppCnt(pvpDefense); - if(refOppObj.setAttackCnt >= PVP.PVP_SET_ATTACK_FREE_CNT + refOppObj.buyAttackCnt) { - return resResult(STATUS.PVP_SET_ATTACK_CNT_NOT_ENOUGH); - } - if(!!pvpDefense.attack) { - refOppObj.setAttackCnt ++; - } - - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - // 更新挑战阵容 - let scores: number[] = []; - for(let { actorId, subHid } of heroes) { - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); - if(heroScore) { - scores.push(heroScore.score); - } - let dicHero = gameData.hero.get(actorId); - if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); - if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); - } - let attack = new Attack(heroes, scores, pvpDefense.heroScores); - let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); - // 刷对手 - let role = pvpDefense.role; - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, attack?.score||0, attack?.pLv||1); - // 保存 - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refOppObj, ...refChallengeObj, attack, oppPlayers, lineupCe }); - // 返回 - let result = new PvpDataReturn(); - result.setPvpDefense(pvpDefense); - - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - - return resResult(STATUS.SUCCESS, pick(result, ['attack', 'oppPlayers', 'buyAttackCnt', 'setAttackCnt', 'challengeCnt', 'challengeRefTime'])); - } - - - // 只保存副将 - async saveAttackSub(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { - let { heroes } = msg; - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - - // 更新挑战阵容 - let oldAttack = pvpDefense.attack?.heroes||[]; - let scores: number[] = []; - for(let { actorId, order, subHid } of heroes) { - let oldData = oldAttack.find(cur => cur.actorId == actorId); - if(!oldData || oldData.order != order) return resResult(STATUS.PVP_CAN_NOT_CHANGE_HERO); - - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); - if(heroScore) { - scores.push(heroScore.score); - } - let dicHero = gameData.hero.get(actorId); - if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); - if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); - } - let attack = new Attack(heroes, scores, pvpDefense.heroScores); - let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); - // 保存 - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { attack, lineupCe }); - // 返回 - let result = new PvpDataReturn(); - result.setPvpDefense(pvpDefense); - - return resResult(STATUS.SUCCESS, pick(result, ['attack'])); - } - - - // 获取存档列表 - async getSaveData(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - - let pvpConfig = await PVPConfigModel.findCurPVPConfig(); - if(!pvpConfig) return resResult(STATUS.PVP_SEASON_NOT_OPEN); - - let saveDatas = await PvpSaveDataModel.findByRoleId(roleId); - - let list: pvpSaveDataReturn[] = []; - for(let warId of (pvpConfig.warIds||[])) { - let dicWar = gameData.war.get(warId); - if(dicWar && dicWar.selectView == 1) { - let data = new pvpSaveDataReturn(warId); - let curSaveData = saveDatas.find(cur => cur.warId == warId); - data.setUserSaveData(curSaveData); - if(pvpDefense.defense?.warId == warId) { - data.setAsUsing(); - } - list.push(data); - } - } - return resResult(STATUS.SUCCESS, { list }); - } - - //3. 保存防守阵容 - async saveDefense(msg: { heroes: { actorId: number, dataId: number, order: number, ai: number, subHid?: number }[], warId: number, buff: number, combo: Combo[] }, session: BackendSession) { - let { heroes, warId, buff, combo } = msg; - let roleId = session.get('roleId'); - if (heroes.length > LINEUP_NUM || heroes.length <= 0) { - return resResult(STATUS.WRONG_PARMS); - } - if(checkPvpSeasonIsSummit()) { - return resResult(STATUS.PVP_CAN_NOT_SAVE_DEFENSE); - } - - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - // 刷新次数 - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - // 更新防守阵容 - let scores: number[] = [], heroIdMap = new Map(), hids: number[] = []; - for(let { actorId, subHid } of heroes) { - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - let dicHero = gameData.hero.get(actorId); - if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); - if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); - - let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); - if(heroScore) { - scores.push(heroScore.score); - } - // 记录hero的objectId,用于存defense.heroes.hero - if(pvpDefense.defense && pvpDefense.defense.heroes) { - let heroInDefense = pvpDefense.defense.heroes.find(cur => cur.actorId == actorId); - if(heroInDefense) { - heroIdMap.set(actorId, heroInDefense.hero); - } else { - hids.push(actorId); - } - } else { - hids.push(actorId); - } - } - - let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true); - for(let hero of dbHeroes) { - heroIdMap.set(hero.hid, hero._id); - } - - let defenseHeroes = heroes.map(cur => { - return new DefenseHero(cur, heroIdMap.get(cur.actorId)); - }); - let defense = new Defense(defenseHeroes, scores, warId, buff, combo, pvpDefense.heroScores); - let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, pvpDefense.attack?.heroes??[], defense.heroes, dbHeroes); - await PvpSaveDataModel.createSaveData(roleId, warId, buff, defenseHeroes); - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refChallengeObj, defense, lineupCe, hasDefense: true, seasonNum }); - // 返回 - let result = new PvpDataReturn(); - result.setPvpDefense(pvpDefense); - - return resResult(STATUS.SUCCESS, {...pick(result, ['defense', 'challengeCnt', 'challengeRefTime']), hasSaveDefense: true}); - } - - - //8. 排行榜 - async getRank(msg: {}, session: BackendSession) { - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let seasonNum: number = this.app.get('pvpSeasonNum'); - if(checkPvpSeasonIsWaiting()) { // 休赛期 - seasonNum ++; - } - - let serverNames = await getAllServerName(); - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - r.setGenerFieldsFun(function (param: RoleRankInfo) { - let { serverId } = param; - return { ...param, serverName: serverNames[serverId]||'无' }; - }); - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); - - if (!myRank) { - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - - myRank = await r.generMyRankWithRole(roleId, pvpDefense.score, getSeconds(pvpDefense.refDaily)); - } - - return resResult(STATUS.SUCCESS, { ranks, myRank }); - } - - //2.5. 获取对手详细信息(排行榜,战报,阵容查看) - async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let { roleId: oppoRoleId } = msg; - let isRobot = checkRoleIsRobot(oppoRoleId); - - let result: PlayerDetail; - - if (isRobot) { // 如果是机器人,从自己的pvpDefense中寻找 - let pvpHistoryOpp = await PvpHistoryOppModel.findByRoleIdAndOppId(roleId, oppoRoleId); - if (!pvpHistoryOpp) { - return resResult(STATUS.PVP_ROLE_NOT_FOUND); - } - - let heroes = new Array(); - for (let hero of pvpHistoryOpp.heroes) { - let newHero = new PlayerDetailHero(); - newHero.setPvpHeroInfo(hero); - newHero.setIsDefense(true); - heroes.push(newHero); - } - for (let hero of pvpHistoryOpp.otherHeroes) { - let newHero = new PlayerDetailHero(); - newHero.setPvpHeroInfo(hero); - newHero.setIsDefense(false); - heroes.push(newHero); - } - result = new PlayerDetail(pvpHistoryOpp.oppRoleId, heroes, pvpHistoryOpp.rankLv); - result.setRobot(pvpHistoryOpp); - if(pvpHistoryOpp.isRobot) { - result.setServerName(await getServerName(serverId)); - } else { - let role = await RoleModel.findByRoleId(robotIdComBack(oppoRoleId), 'serverId'); - result.setServerName(await getServerName(role.serverId)); - } - } else { // 查询对方pvpDefense - let pvpDefense = await PvpDefenseModel.findByRoleId(oppoRoleId); - let dbHeroes = await HeroModel.findByRole(oppoRoleId); - let role = await RoleModel.findByRoleId(oppoRoleId); - - let heroes = new Array(); - for (let dbHero of dbHeroes) { - let hero = new PlayerDetailHero(); - hero.setByDbHero(dbHero); - hero.setPvpDefense(pvpDefense); - heroes.push(hero); - } - heroes.sort((a, b) => b.score - a.score); - let seasonNum: number = this.app.get('pvpSeasonNum'); - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let rank = await r.getMyRank({ roleId: oppoRoleId });//去redis中获取排名 - - result = new PlayerDetail(oppoRoleId, heroes, rank); - result.setPlayer(role); - result.setPvpDefense(pvpDefense); - result.setServerName(await getServerName(role.serverId)); - } - - return resResult(STATUS.SUCCESS, result); - } - - //7. 领取巅峰之路奖励 - async receiveBox(msg: { id: number }, session: BackendSession) { - let { id } = msg; - let roleId = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId = session.get('serverId'); - let roleName = session.get('roleName'); - - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let { seasonWinNum, receivedBox, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - let dicPvpBox = getPvpBoxBySeasonNumAndIndex(seasonNum, id); - if(!dicPvpBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if (seasonWinNum < dicPvpBox.winTimes) { - return resResult(STATUS.PVP_NOT_REACH_BOX_SCORE); - } - if (receivedBox.indexOf(id) != -1) { - return resResult(STATUS.PVP_BOX_IS_GOT); - } - receivedBox.push(id); - let { challengeCnt, challengeRefTime } = await refChallengeCnt(lastChallengeCnt, lastChallengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - await PvpDefenseModel.updateInfo(roleId, { receivedBox, challengeCnt, challengeRefTime }); - let result = await addItems(roleId, roleName, sid, dicPvpBox.reward, ITEM_CHANGE_REASON.PVP_BOX_REWARD); - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_RECEIVE_BOX); - return resResult(STATUS.SUCCESS, { goods: result, receivedBox, challengeCnt, challengeRefTime, seasonWinNum }); - } - - //9. 战报 - async getRec(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let pvpRecords = await PvpRecordModel.getRecByRoleId(roleId); - let serverNames = await getAllServerName(); - for(let record of pvpRecords) { - // console.log('#####', record.defenseInfo.serverId, serverNames, serverNames[record.defenseInfo.serverId]) - if(record.defenseInfo) record.defenseInfo['serverName'] = serverNames[record.defenseInfo.serverId]; - if(record.attackInfo) record.attackInfo['serverName'] = serverNames[record.attackInfo.serverId]; - } - - return resResult(STATUS.SUCCESS, { - list: pvpRecords.map(rec => { - const { roleId1, battleCode, hasRpl, remoteUrl } = rec; - const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; - return { ...rec, rplFileUrl }; - }), - rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) - }); - } - - - async buyChallengeCnt(msg: { count: number }, session: BackendSession) { - let { count } = msg; - let roleId = session.get('roleId'); - let sid: string = session.get('sid'); - - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - let isRefreshBuyChallengeCnt = refreshBuyChallengeCnt(pvpDefense.buyChallengeTime); - if (isRefreshBuyChallengeCnt) pvpDefense.buyChallengeCnt = 0; - - if (count + pvpDefense.buyChallengeCnt > PVP.PVP_CHALLENGE_COST_TIMES) { - return resResult(STATUS.PVP_CAN_NOT_BUY_CHALLENGE_CAT); - } - let cost = parseGoodStr(PVP.PVP_CHALLENGE_BUY_TIMES_COST); - for (let cur of cost) { - cur.count = cur.count * count; - } - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.PVP_BUY_CHALLENGE_CNT); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 刷新次数 - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - let challengeCnt = refChallengeObj.challengeCnt + count; - - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, buyChallengeCnt: pvpDefense.buyChallengeCnt + count, buyChallengeTime: Date.now() }); - if (!pvpDefense) return resResult(STATUS.PVP_BUY_CHALLENGE_FAIL) - return resResult(STATUS.SUCCESS, { challengeCnt: pvpDefense.challengeCnt, buyChallengeCnt: pvpDefense.buyChallengeCnt }) - } - - async sweep(msg: { warId: number, oppRoleId: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - const serverId = session.get('serverId'); - - const { warId, oppRoleId } = msg; - let warInfo = gameData.war.get(warId); - if (!warInfo) { - return resResult(STATUS.BATTLE_MISS_INFO); - } - const role = await RoleModel.findByRoleId(roleId, null, true); - if (!role || role.lv < 50) return resResult(STATUS.PVP_NOT_OPEN); - - // let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); - if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); - let { hisWinStreakNum = 0 } = pvpDefense; - - // 检查挑战次数 - let seasonNum: number = this.app.get('pvpSeasonNum'); - let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); - let { challengeCnt, challengeRefTime } = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - if (challengeCnt == 0) { - return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH); - } - - let { attackCe } = PvpDataReturn.getAttackAndDefenseCe(pvpDefense); - let curOpp = pvpDefense.oppPlayers.find(cur => cur.roleId == oppRoleId); - if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); - let oppDef = curOpp.oppDef; - // 战力检测 - if (attackCe <= oppDef.defCe * 2) return resResult(STATUS.PVP_SWEEP_NOT_CE); - - // 对手记录更新 - await PvpHistoryOppModel.setStatus(oppDef._id.toString(), 1); - - // 战斗记录 - const battleCode = genCode(8) + '_sweep'; // 关卡唯一值 - let heroes = pvpDefense.attack.heroes.map(cur => cur.actorId); - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId: warId, - status: 0, - warName: warInfo.gk_name, - warType: warInfo.warType, - record: { heroes, pos: curOpp.pos, oppRoleId, pvpSeasonNum: seasonNum } - } - }, true); - - let update: pvpUpdateInter = {}; - const myHeroes: pvpEndParamInter[] = heroes.map(hid => { return { hid, damage: 0, heal: 0, underDamage: 0 } }) - const myRecInfo = await generMyRecInfo(pvpDefense, role, true, curOpp.pos, myHeroes); - let { attackInfo, showHeroScores, updateParam } = myRecInfo; - update = { ...update, ...updateParam }; - - const oppHeroes: pvpEndParamInter[] = oppDef.heroes.map(cur => { return { hid: cur.actorId, damage: 0, heal: 0, underDamage: 0 } }) - const defenseInfo = await generPVPOppRecInfo(true, curOpp, oppHeroes, serverId); - update = { ...update, oppBeforePlayers: pvpDefense.oppPlayers }; - - await PvpRecordModel.updateByRec(battleCode, {roleId1:roleId, roleId2:oppRoleId, warId, attackInfo, defenseInfo, createTime: nowSeconds(), timeout: false }); - - // 刷新对手 - let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv || 1); - update.oppPlayers = oppPlayers; - - // 减少挑战次数 - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); - refChallengeObj.challengeCnt--; - update = { ...update, ...refChallengeObj }; - - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); - - let result = new PvpDataReturn(); // 返回对象 - result.setPvpDefense(pvpDefense); - - // 加入排行榜 - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); - if (defenseInfo && defenseInfo.score > 0) await r.setRankWithRoleInfo(defenseInfo.roleId, defenseInfo.score, pvpDefense.updatedAt.getTime(), null, true); - - let myRank = await r.getMyRank({ roleId }); - result.setMyRank(myRank); - - let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); - result.setOppPlayers(oppPlayersReturn); - - await checkTaskInPvpEnd(serverId, roleId, sid, true, pvpDefense.heroScores, pvpDefense.seasonWinNum); - if (hisWinStreakNum < pvpDefense.hisWinStreakNum) { - await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]); - } - - return resResult(STATUS.SUCCESS, { - battleCode, isSuccess: true, - heroScores: showHeroScores, - createdAt: getSeconds(new Date()), - ...pick(result, ['score', 'myRank', 'winStreakNum', 'attack', 'oppPlayers', 'challengeCnt', 'challengeRefTime', 'seasonWinNum']) - }); - - } - - - - // debug接口 - - - async addRoleScore(msg: { heroScores: Array<{ hid: number, score: number }> }, session: BackendSession) { - let { heroScores: addHeroScores } = msg; - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - let { heroScores, hisScore, attack, defense } = await PvpDefenseModel.findByRoleId(roleId); - let score = 0; - for (let { hid, score: heroScore } of addHeroScores) { - if (heroScore < 0) continue; - let index = findIndex(heroScores, { hid }); - if (index != -1) { - heroScores[index].score = heroScore; - } else { - heroScores.push({ hid, score: heroScore }); - } - } - for (let heroScore of heroScores) { - score += heroScore.score; - } - if (score < 0) { - score = 0; - } - if (hisScore < score) { - hisScore = score; - } - - let newAttack = calLineupScore(attack, heroScores); - let newDefense = calLineupScore(defense, heroScores); - - let pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { score, hisScore, heroScores, attack: newAttack, defense: newDefense }); - const role = await RoleModel.findByRoleId(roleId); - - // 加入排行榜 - let seasonNum: number = this.app.get('pvpSeasonNum'); - let groupId = await getPVPGroupIdOfServer(serverId); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_HERO_SCORE, { heroScores }); - - return resResult(STATUS.SUCCESS, { score, hisScore, heroScores }); - } - - async debugPvpSeasonResetTime(msg: {}, session: BackendSession) { - return resResult(STATUS.DEBUG_FUNCTION_ERR); - } - - async debugAddChallengeCnt(msg: { challengeCnt: number }, session: BackendSession) { - let { challengeCnt } = msg; - let roleId = session.get('roleId'); - if (challengeCnt > PVP.PVP_CHALLENGE_COUNTS) { - challengeCnt = PVP.PVP_CHALLENGE_COUNTS; - } - let { challengeRefTime } = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, challengeRefTime: nowSeconds(), refOppCnt: 0 }); - return resResult(STATUS.SUCCESS, { challengeCnt, challengeRefTime }); - } - - async debugResetRefOppCnt(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await PvpDefenseModel.updateInfo(roleId, { refOppCnt: 0 }); - return resResult(STATUS.SUCCESS); - } - - async debugResetAttackCnt(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await PvpDefenseModel.updateInfo(roleId, { setAttackCnt: 0, buyAttackCnt: 0 }); - return resResult(STATUS.SUCCESS); - } - - async debugResetBox(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - await PvpDefenseModel.updateInfo(roleId, { hisScore: 5000, receivedBox: [] }); - return resResult(STATUS.SUCCESS); - } -} +import { WAR_TYPE } from './../../../consts/constModules/battleConst'; + +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { findIndex } from 'underscore'; +import { gameData, getPvpBoxBySeasonNumAndIndex } from '@pubUtils/data'; +import { refreshEnemies, getEnemies, refChallengeCnt, generPVPOppRecInfo, generMyRecInfo, sendLastSeasonRewardIfNotSent, refreshRefOppCnt, generPvpLineupCe, calLineupScore, checkPvpSeasonIsStart, checkPvpSeasonIsSummit, getPvpSeasonStatus, checkPvpSeasonIsWaiting, refreshBuyChallengeCnt } from '../../../services/pvpService'; +import { RoleModel, RoleType } from '@db/Role'; +import { STATUS } from '@consts/statusCode'; +import { resResult, genCode, checkRoleIsRobot, robotIdComBack, parseGoodStr } from '@pubUtils/util'; +import { PvpDefenseModel, pvpUpdateInter } from '@db/PvpDefense'; +import { PvpSeasonResultModel } from '@db/PvpSeasonResult'; +import { Rank } from '../../../services/rankService'; +import { checkTask, checkTaskInPvpEnd } from '../../../services/task/taskService'; +import { Attack, Combo, Defense, DefenseHero, PvpDataReturn, pvpSaveDataReturn } from '@domain/battleField/pvp'; +import { DEBUG_MAGIC_WORD, FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, LINEUP_NUM, REDIS_KEY, TASK_TYPE } from '../../../consts'; +import { PVP } from '@pubUtils/dicParam'; +import { addItems, getGoldObject, handleCost, unlockFigure } from '../../../services/role/rewardService'; +import { pick } from "underscore"; +import { HeroModel } from '@db/Hero'; +import PvpHistoryOpp, { PvpHistoryOppModel, PvpHistoryOppType } from '@db/PvpHistoryOpp'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { PvpRecordModel, PvpRecordParam, PvpRecordType } from '@db/PvpRecord'; +import { pvpEndParamInter } from '@pubUtils/interface'; +import { getSeconds, nowSeconds } from '@pubUtils/timeUtil'; +import { getRemoteRplPrefix, getRemoteRplFilePath } from '@pubUtils/battleUtils'; +import { PlayerDetail, PlayerDetailHero } from '@domain/battleField/guild'; +import { PvpSaveDataModel } from '@db/PvpSaveData'; +import { PVPConfigModel } from '@db/PvpConfig'; +import { getAllServerName, getServerName } from '../../../services/redisService'; +import { RoleRankInfo } from '@domain/rank'; +import { isHeroHidden } from '../../../services/dataService'; +import { getPVPGroupIdOfServer } from '../../../services/serverService'; +import { getBattleRecordParam } from '../../../services/normalBattleService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new PvpHandler(app); +} + +export class PvpHandler { + constructor(private app: Application) { + } + + //1获取主界面 + async getData(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonStartTime: number = this.app.get('pvpSeasonStartTime'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let seasonRewardTime: number = this.app.get('pvpSeasonRewardTime'); + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if(!pvpDefense) { + let role = await RoleModel.findByRoleId(roleId); + pvpDefense = await PvpDefenseModel.createPvpDefense(seasonNum, { serverId: role.serverId, roleId: role.roleId, roleName: role.roleName, role: role._id }); + } else { + // 如果没有发过,将上赛季的奖励发下 + pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense); + } + + let update: pvpUpdateInter = { }; + let result = new PvpDataReturn(); // 返回对象 + // 刷新次数 + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + if(refChallengeObj.hasChanged) { + update = { ...update, ...refChallengeObj } + } + let refOppObj = refreshRefOppCnt(pvpDefense); + // 每天首次打开要刷掉对手 + if(refOppObj.shouldRefOpp) { + if(pvpDefense.attack) { + let role = pvpDefense.role; + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); + update.oppPlayers = oppPlayers; + } + update = { ...update, ...refOppObj } + } + + if (refreshBuyChallengeCnt(pvpDefense.buyChallengeTime)) { + update = { ...update, buyChallengeCnt: 0, buyChallengeTime: Date.now() }; + } + + if(Object.keys(update).length > 0) { + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); + } + + result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); + result.setPvpDefense(pvpDefense); + result.calHasSaveDefense(); + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + // 赛季结算 + let pvpSeasonResult = await PvpSeasonResultModel.getPvpSeasonResult(roleId); + if (!!pvpSeasonResult && !!pvpSeasonResult.show) { + result.setPvpSeasonResult(pvpSeasonResult); + await PvpSeasonResultModel.setShow(roleId); + } + // 排行榜 + let myRank = await r.getMyRank({ roleId });//去redis中获取排名 + result.setMyRank(myRank); + + return resResult(STATUS.SUCCESS, result); + } + + // 刷新对手 + async refreshOppPlayer(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + if(!pvpDefense.attack) return resResult(STATUS.PVP_NOT_SET_ATTACK); + + // 刷新次数及消耗 + let refOppObj = refreshRefOppCnt(pvpDefense); + if (refOppObj.refOppCnt >= gameData.maxPvpRefreshCnt.max) { + return resResult(STATUS.PVP_REFRESH_CNT_REACH_MAX); + } + + let costResult = await handleCost(roleId, sid, refOppObj.consume, ITEM_CHANGE_REASON.PVP_REFRESH_OPP); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + refOppObj.refOppCnt ++; + + // 刷新对手 + let role = pvpDefense.role; + let seasonNum: number = this.app.get('pvpSeasonNum'); + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); + + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { oppPlayers, ...refOppObj }); + + let result = new PvpDataReturn(); // 返回对象 + result.setPvpDefense(pvpDefense); + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + + return resResult(STATUS.SUCCESS, pick(result, ['oppPlayers', 'refOppCnt', 'buyAttackCnt', 'setAttackCnt'])); + } + + // 获取对手阵容具体信息 + async getOppPlayer(msg: { roleId: string }, session: BackendSession) { + let roleId = session.get('roleId'); + + if(!checkPvpSeasonIsStart()) { + return resResult(STATUS.PVP_SEASON_NOT_OPEN); + } + let oppoRoleId = msg.roleId; + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + let { oppPlayers } = pvpDefense; + + let curOpp = oppPlayers.find(cur => cur.roleId == oppoRoleId); + if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); + + let pvpHistoryOpp = curOpp.oppDef; + + return resResult(STATUS.SUCCESS, { roleId: pvpHistoryOpp.oppRoleId, ...pick(pvpHistoryOpp, ['pos', 'title', 'warId', 'buff', 'heroes', 'combo']) }); + } + + + // 开战 + async pvpStart(msg: { warId: number, roleId: string }, session: BackendSession) { + const { warId, roleId: oppRoleId } = msg; + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + + let warInfo = gameData.war.get(warId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + const role = await RoleModel.findByRoleId(roleId, null, true); + if(!role || role.lv < 50) return resResult(STATUS.PVP_NOT_OPEN); + + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + // 检查挑战次数 + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let { challengeCnt, challengeRefTime } = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + if (challengeCnt == 0) { + return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH); + } + let curOpp = pvpDefense.oppPlayers.find(cur => cur.roleId == oppRoleId); + if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND) + + const battleCode = genCode(8); // 关卡唯一值 + let heroes = pvpDefense.attack.heroes.map(cur => cur.actorId); + + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId: warId, + status: 0, + warName: warInfo.gk_name, + warType: warInfo.warType, + record: { heroes, pos: curOpp.pos, oppRoleId, pvpSeasonNum: seasonNum } + } + }, true); + await checkTask(serverId, roleId, sid, TASK_TYPE.PVP); + // 战报记录 + await PvpRecordModel.createRec(roleId, robotIdComBack(oppRoleId), battleCode); + + // 对手记录更新 + await PvpHistoryOppModel.setStatus(curOpp.oppDef.toString(), 1); + + let update: pvpUpdateInter = { + oppBeforePlayers: pvpDefense.oppPlayers + }; + // 刷新对手 + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score ,pvpDefense.attack.score, pvpDefense.attack.pLv||1); + update.oppPlayers = oppPlayers; + + // 减少挑战次数 + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + refChallengeObj.challengeCnt--; + update = {...update, ...refChallengeObj}; + + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); + + let result = new PvpDataReturn(); // 返回对象 + result.setPvpDefense(pvpDefense); + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + + return resResult(STATUS.SUCCESS, { + battleCode, + ...pick(result, ['oppPlayers', 'challengeCnt', 'challengeRefTime']) + }); + } + + // 结算 + async pvpEnd(msg: { battleCode: string, isSuccess: boolean, myHeroes: pvpEndParamInter[], oppHeroes: pvpEndParamInter[], round: number }, session: BackendSession) { + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + const serverId = session.get('serverId'); + + const { battleCode, isSuccess, myHeroes, oppHeroes, round } = msg; + + const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); + if (!BattleRecord || BattleRecord.status != 0) { + return resResult(STATUS.BATTLE_STATUS_WRONG); + } + + let { record: { heroes: dbHeroes, oppRoleId, pos, pvpSeasonNum }, createdAt } = BattleRecord; + + let flag = 1; // 对比hero信息 + for (let { hid } of myHeroes) { + if (dbHeroes.indexOf(hid) == -1) flag = 0; + } + if (!flag) return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); + + // 更新军功 + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + let { hisWinStreakNum = 0 } = pvpDefense; + + let update: pvpUpdateInter = {}; + + const role = await RoleModel.findByRoleId(roleId, null, true); + + const myRecInfo = await generMyRecInfo(pvpDefense, role, isSuccess, pos, myHeroes); + let { attackInfo, showHeroScores, updateParam } = myRecInfo + update = { ...update, ...updateParam }; + + let curOpp = pvpDefense.oppBeforePlayers.find(cur => cur.roleId == oppRoleId && cur.pos == pos); + if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); + const defenseInfo = await generPVPOppRecInfo(isSuccess, curOpp, oppHeroes, serverId); + + let seasonNum: number = this.app.get('pvpSeasonNum'); + // 战报记录 + await PvpRecordModel.updateByBattleCode(battleCode, { warId: BattleRecord.battleId, attackInfo, defenseInfo, createTime: nowSeconds(), timeout: seasonNum != pvpSeasonNum }); + + // 更新battleRecord + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { status: isSuccess ? 1 : 2, ...getBattleRecordParam(myHeroes, round) } + }, true); + + if(seasonNum == pvpSeasonNum) { + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); + } + + let result = new PvpDataReturn(); // 返回对象 + result.setPvpDefense(pvpDefense); + + + if(seasonNum == pvpSeasonNum) { + // 加入排行榜 + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpSeasonNum, groupId }); + await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); + let myRank = await r.getMyRank({ roleId }); + result.setMyRank(myRank); + if(defenseInfo && defenseInfo.score > 0) await r.setRankWithRoleInfo(defenseInfo.roleId, defenseInfo.score, pvpDefense.updatedAt.getTime(), null, true); + } + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + + await checkTaskInPvpEnd(serverId, roleId, sid, isSuccess, pvpDefense.heroScores, pvpDefense.seasonWinNum); + if(hisWinStreakNum < pvpDefense.hisWinStreakNum) { + await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]); + } + + return resResult(STATUS.SUCCESS, { + battleCode, isSuccess, + heroScores: showHeroScores, + createdAt: getSeconds(createdAt), + ...pick(result, ['score', 'myRank', 'winStreakNum', 'attack', 'oppPlayers', 'challengeCnt', 'challengeRefTime', 'seasonWinNum']) + }); + } + + async buyAttackCnt(msg: { count: number }, session: BackendSession) { + let { count } = msg; + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let seasonNum: number = this.app.get('pvpSeasonNum'); + + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + + // 次数 + let refOppObj = refreshRefOppCnt(pvpDefense); + if(refOppObj.buyAttackCnt + count > PVP.PVP_BUY_SET_ATTACK_CNT) { + return resResult(STATUS.PVP_BUY_ATTACK_CNT_NOT_ENOUGH); + } + refOppObj.buyAttackCnt += count; + + let gold = getGoldObject(PVP.PVP_SET_ATTACK_CNT_GOLD * count); + let costResult = await handleCost(roleId, sid, [gold], ITEM_CHANGE_REASON.PVP_BUY_ATTACK_CNT); + if(!costResult) return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); + + let update: pvpUpdateInter = { ...refOppObj }; + + // 更新挑战阵容 + if(refOppObj.shouldRefOpp) { + if(pvpDefense.attack) { + let role = await RoleModel.findByRoleId(roleId); + let seasonNum: number = this.app.get('pvpSeasonNum'); + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv||1); + update.oppPlayers = oppPlayers; + } + } + // 保存 + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); + // 返回 + let result = new PvpDataReturn(); + result.setPvpDefense(pvpDefense); + let pickParam = ['buyAttackCnt', 'setAttackCnt', 'refOppCnt']; + if(refOppObj.shouldRefOpp) { + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + pickParam.push('oppPlayers'); + } + + return resResult(STATUS.SUCCESS, pick(result, pickParam)); + } + + async saveAttack(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { + let { heroes } = msg; + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + + // 次数 + let refOppObj = refreshRefOppCnt(pvpDefense); + if(refOppObj.setAttackCnt >= PVP.PVP_SET_ATTACK_FREE_CNT + refOppObj.buyAttackCnt) { + return resResult(STATUS.PVP_SET_ATTACK_CNT_NOT_ENOUGH); + } + if(!!pvpDefense.attack) { + refOppObj.setAttackCnt ++; + } + + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + // 更新挑战阵容 + let scores: number[] = []; + for(let { actorId, subHid } of heroes) { + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); + if(heroScore) { + scores.push(heroScore.score); + } + let dicHero = gameData.hero.get(actorId); + if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); + if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); + } + let attack = new Attack(heroes, scores, pvpDefense.heroScores); + let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); + // 刷对手 + let role = pvpDefense.role; + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, attack?.score||0, attack?.pLv||1); + // 保存 + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refOppObj, ...refChallengeObj, attack, oppPlayers, lineupCe }); + // 返回 + let result = new PvpDataReturn(); + result.setPvpDefense(pvpDefense); + + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers||[], pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + + return resResult(STATUS.SUCCESS, pick(result, ['attack', 'oppPlayers', 'buyAttackCnt', 'setAttackCnt', 'challengeCnt', 'challengeRefTime'])); + } + + + // 只保存副将 + async saveAttackSub(msg: { heroes: { actorId: number, order: number, subHid: number }[] }, session: BackendSession) { + let { heroes } = msg; + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + + // 更新挑战阵容 + let oldAttack = pvpDefense.attack?.heroes||[]; + let scores: number[] = []; + for(let { actorId, order, subHid } of heroes) { + let oldData = oldAttack.find(cur => cur.actorId == actorId); + if(!oldData || oldData.order != order) return resResult(STATUS.PVP_CAN_NOT_CHANGE_HERO); + + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); + if(heroScore) { + scores.push(heroScore.score); + } + let dicHero = gameData.hero.get(actorId); + if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); + if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); + } + let attack = new Attack(heroes, scores, pvpDefense.heroScores); + let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, attack.heroes, pvpDefense.defense?.heroes??[], []); + // 保存 + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { attack, lineupCe }); + // 返回 + let result = new PvpDataReturn(); + result.setPvpDefense(pvpDefense); + + return resResult(STATUS.SUCCESS, pick(result, ['attack'])); + } + + + // 获取存档列表 + async getSaveData(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + + let pvpConfig = await PVPConfigModel.findCurPVPConfig(); + if(!pvpConfig) return resResult(STATUS.PVP_SEASON_NOT_OPEN); + + let saveDatas = await PvpSaveDataModel.findByRoleId(roleId); + + let list: pvpSaveDataReturn[] = []; + for(let warId of (pvpConfig.warIds||[])) { + let dicWar = gameData.war.get(warId); + if(dicWar && dicWar.selectView == 1) { + let data = new pvpSaveDataReturn(warId); + let curSaveData = saveDatas.find(cur => cur.warId == warId); + data.setUserSaveData(curSaveData); + if(pvpDefense.defense?.warId == warId) { + data.setAsUsing(); + } + list.push(data); + } + } + return resResult(STATUS.SUCCESS, { list }); + } + + //3. 保存防守阵容 + async saveDefense(msg: { heroes: { actorId: number, dataId: number, order: number, ai: number, subHid?: number }[], warId: number, buff: number, combo: Combo[] }, session: BackendSession) { + let { heroes, warId, buff, combo } = msg; + let roleId = session.get('roleId'); + if (heroes.length > LINEUP_NUM || heroes.length <= 0) { + return resResult(STATUS.WRONG_PARMS); + } + if(checkPvpSeasonIsSummit()) { + return resResult(STATUS.PVP_CAN_NOT_SAVE_DEFENSE); + } + + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if(!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + // 刷新次数 + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + // 更新防守阵容 + let scores: number[] = [], heroIdMap = new Map(), hids: number[] = []; + for(let { actorId, subHid } of heroes) { + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + let dicHero = gameData.hero.get(actorId); + if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); + if(subHid && heroes.findIndex(hero => hero.actorId == subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE); + + let heroScore = pvpDefense.heroScores.find(cur => cur.hid == actorId); + if(heroScore) { + scores.push(heroScore.score); + } + // 记录hero的objectId,用于存defense.heroes.hero + if(pvpDefense.defense && pvpDefense.defense.heroes) { + let heroInDefense = pvpDefense.defense.heroes.find(cur => cur.actorId == actorId); + if(heroInDefense) { + heroIdMap.set(actorId, heroInDefense.hero); + } else { + hids.push(actorId); + } + } else { + hids.push(actorId); + } + } + + let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true); + for(let hero of dbHeroes) { + heroIdMap.set(hero.hid, hero._id); + } + + let defenseHeroes = heroes.map(cur => { + return new DefenseHero(cur, heroIdMap.get(cur.actorId)); + }); + let defense = new Defense(defenseHeroes, scores, warId, buff, combo, pvpDefense.heroScores); + let lineupCe = await generPvpLineupCe(roleId, pvpDefense.lineupCe, pvpDefense.attack?.heroes??[], defense.heroes, dbHeroes); + await PvpSaveDataModel.createSaveData(roleId, warId, buff, defenseHeroes); + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { ...refChallengeObj, defense, lineupCe, hasDefense: true, seasonNum }); + // 返回 + let result = new PvpDataReturn(); + result.setPvpDefense(pvpDefense); + + return resResult(STATUS.SUCCESS, {...pick(result, ['defense', 'challengeCnt', 'challengeRefTime']), hasSaveDefense: true}); + } + + + //8. 排行榜 + async getRank(msg: {}, session: BackendSession) { + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let seasonNum: number = this.app.get('pvpSeasonNum'); + if(checkPvpSeasonIsWaiting()) { // 休赛期 + seasonNum ++; + } + + let serverNames = await getAllServerName(); + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + r.setGenerFieldsFun(function (param: RoleRankInfo) { + let { serverId } = param; + return { ...param, serverName: serverNames[serverId]||'无' }; + }); + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); + + if (!myRank) { + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + + myRank = await r.generMyRankWithRole(roleId, pvpDefense.score, getSeconds(pvpDefense.refDaily)); + } + + return resResult(STATUS.SUCCESS, { ranks, myRank }); + } + + //2.5. 获取对手详细信息(排行榜,战报,阵容查看) + async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let { roleId: oppoRoleId } = msg; + let isRobot = checkRoleIsRobot(oppoRoleId); + + let result: PlayerDetail; + + if (isRobot) { // 如果是机器人,从自己的pvpDefense中寻找 + let pvpHistoryOpp = await PvpHistoryOppModel.findByRoleIdAndOppId(roleId, oppoRoleId); + if (!pvpHistoryOpp) { + return resResult(STATUS.PVP_ROLE_NOT_FOUND); + } + + let heroes = new Array(); + for (let hero of pvpHistoryOpp.heroes) { + let newHero = new PlayerDetailHero(); + newHero.setPvpHeroInfo(hero); + newHero.setIsDefense(true); + heroes.push(newHero); + } + for (let hero of pvpHistoryOpp.otherHeroes) { + let newHero = new PlayerDetailHero(); + newHero.setPvpHeroInfo(hero); + newHero.setIsDefense(false); + heroes.push(newHero); + } + result = new PlayerDetail(pvpHistoryOpp.oppRoleId, heroes, pvpHistoryOpp.rankLv); + result.setRobot(pvpHistoryOpp); + if(pvpHistoryOpp.isRobot) { + result.setServerName(await getServerName(serverId)); + } else { + let role = await RoleModel.findByRoleId(robotIdComBack(oppoRoleId), 'serverId'); + result.setServerName(await getServerName(role.serverId)); + } + } else { // 查询对方pvpDefense + let pvpDefense = await PvpDefenseModel.findByRoleId(oppoRoleId); + let dbHeroes = await HeroModel.findByRole(oppoRoleId); + let role = await RoleModel.findByRoleId(oppoRoleId); + + let heroes = new Array(); + for (let dbHero of dbHeroes) { + let hero = new PlayerDetailHero(); + hero.setByDbHero(dbHero); + hero.setPvpDefense(pvpDefense); + heroes.push(hero); + } + heroes.sort((a, b) => b.score - a.score); + let seasonNum: number = this.app.get('pvpSeasonNum'); + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let rank = await r.getMyRank({ roleId: oppoRoleId });//去redis中获取排名 + + result = new PlayerDetail(oppoRoleId, heroes, rank); + result.setPlayer(role); + result.setPvpDefense(pvpDefense); + result.setServerName(await getServerName(role.serverId)); + } + + return resResult(STATUS.SUCCESS, result); + } + + //7. 领取巅峰之路奖励 + async receiveBox(msg: { id: number }, session: BackendSession) { + let { id } = msg; + let roleId = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId = session.get('serverId'); + let roleName = session.get('roleName'); + + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let { seasonWinNum, receivedBox, challengeCnt: lastChallengeCnt, challengeRefTime: lastChallengeRefTime } = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + let dicPvpBox = getPvpBoxBySeasonNumAndIndex(seasonNum, id); + if(!dicPvpBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if (seasonWinNum < dicPvpBox.winTimes) { + return resResult(STATUS.PVP_NOT_REACH_BOX_SCORE); + } + if (receivedBox.indexOf(id) != -1) { + return resResult(STATUS.PVP_BOX_IS_GOT); + } + receivedBox.push(id); + let { challengeCnt, challengeRefTime } = await refChallengeCnt(lastChallengeCnt, lastChallengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + await PvpDefenseModel.updateInfo(roleId, { receivedBox, challengeCnt, challengeRefTime }); + let result = await addItems(roleId, roleName, sid, dicPvpBox.reward, ITEM_CHANGE_REASON.PVP_BOX_REWARD); + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_RECEIVE_BOX); + return resResult(STATUS.SUCCESS, { goods: result, receivedBox, challengeCnt, challengeRefTime, seasonWinNum }); + } + + //9. 战报 + async getRec(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let pvpRecords = await PvpRecordModel.getRecByRoleId(roleId); + let serverNames = await getAllServerName(); + for(let record of pvpRecords) { + // console.log('#####', record.defenseInfo.serverId, serverNames, serverNames[record.defenseInfo.serverId]) + if(record.defenseInfo) record.defenseInfo['serverName'] = serverNames[record.defenseInfo.serverId]; + if(record.attackInfo) record.attackInfo['serverName'] = serverNames[record.attackInfo.serverId]; + } + + return resResult(STATUS.SUCCESS, { + list: pvpRecords.map(rec => { + const { roleId1, battleCode, hasRpl, remoteUrl } = rec; + const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; + return { ...rec, rplFileUrl }; + }), + rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) + }); + } + + + async buyChallengeCnt(msg: { count: number }, session: BackendSession) { + let { count } = msg; + let roleId = session.get('roleId'); + let sid: string = session.get('sid'); + + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + let isRefreshBuyChallengeCnt = refreshBuyChallengeCnt(pvpDefense.buyChallengeTime); + if (isRefreshBuyChallengeCnt) pvpDefense.buyChallengeCnt = 0; + + if (count + pvpDefense.buyChallengeCnt > PVP.PVP_CHALLENGE_COST_TIMES) { + return resResult(STATUS.PVP_CAN_NOT_BUY_CHALLENGE_CAT); + } + let cost = parseGoodStr(PVP.PVP_CHALLENGE_BUY_TIMES_COST); + for (let cur of cost) { + cur.count = cur.count * count; + } + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.PVP_BUY_CHALLENGE_CNT); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 刷新次数 + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + let challengeCnt = refChallengeObj.challengeCnt + count; + + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, buyChallengeCnt: pvpDefense.buyChallengeCnt + count, buyChallengeTime: Date.now() }); + if (!pvpDefense) return resResult(STATUS.PVP_BUY_CHALLENGE_FAIL) + return resResult(STATUS.SUCCESS, { challengeCnt: pvpDefense.challengeCnt, buyChallengeCnt: pvpDefense.buyChallengeCnt }) + } + + async sweep(msg: { warId: number, oppRoleId: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + const serverId = session.get('serverId'); + + const { warId, oppRoleId } = msg; + let warInfo = gameData.war.get(warId); + if (!warInfo) { + return resResult(STATUS.BATTLE_MISS_INFO); + } + const role = await RoleModel.findByRoleId(roleId, null, true); + if (!role || role.lv < 50) return resResult(STATUS.PVP_NOT_OPEN); + + // let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + let pvpDefense = await PvpDefenseModel.findByRoleIdIncludeAll(roleId); + if (!pvpDefense) return resResult(STATUS.PVP_NOT_OPEN); + let { hisWinStreakNum = 0 } = pvpDefense; + + // 检查挑战次数 + let seasonNum: number = this.app.get('pvpSeasonNum'); + let seasonEndTime: number = this.app.get('pvpSeasonEndTime'); + let { challengeCnt, challengeRefTime } = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + if (challengeCnt == 0) { + return resResult(STATUS.PVP_CHALLENGE_TIMES_NOT_ENOUGH); + } + + let { attackCe } = PvpDataReturn.getAttackAndDefenseCe(pvpDefense); + let curOpp = pvpDefense.oppPlayers.find(cur => cur.roleId == oppRoleId); + if (!curOpp) return resResult(STATUS.PVP_ROLE_NOT_FOUND); + let oppDef = curOpp.oppDef; + // 战力检测 + if (attackCe <= oppDef.defCe * 2) return resResult(STATUS.PVP_SWEEP_NOT_CE); + + // 对手记录更新 + await PvpHistoryOppModel.setStatus(oppDef._id.toString(), 1); + + // 战斗记录 + const battleCode = genCode(8) + '_sweep'; // 关卡唯一值 + let heroes = pvpDefense.attack.heroes.map(cur => cur.actorId); + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId: warId, + status: 0, + warName: warInfo.gk_name, + warType: warInfo.warType, + record: { heroes, pos: curOpp.pos, oppRoleId, pvpSeasonNum: seasonNum } + } + }, true); + + let update: pvpUpdateInter = {}; + const myHeroes: pvpEndParamInter[] = heroes.map(hid => { return { hid, damage: 0, heal: 0, underDamage: 0 } }) + const myRecInfo = await generMyRecInfo(pvpDefense, role, true, curOpp.pos, myHeroes); + let { attackInfo, showHeroScores, updateParam } = myRecInfo; + update = { ...update, ...updateParam }; + + const oppHeroes: pvpEndParamInter[] = oppDef.heroes.map(cur => { return { hid: cur.actorId, damage: 0, heal: 0, underDamage: 0 } }) + const defenseInfo = await generPVPOppRecInfo(true, curOpp, oppHeroes, serverId); + update = { ...update, oppBeforePlayers: pvpDefense.oppPlayers }; + + await PvpRecordModel.updateByRec(battleCode, {roleId1:roleId, roleId2:oppRoleId, warId, attackInfo, defenseInfo, createTime: nowSeconds(), timeout: false }); + + // 刷新对手 + let oppPlayers = await refreshEnemies(role, seasonNum, pvpDefense.score, pvpDefense.attack.score, pvpDefense.attack.pLv || 1); + update.oppPlayers = oppPlayers; + + // 减少挑战次数 + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId, session.get('vipStartTime')); + refChallengeObj.challengeCnt--; + update = { ...update, ...refChallengeObj }; + + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, update); + + let result = new PvpDataReturn(); // 返回对象 + result.setPvpDefense(pvpDefense); + + // 加入排行榜 + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); + if (defenseInfo && defenseInfo.score > 0) await r.setRankWithRoleInfo(defenseInfo.roleId, defenseInfo.score, pvpDefense.updatedAt.getTime(), null, true); + + let myRank = await r.getMyRank({ roleId }); + result.setMyRank(myRank); + + let oppPlayersReturn = await getEnemies(r, pvpDefense.oppPlayers, pvpDefense.winStreakNum); + result.setOppPlayers(oppPlayersReturn); + + await checkTaskInPvpEnd(serverId, roleId, sid, true, pvpDefense.heroScores, pvpDefense.seasonWinNum); + if (hisWinStreakNum < pvpDefense.hisWinStreakNum) { + await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES, paramWinStreakNum: pvpDefense.hisWinStreakNum }]); + } + + return resResult(STATUS.SUCCESS, { + battleCode, isSuccess: true, + heroScores: showHeroScores, + createdAt: getSeconds(new Date()), + ...pick(result, ['score', 'myRank', 'winStreakNum', 'attack', 'oppPlayers', 'challengeCnt', 'challengeRefTime', 'seasonWinNum']) + }); + + } + + + + // debug接口 + + + async addRoleScore(msg: { heroScores: Array<{ hid: number, score: number }> }, session: BackendSession) { + let { heroScores: addHeroScores } = msg; + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + let { heroScores, hisScore, attack, defense } = await PvpDefenseModel.findByRoleId(roleId); + let score = 0; + for (let { hid, score: heroScore } of addHeroScores) { + if (heroScore < 0) continue; + let index = findIndex(heroScores, { hid }); + if (index != -1) { + heroScores[index].score = heroScore; + } else { + heroScores.push({ hid, score: heroScore }); + } + } + for (let heroScore of heroScores) { + score += heroScore.score; + } + if (score < 0) { + score = 0; + } + if (hisScore < score) { + hisScore = score; + } + + let newAttack = calLineupScore(attack, heroScores); + let newDefense = calLineupScore(defense, heroScores); + + let pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { score, hisScore, heroScores, attack: newAttack, defense: newDefense }); + const role = await RoleModel.findByRoleId(roleId); + + // 加入排行榜 + let seasonNum: number = this.app.get('pvpSeasonNum'); + let groupId = await getPVPGroupIdOfServer(serverId); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + await r.setRankWithRoleInfo(roleId, pvpDefense.score, pvpDefense.updatedAt.getTime(), role); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.PVP_HERO_SCORE, { heroScores }); + + return resResult(STATUS.SUCCESS, { score, hisScore, heroScores }); + } + + async debugPvpSeasonResetTime(msg: {}, session: BackendSession) { + return resResult(STATUS.DEBUG_FUNCTION_ERR); + } + + async debugAddChallengeCnt(msg: { challengeCnt: number }, session: BackendSession) { + let { challengeCnt } = msg; + let roleId = session.get('roleId'); + if (challengeCnt > PVP.PVP_CHALLENGE_COUNTS) { + challengeCnt = PVP.PVP_CHALLENGE_COUNTS; + } + let { challengeRefTime } = await PvpDefenseModel.updateInfoAndInclude(roleId, { challengeCnt, challengeRefTime: nowSeconds(), refOppCnt: 0 }); + return resResult(STATUS.SUCCESS, { challengeCnt, challengeRefTime }); + } + + async debugResetRefOppCnt(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await PvpDefenseModel.updateInfo(roleId, { refOppCnt: 0 }); + return resResult(STATUS.SUCCESS); + } + + async debugResetAttackCnt(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await PvpDefenseModel.updateInfo(roleId, { setAttackCnt: 0, buyAttackCnt: 0 }); + return resResult(STATUS.SUCCESS); + } + + async debugResetBox(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + await PvpDefenseModel.updateInfo(roleId, { hisScore: 5000, receivedBox: [] }); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/rougeHandler.ts b/game-server/app/servers/battle/handler/rougeHandler.ts index 27fc92903..e2166bc18 100644 --- a/game-server/app/servers/battle/handler/rougeHandler.ts +++ b/game-server/app/servers/battle/handler/rougeHandler.ts @@ -1,1327 +1,1328 @@ -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { RougelikeRecordModel } from '../../../db/RougelikeRecord'; -import { genCode, getRandEelmWithWeight, resResult } from '../../../pubUtils/util'; -import { COLLECTION_TYPE, ITEM_CHANGE_REASON, REST_POINT_TYPE, ROUGE_LIKE_CARD_TYPE, ROUGE_LIKE_CHOOSE_REWARD, ROUGE_LIKE_NODE_TYPE, ROUGE_LIKE_STATUS, TASK_ROUGE_CARD_TYPE, TASK_TYPE } from '../../../consts'; -import { Quest, RestPoint, RougelikeRecordDetailModel } from '../../../db/RougelikeRecordDetail'; -import { STATUS } from '../../../consts/statusCode'; -import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from '../../../db/RougelikeCard'; -import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from '../../../db/RougelikeChara'; -import { CollectionReturnParam, CommonCard, CommonChara, RewardInter, RewardOption, RougeDamageInter, SlotCard, layerNode } from '../../../pubUtils/interface'; -import { clone } from 'underscore'; -import { RougelikeScoreModel } from '../../../db/RougelikeScore'; -import { RougelikeTechModel } from '../../../db/RougelikeTech'; -import { RougelikeCollectionModel } from '../../../db/RougelikeCollection'; -import { RougelikeLayerModel, RougelikeLayerType } from '../../../db/RougelikeLayer'; -import { RoleModel } from '../../../db/Role'; -import { gameData } from '../../../pubUtils/data'; -import { chooseNode, getCardCount, getGame, getInitCharaCard, getLayerNodeReward, getLayerRewardOneData, getMap, getMaxHp, getRandomSpirit, getRougeData, repaireSendScoreReward, updateChalleng, updateMaxHp } from '../../../services/battle/rougeService'; -import { checkPreRougeTech, getCurTechData, updateEffectId } from '../../../services/battle/rougeTechService'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { HeroModel } from '../../../db/Hero'; -import { ROUGELIKE } from '../../../pubUtils/dicParam'; -import { HandleAddCard, addSameTypeCollect, addSingleCollect, formateCharasOrCards } from '../../../services/battle/rougeCollectService'; -import { DicRougePassiveCollect } from '../../../pubUtils/dictionary/DicRougePassiveCollect'; -import { DicRougeHolyCard } from '../../../pubUtils/dictionary/DicRougeHolyCard'; -import { DicRougeSkillCard } from '../../../pubUtils/dictionary/DicRougeSkillCard'; -import { DicRougeOptionGroup } from '../../../pubUtils/dictionary/DicRougeOptionGroup'; -import { addItems, getRougeTechScoreObject, handleCost } from '../../../services/role/rewardService'; -import { getEffectWhenGameStart, getCharaHp, getAddCoin, getNoBossRecoveryHp, getBattleRecoveryNum, getRecoveryExtendHp, getTrainCardDiscount, checkCanChooseSkillCard, checkCanReRandomReward, getEnterGame } from '../../../services/battle/rougeEffectService'; -import { RougelikeExtendModel } from '../../../db/RougelikeExtend'; -import * as util from 'util'; -import { DicRougePassiveCard } from '../../../pubUtils/dictionary/DicRougePassiveCard'; -import { checkTask } from '../../../services/task/taskService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RougeHandler(app); -} - -export class RougeHandler { - constructor(private app: Application) { - } - - - /** - * 获取大界面数据(即进入游戏获取当前是否有进行中的一场数据) - * @param msg - * @param session - * @returns - */ - async getData(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - - let data = await getRougeData(roleId); - return resResult(STATUS.SUCCESS, data); - } - - - /** - * 获取一场试炼正在进行中的游戏数据 - * @param msg - * @param session - */ - async getGame(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - - return resResult(STATUS.SUCCESS, { ...await getGame(roleId) }) - } - - - - /** - * 获取初始角色卡 - * @param msg - * @param session - * @returns - */ - async getInitCharaCard(msg: { type: number, grade: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - const { type, grade } = msg; - - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS) - // 存在一场正在进行中,不能开启新一场 - if (dbRecord) return resResult(STATUS.ROUGELIKE_GAME_PLAYING); - - let typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE); - - const { lv = 0 } = await RoleModel.findByRoleId(roleId, 'lv'); - if (lv < (typeGradeData.lvLimit || 0)) return resResult(STATUS.LIMIT_LV); - - // 开启新一场 - const gameCode = genCode(8); - - const charaCards = getInitCharaCard() || []; - - let handleAddFun = new HandleAddCard(session, gameCode); - for (let ele of charaCards) { - handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []); - } - let result = await handleAddFun.save(); - await RougelikeRecordModel.updateByGameCode(gameCode, { - $set: { - roleId, grade, type, authorType: 0, curLayer: 0, - maxLayer: typeGradeData.layerCount, status: 0, takeoutReward: [], - }, - $inc: { score: 0, coin: 0, techScore: 0 } - }) - - return resResult(STATUS.SUCCESS, { gameCode, ...result }) - } - - /** - * 角色卡刷新 - * @param msg - * @param session - * @returns - */ - async refreshInitCharaCard(msg: { gameCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - - const { gameCode } = msg; - - let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - const { type = 0, grade = 0 } = dbRecord; - - await RougelikeCharaModel.deleteCharaByRoleId(roleId); - const charaCards = getInitCharaCard() || []; - let handleAddFun = new HandleAddCard(session, gameCode); - for (let ele of charaCards) { - handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []); - } - let result = await handleAddFun.save(); - - return resResult(STATUS.SUCCESS, { gameCode, charas: result?.addCharas || [] }) - } - - - /** - * 开启一场游戏 - * @param msg - * @param session - * @returns - */ - async startGame(msg: { gameCode: string, authorType: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - const { gameCode, authorType } = msg; - - // 检测流派 - const authorTypeData = gameData.rougeAuthorType.get(authorType); - if (!authorTypeData) return resResult(STATUS.NO_AUTHOR_TYPE); - - let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - // 未选角色 - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME) - // 存在一场正在进行中,不能开启新一场 - if (dbRecord.status != ROUGE_LIKE_STATUS.CHOOSECHARA) return resResult(STATUS.ROUGELIKE_GAME_PLAYING); - - const { type, grade, curLayer, maxLayer, } = dbRecord - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE); - - const typeGradeByIdData = gameData.rougeTypeGradeById.get(typeGradeData.limitId); - if (typeGradeByIdData) { - const dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.limitId) - if (!dbExtend) return resResult(STATUS.TYPE_UNLOCK); - } - - let nodes = getMap(typeGradeData.layerPlan, typeGradeData.layerCount); - - await RougelikeLayerModel.bulkWriteUpdate(nodes.map(cur => { return { ...cur, gameCode, roleId, status: 0 }; })); - await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { authorType, status: ROUGE_LIKE_STATUS.INPROGRESS } }); - - let { addCoin, cardIds } = await getEffectWhenGameStart(roleId, gameCode, authorType); - dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: addCoin, coinTotal: addCoin } }); - //任务 - if (addCoin > 0) { - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin }); - } - - - - const charas: CommonChara[] = formateCharasOrCards(await RougelikeCharaModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; - let handleAddFun = new HandleAddCard(session, gameCode); - handleAddFun.pushHolyCards(cardIds); - let result = await handleAddFun.save(); - result = await handleAddFun.getHolyEffect(); - - - return resResult(STATUS.SUCCESS, { gameCode, grade, coin: dbRecord.coin, coinTotal: dbRecord.coinTotal, type, authorType, curLayer, maxLayer, nodes, charas: [...charas, ...result.addCharas], cards: result.addCards }) - - } - - /** - * 结束游戏 - * @param msg - * @param session - * @returns - */ - async gameEnd(msg: { gameCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - const { gameCode } = msg; - let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - let { type, grade, status = 0, takeoutReward = [], hasReceivedTakeout = false, curLayer = 0, } = dbRecord; - if (status == ROUGE_LIKE_STATUS.SUCCESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - status = ROUGE_LIKE_STATUS.SUCCESS; - - const dbLayers = await RougelikeLayerModel.findByGameCode(gameCode); - - let takeoutRewardMap = takeoutReward.reduce((map, cur) => { map.set(cur.id, cur.count); return map; }, new Map()); - let spiritIds: number[] = []; - let addScore = 0, addTech = 0, isPass = true; - if (dbLayers.length == 0) isPass = false; - for (const { layer, hasPass = false, layerNodes } of dbLayers) { - if (layer > dbRecord.curLayer) { - isPass = false; - continue; - }; - const layerNodeOne = layerNodes.find(cur => cur.isChoose == 1); - let nodeType = layerNodeOne?.type || 0; - const detailCode = layerNodeOne?.detailCode; - - //忽略挑战关 - if (!hasPass && nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) { - isPass = false; - continue; - } - if (nodeType == ROUGE_LIKE_NODE_TYPE.QUEST_POINT) { - const dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode) - nodeType = dbDetail?.questType || 0; - } - const layerReward = getLayerRewardOneData(type, grade, layer, nodeType); - const { takeoutReward = [], score = 0, tech = 0, spiritPlan } = clone(layerReward); - addScore += score, addTech += tech; - for (const { id, count } of takeoutReward) takeoutRewardMap.set(id, takeoutRewardMap.get(id) || 0 + count); - for (const { id, count } of spiritPlan) { spiritIds.push(...getRandomSpirit(id, count)); } - } - let spiritMap = new Map(); - spiritIds.forEach((spiritId) => { - spiritMap.set(spiritId, { id: spiritId, count: (spiritMap.get(spiritId)?.count || 0) + 1 }); - }) - - takeoutReward = [...Array.from(takeoutRewardMap, ([id, count]) => ({ id, count })), ...spiritMap.values()]; - - - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { status, takeoutReward }, $inc: { score: addScore, techScore: addTech } }); - - let { score = 0, techScore = 0 } = dbRecord; - let dbScore = await RougelikeScoreModel.incScore(roleId, score); - let goods = await addItems(roleId, roleName, sid, [getRougeTechScoreObject(techScore)], ITEM_CHANGE_REASON.ROUGE_TECH_SCORE); - - let firstReward = []; - if (isPass) { - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - if (!typeGradeData || !typeGradeData.id) return resResult(STATUS.NO_TYPE_GRADE); - let dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.id); - if ((dbExtend?.limitId || 0) != typeGradeData.id) { - firstReward = await addItems(roleId, roleName, sid, typeGradeData?.firstReward || [], ITEM_CHANGE_REASON.ROUGE_FIRST_REWARD); - await RougelikeExtendModel.update(roleId, typeGradeData.id, firstReward, gameCode); - } - await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_ROUGE, { rougeId: typeGradeData.id, count: 1 }); - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GAME_COUNT, { count: 1 }); - } - - return resResult(STATUS.SUCCESS, { - gameCode, goods, score, techScore, hasReceivedTakeout, firstReward, - takeoutReward, weeklyScore: dbScore?.score || 0, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0 - }); - - } - - /** - * 选择外带奖励 - * @param msg - * @param session - */ - async takeoutReward(msg: { gameCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - const { gameCode } = msg; - let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - let { takeoutReward, hasReceivedTakeout } = dbRecord; - if (hasReceivedTakeout) return resResult(STATUS.ROUGELIKE_TAKEOUT_HAS_RECEIVED); - - let dbScore = await RougelikeScoreModel.receiveTakeoutReward(roleId, ROUGELIKE.TAKEOUT_REWARD_CNT); - if (!dbScore) return resResult(STATUS.ROUGELIKE_TAKEOUT_CNT_NOT_ENOUGH); - - dbRecord = await RougelikeRecordModel.takeout(gameCode); - - let goods = await addItems(roleId, roleName, sid, takeoutReward, ITEM_CHANGE_REASON.ROUGE_TAKE_OUT_REWARD) - - return resResult(STATUS.SUCCESS, { gameCode, hasReceivedTakeout: dbRecord?.hasReceivedTakeout || false, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0, goods }); - } - - /** - * 选择关卡节点 - * @param msg - * @param session - */ - async chooseNode(msg: { gameCode: string, layer: number, detailCode: string }, session: BackendSession) { - let chooseNodeStartTime = Date.now(); - - let roleId = session.get('roleId'); - const { gameCode, layer, detailCode } = msg; - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - const { curLayer, maxLayer, type, grade } = dbRecord; - - if (layer < curLayer || layer > maxLayer) return resResult(STATUS.NODE_NO_CHOOSE); - - let dbCurLayer = {} as RougelikeLayerType, dbPreLayer = {} as RougelikeLayerType; - let dbLayerNodes = await RougelikeLayerModel.findByGameCodeAndLayers(gameCode, [layer, layer - 1]); - - if (!dbLayerNodes) return resResult(STATUS.NODE_NO_CHOOSE); - for (let val of dbLayerNodes) { - if (val.layer == layer) { - if (val.hasPass) return resResult(STATUS.NODE_NO_CHOOSE);//当前关完成 - dbCurLayer = val; - } - // 注意过滤挑战点 - if ((val.layer || 0) == layer - 1 && layer - 1 > 0) { - let dbDetail = await RougelikeRecordDetailModel.findByGameCodeAndLayer(gameCode, layer - 1); - if (!val.hasPass && (!dbDetail || dbDetail.nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE)) return resResult(STATUS.NODE_NO_CHOOSE);//前一关未完成 - dbPreLayer = val; - } - } - - let dbIsChoose = dbCurLayer.layerNodes.find(cur => cur.isChoose == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE); - if (dbIsChoose && dbIsChoose.detailCode != detailCode) return resResult(STATUS.NODE_NO_CHOOSE); //该层已经选择过一关卡,不能再次选择其他关卡 - let dbCurLayerChooseNode: layerNode = dbCurLayer.layerNodes.find(cur => cur.detailCode == detailCode); - if (!dbCurLayerChooseNode) return resResult(STATUS.NODE_NO_CHOOSE); - if (dbPreLayer && Object.keys(dbPreLayer).length > 0) { - let dbPreLayerChooseNode = dbPreLayer.layerNodes.find(cur => cur.isChoose != 0); - if (dbCurLayerChooseNode.preNodeIndexs.indexOf(dbPreLayerChooseNode.index) == -1) return resResult(STATUS.NODE_NO_CHOOSE); - } - - - const curNode = await chooseNode(dbRecord, dbCurLayerChooseNode, layer) - - console.log('*********************************nodeType=%s, chooseNodeTime=%s', curNode?.nodeType, Date.now() - chooseNodeStartTime); - - return resResult(STATUS.SUCCESS, { detailCode, layer, curNode }) - } - - // 挑战关卡 - async checkBattle(msg: { gameCode: string, detailCode: string, warId: number, charaCodes: string[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - - const { gameCode, detailCode, warId, charaCodes } = msg; - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); - let { status = 0, rewards, layer, nodeType, warId: detailWarId = 0 } = dbDetail; - - if (status != 0 || warId != detailWarId) return resResult(STATUS.WAR_NO_CHOOSE); - - let dicWar = gameData.war.get(detailWarId); - if (!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const battleCode = genCode(8); // 关卡唯一值 - const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, charaCodes); - if (!dbCharas || dbCharas.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE); - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId: warId, status: 0, warName: dicWar.gk_name, warType: dicWar.warType, - record: { - rougeOriginal: dbCharas.map(cur => { - const { charaId, cards = [], hp = 0, ap = 0, shield = 0, roundSkill = 0, apSkill = 0 } = cur; - return { charaId, cards, hp, ap, roundSkill, apSkill } - }) - } - } - }, true); - return resResult(STATUS.SUCCESS, { gameCode, battleCode }); - } - - - /** - * 结束关卡 - * @param msg - * @param session - * @returns - */ - async battleEnd(msg: { gameCode: string, detailCode: string, battleCode: string, warId: number, status: number, round: number, rougeDamage: RougeDamageInter[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - let { gameCode, detailCode, battleCode, warId, status, round, rougeDamage } = msg; - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail || (dbDetail.warId || 0) != warId || warId == 0 || (dbDetail.status || 0) != 0) return resResult(STATUS.WAR_NO_CHOOSE); - let { layer, nodeType, questType = 0 } = dbDetail; - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, rougeDamage.map(cur => { return cur.charaCode })); - if (!dbCharas || dbCharas.length == 0 || dbCharas.length != rougeDamage.length) return resResult(STATUS.REWARD_NO_CHOOSE); - - await BattleRecordModel.findOneAndUpdate({ battleCode }, { - $set: { status, 'record.round': round, 'record.rougeDamage': rougeDamage, } - }, { new: true, upsert: true }).lean(true); - - const dbCharaMap = dbCharas.reduce((result, cur) => { result.set(cur.charaCode, { ...cur }); return result; }, new Map()); - - let isAp: boolean = false, isRound: boolean = false, arrAuthorType: number[] = [], isHpZero = false; - for (let obj of rougeDamage) { - if (obj.isAp) isAp = true; - if (obj.isRound) isRound = true; - const chara = dbCharaMap.get(obj.charaCode); - if (!chara) return resResult(STATUS.BATTLE_ABNORMAL) - obj.maxHp = (chara.maxHp || 0); - - if (!chara.cards || chara.cards.length == 0) console; - for (const { cardId } of chara.cards) { - const passiveCardData = gameData.rougePassiveCard.get(cardId); - if (nodeType == ROUGE_LIKE_NODE_TYPE.BOSS && passiveCardData && passiveCardData.authorType) arrAuthorType.push(passiveCardData.authorType); - } - if (!obj.hp || obj.hp == 0) isHpZero = true; - } - await updateChalleng(dbRecord, roleId, sid, gameCode, layer, rougeDamage, isAp, isRound); - - let updateCharas: RougelikeCharaPara[] = [], charas: CommonChara[] = []; - - - let recoveryHp = false; - if (status != 1 && nodeType != ROUGE_LIKE_NODE_TYPE.BOSS && isHpZero) { - recoveryHp = await getNoBossRecoveryHp(roleId, gameCode); - if (recoveryHp) status = 1; - } - - let hpRatio = 0; - if (status == 1) { - hpRatio = await getCharaHp(roleId, gameCode); - } - const minHp = rougeDamage.reduce((min, cur) => { return Math.min(min, cur.hp); }, Infinity); - let recoveryNum = 0; - if (minHp == 0) recoveryNum = await getBattleRecoveryNum(roleId, gameCode); - - - let updateCharasMap = new Map(); - for (let { charaCode, hp, ap, shield, others } of rougeDamage) { - const chara = dbCharaMap.get(charaCode); - if (!chara) return resResult(STATUS.BATTLE_ABNORMAL) - if (chara.maxHp < hp) hp = chara.maxHp; - - if (recoveryHp && hp == 0) hp = chara.maxHp; - if (hpRatio > 0 && hp != 0) hp = Math.min(Math.floor(hp + (chara.maxHp * hpRatio / 100)), chara.maxHp); - - if ((recoveryNum--) > 0 && hp == 0) { hp = chara.maxHp; } - - charas.push({ charaCode, charaId: chara.charaId, seqId: chara.seqId, cards: chara.cards, hp, maxHp: chara.maxHp, ap, shield, others, apSkill: chara.apSkill, roundSkill: chara.roundSkill }) - updateCharas.push({ gameCode, charaCode, hp, ap, shield, others }); - updateCharasMap.set(charaCode, { hp, ap, shield, others }); - } - - let incCoin = 0; - if (status == 1) { - let { coinRatio, coinAdd } = await getAddCoin(roleId, gameCode, nodeType); - let newNodeType = nodeType; - if (questType > 0) newNodeType = questType; - const layerReward = getLayerRewardOneData(dbRecord.type, dbRecord.grade, layer, newNodeType); - incCoin = Math.floor((layerReward.coin || 0) * (1 + coinRatio / 100) + coinAdd); - await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } }); - - //battleEnd 主动将hasPass置为true - await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }); - } - - // let coinReward = rewards.find(cur => cur.rewardType == 0); - // if (coinReward) coinReward.chooseNum = Math.floor(coinReward.chooseNum * (1 + coinRatio / 100) + coinAdd); - // if (coinRatio != 0 || coinAdd != 0) { - // await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.rewardType': 0 }, { 'rewards.$.chooseNum': coinReward.chooseNum, }, { new: true, upsert: true }).lean(true); - // } - - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } }) - - if (incCoin > 0) { - charas = await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade, updateCharasMap) - - //任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin: incCoin }); - - } else { - await RougelikeCharaModel.bulkWriteUpdate(updateCharas); - } - - if (status == 1 && arrAuthorType.length > 0 && arrAuthorType.every(cur => cur == arrAuthorType[0])) { - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_BOSS_PASS, { authorType: arrAuthorType[0], count: 1 }); - } - - await getEnterGame(roleId, gameCode); - - return resResult(STATUS.SUCCESS, { status, gameCode, detailCode, charas, incCoin }); - } - - // 重置 - async reRandomReward(msg: { gameCode: string, detailCode: string, rewardType: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const { gameCode, detailCode, rewardType } = msg; - - // 检查数量 - let { canReRandom, costCoin } = await checkCanReRandomReward(roleId, gameCode, rewardType); - if (!canReRandom) return resResult(STATUS.ROUGE_TECH_NOT_UNLOCKED); - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); - - let dbDetailReward = dbDetail.rewards.find(cur => cur.rewardType == rewardType); - if (!dbDetailReward || dbDetailReward.reRandRewardCnt > 0) return resResult(STATUS.ROUGE_RE_RANDOM_CNT_OVER); - - const typeGradeData = gameData.rougeTypeGrade.get(dbRecord.type + '_' + dbRecord.grade); - const nodeData = gameData.rougeNode.get(dbDetail.nodeId); - if (!typeGradeData || !nodeData) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + dbDetail.layer); - if (!layerPlanData) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let costResult = await RougelikeRecordModel.costCoin(gameCode, costCoin); - if (!costResult) return resResult(STATUS.COIN_NOT_ENOUGH); - - let replaceReward = await getLayerNodeReward(roleId, gameCode, dbRecord.authorType, dbDetail.nodeId, layerPlanData.rewardPlan, dbDetail.layer, dbDetail.questType); - let { rewards } = dbDetail; - if (replaceReward && replaceReward.rewards.length > 0) { - let newRewards = [...rewards.filter(reward => reward.rewardType != rewardType), ...replaceReward.rewards.filter(reward => reward.rewardType == rewardType)].map(reward => ({ ...reward, reRandRewardCnt: 1 })).sort((a, b) => a.groupIndex - b.groupIndex); - dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards: newRewards } }); - } - - return resResult(STATUS.SUCCESS, { rewards: dbDetail.rewards }); - } - - /** - * 选择奖励 - * @param msg - * @param session - * @returns - */ - async chooseReward(msg: { gameCode: string, detailCode: string, groupIndex: number, optionIndexs: number[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - const { gameCode, detailCode, groupIndex, optionIndexs } = msg; - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); - let { status, rewards, layer, nodeType, warId = 0, challenge } = dbDetail; - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - // 检测有关卡的是否挑战成功 - if (warId != 0 && status != 1) return resResult(STATUS.REWARD_NO_CHOOSE); - - if (!rewards || rewards.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE); - let { rewardType, options, groupStatus, chooseNum } = rewards.find((obj) => obj.groupIndex == groupIndex); - - // if (groupStatus == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return resResult(STATUS.REWARD_NO_CHOOSE); - - let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); - let incCoin = 0, redCoin = 0; - // //处理下试炼币 - // if (rewardType == 0) { - // incCoin = chooseNum; - // groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; - // const result = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.groupIndex': groupIndex }, { 'rewards.$.groupStatus': groupStatus, }, { new: true, upsert: true }).lean(true); - // if (result.rewards.find((obj) => obj.groupStatus != ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) == undefined) { - // await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) - // } - // await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } }) - // return resResult(STATUS.SUCCESS, { addCharas: await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade), addCards: [], incCoin, redCoin }); - // } - - - // 特性卡可以选多次 - let passiveChooseCount = 0; - if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE || rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) { - passiveChooseCount = options.reduce((accumulator, obj) => { - if (obj.optionStatus === ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return accumulator + 1; - return accumulator; - }, 0); - if (chooseNum - passiveChooseCount < optionIndexs.length) return resResult(STATUS.REWARD_NO_CHOOSE); - } - - if (optionIndexs.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE); - - let tempOptions: RewardOption[] = options.filter(opt => optionIndexs.includes(opt.optionIndex)); - if (tempOptions.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE); - - for (let { rewardId, passiveCardIds, optionStatus, optionIndex } of tempOptions) { - if (optionStatus != 0) return resResult(STATUS.REWARD_NO_CHOOSE); - let cardCode = genCode(8); - if (rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) { - // 更新角色卡 - handleAddFun.pushChara(rewardId, await getMaxHp(roleId, gameCode, rewardId, dbRecord.type, dbRecord.grade), passiveCardIds || []); - //休整点 消耗 - if (nodeType == ROUGE_LIKE_NODE_TYPE.REST_POINT) { - let charaData = gameData.rougeChara.get(rewardId); - if (!charaData) return; - redCoin += charaData.recruitConsume || 0; - } - } else { - // 更新特性卡or圣物 - handleAddFun.pushCard(rewardId, rewardType); - } - optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; - options.forEach((ele) => { if (ele.optionIndex == optionIndex) ele.optionStatus = optionStatus; }); - } - - if ((dbRecord.coin || 0) < redCoin) return resResult(STATUS.COIN_NOT_ENOUGH); - if (redCoin > 0) await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -redCoin } }); - - groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; - - if (nodeType == ROUGE_LIKE_NODE_TYPE.CHALLENGE) { - // 挑战关领奖更新 - await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) - } else { - // 更新进度 - await updateChalleng(dbRecord, roleId, sid, gameCode, layer, []); // 更新挑战进度 - } - - await RougelikeRecordDetailModel.updateRewardByGroupIndex(gameCode, detailCode, groupIndex, groupStatus, options); - - let addResult = await handleAddFun.save(); - addResult = await handleAddFun.getHolyEffect(); - - return resResult(STATUS.SUCCESS, { ...addResult, incCoin, redCoin }); - - } - - - /** - * 商店购买 - * @param msg - * @param session - * @returns - */ - async shopBuy(msg: { gameCode: string, detailCode: string, optionIndex: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - let { gameCode, detailCode, optionIndex } = msg; - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.SHOP_NO_BUY); - - let { status = 0, shops, layer, nodeType } = dbDetail; - if (status == 1 || !shops || shops.length == 0) return resResult(STATUS.SHOP_NO_BUY); - - let shop = shops.find((obj) => obj.optionIndex == optionIndex); - if (!shop || shop.optionStatus != ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE) return resResult(STATUS.SHOP_NO_BUY); - - let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode); - if (!dbRecord || (dbRecord.coin || 0) < shop.discountPrice) return resResult(STATUS.COIN_NOT_ENOUGH); - - - shop.optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; - - await RougelikeRecordDetailModel.updateShopByCode(gameCode, detailCode, optionIndex, shop.optionStatus); - await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { coin: (dbRecord.coin || 0) - shop.discountPrice } }); - - let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); - handleAddFun.pushCard(shop.rewardId, shop.rewardType); - let result = await handleAddFun.save(); - result = await handleAddFun.getHolyEffect(); - - return resResult(STATUS.SUCCESS, { curShop: shop, ...result, redCoin: -shop.discountPrice }); - - } - - /** - * 结束这一节点 - * @param msg - * @param session - * @returns - */ - async nodeEnd(msg: { gameCode: string, detailCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - const { gameCode, detailCode } = msg; - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.NO_EXIT_NODE); - let { layer, nodeType, status = 0, shops, warId = 0 } = dbDetail; - if ((warId != 0 && status != 1)) { - //检测关卡是否挑战成功 - return resResult(STATUS.NODE_NO_END) - } - status = 1; - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } }); - if (nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) { - await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }); - } - - return resResult(STATUS.SUCCESS, { gameCode, detailCode, status, ...await getGame(roleId) }) - } - - - /** - * 问号点选择题 - * @param msg - * @param session - * @returns - */ - async chooseOption(msg: { gameCode: string, detailCode: string, eventOptions: number[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - const { gameCode, detailCode, eventOptions } = msg; - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); - let { layer, nodeType, status = 0, question = {} as Quest } = dbDetail; - if (status == 1) return resResult(STATUS.NODE_NO_CHOOSE); - - let checkAfterGroup = 0, optionGroupIds: number[] = []; - let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); - for (let [index, id] of eventOptions.entries()) { - const rougeEventOptionData = gameData.rougeEventOption.get(id); - if (!rougeEventOptionData) return resResult(STATUS.NODE_NO_CHOOSE); - const { randomEventId, optionGroup, afterGroup, holyCardPlan } = rougeEventOptionData; - - if (randomEventId != (question.randomEventId || 0)) return resResult(STATUS.NODE_NO_CHOOSE); - - if (index != 0 && checkAfterGroup != optionGroup) return resResult(STATUS.NODE_NO_CHOOSE); - if (!optionGroupIds.includes(optionGroup)) optionGroupIds.push(optionGroup); - - if (!question.EventOptions) question.EventOptions = []; - question.EventOptions.push(id); - checkAfterGroup = afterGroup; - - const rougeHolyCardPlanData = gameData.rougeHolyCardPlan.get(holyCardPlan); - if (!rougeHolyCardPlanData || rougeHolyCardPlanData.length == 0) continue; - let newCards = []; - let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); - for (let obj of rougeHolyCardPlanData) { - let holyCardData = gameData.rougeHolyCard.get(obj.cardId); - if (!holyCardData) continue; - const getLimit = cardsMap.get(obj.cardId) || 0; - if (getLimit >= (holyCardData?.getLimit || 0)) continue; //处理限制获取数量 - newCards.push(obj); - } - let cardId = 0; - if (newCards.length > 0) { - cardId = getRandEelmWithWeight(newCards).dic.cardId; - } - - if (cardId > 0) handleAddFun.pushHolyCard(cardId); - } - - status = 1; - - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { question, status } }) - await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) - - let result = await handleAddFun.save(); - await handleAddFun.getHolyEffect(); - - await addSameTypeCollect(roleId, sid, gameCode, COLLECTION_TYPE.EVENT, optionGroupIds); - //任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_EVENT_COLLECT, { eventGroups: optionGroupIds }); - - return resResult(STATUS.SUCCESS, { ...result }) - } - - - /** - * 休整点恢复 - * @param msg - * @param session - * @returns - */ - async recovery(msg: { gameCode: string, detailCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - - const { gameCode, detailCode } = msg; - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); - let { restPoints = [], nodeType, status, rewards } = dbDetail; - if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE); - - let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.RECOVERY) || new RestPoint(); - if (restPoint.recoveryCnt && restPoint.recoveryCnt > 0) return resResult(STATUS.NO_TIME_RECOVERY); - restPoint.recoveryCnt = 1; - restPoint.restType = REST_POINT_TYPE.RECOVERY; - restPoint.recoveryCharas = []; - let dbCharas = await RougelikeCharaModel.findByGameCode(gameCode); - let updateCharas: RougelikeCharaPara[] = []; - - let hpRatio = await getRecoveryExtendHp(roleId, gameCode); - for (let { gameCode, charaCode, charaId, cards, hp = 0, maxHp = 0, ap, shield, roundSkill, apSkill } of dbCharas) { - if (hp == 0) continue; - let beforeHp = hp; - hp = Math.floor(Math.min(hp + maxHp * ROUGELIKE.RECOVERY_RATIO / 100 + maxHp * hpRatio / 100, maxHp)); - updateCharas.push({ gameCode, charaCode, hp }); - restPoint.recoveryCharas.push({ charaCode, charaId, beforeHp, afterHp: hp }); - } - restPoints.push({ restType: restPoint.restType, recoveryCnt: restPoint.recoveryCnt, recoveryCharas: restPoint.recoveryCharas }); - - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } }); - await RougelikeCharaModel.bulkWriteUpdate(updateCharas); - - const charas: CommonChara[] = formateCharasOrCards(dbCharas, ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; - - return resResult(STATUS.SUCCESS, { restPoints, charas, reward: { rewards } }) - } - - /** - * 休整点强化 - * @param msg - * @param session - */ - async trainCard(msg: { gameCode: string, detailCode: string, cardCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - - const { gameCode, detailCode, cardCode } = msg; - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) - if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); - if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); - - let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); - let { layer, nodeType, status = 0, question, restPoints = [], rewards } = dbDetail; - if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE); - - let dbCard = await RougelikeCardModel.findByCode(gameCode, cardCode); - if (!dbCard) return resResult(STATUS.NO_CARD); - let { type, cardId, charaId = 0, lv = 0 } = dbCard; - - const passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData) return resResult(STATUS.NO_CARD); - const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0); - if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return resResult(STATUS.HIGH_LV); - let passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map()); - if (!passiveCardDataMap.has(lv + 1)) return resResult(STATUS.HIGH_LV); - - const strengthConsume = passiveCardData.strengthConsume || 0; - const { lv: cardLv, id } = passiveCardDataMap.get(lv + 1); - if (lv == cardLv) return resResult(STATUS.HIGH_LV); - - let realConsume = Math.floor(strengthConsume * await getTrainCardDiscount(roleId, gameCode) / 100); - if ((dbRecord.coin || 0) < realConsume) return (STATUS.COIN_NOT_ENOUGH); - - let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.TRAIN) || new RestPoint(); - restPoint.restType = REST_POINT_TYPE.TRAIN; - if (!restPoint.trainCardCnt) restPoint.trainCardCnt = 0; - restPoint.trainCardCnt += 1; - if (!restPoint.trainCards) restPoint.trainCards = []; - restPoint.trainCards.push({ cardCode, cardId: id, beforeLv: lv, afterLv: lv + 1 }); - - if (restPoints.find(cur => cur.restType == restPoint.restType) == undefined) { - restPoints.push({ restType: restPoint.restType, trainCardCnt: restPoint.trainCardCnt, trainCards: restPoint.trainCards }) - } - else restPoints.forEach(obj => { - if (obj.restType == restPoint.restType) { - obj.trainCardCnt = restPoint.trainCardCnt; - obj.trainCards = restPoint.trainCards; - } - - }) - await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -realConsume } }); - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } }); - const newDbCard = await RougelikeCardModel.updateByCode(gameCode, cardCode, { $set: { cardId: id }, $inc: { lv: 1 } }); - const cards: CommonCard[] = formateCharasOrCards([newDbCard], ROUGE_LIKE_CARD_TYPE.PASSIVE)?.cards || []; - - if (charaId > 0) { - const dbCharas = await RougelikeCharaModel.findByGameCodeAndCharaId(gameCode, charaId); - let isEnd = false; - for (let { cards = [], charaCode } of dbCharas) { - for (let obj of cards) { - if (cardCode != obj.cardCode) continue; - obj.cardId = id; - await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode, 'cards.cardCode': cardCode }, { 'cards.$.cardId': id }, { new: true, upsert: true }).lean(true); - isEnd = true; - break; - } - if (isEnd) break; - } - } - - return resResult(STATUS.SUCCESS, { restPoints, cards, reward: { rewards }, redCoin: -realConsume, }) - - } - - /** - * 选择一张技能卡 - * @param msg - * @returns - */ - async chooseSkillCard(msg: { gameCode: string, charaCode: string, skillType: number, id: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - const { gameCode, charaCode, skillType, id } = msg; - - let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode); - if (!dbChara) return resResult(STATUS.NO_CARD); - - if (id > 0) { - const dicSkillCard = gameData.rougeSkillCard.get(id); - if (!dicSkillCard) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicSkillCard.skillType != skillType) return resResult(STATUS.WRONG_PARMS); - - // 检查数量 - if (!await checkCanChooseSkillCard(roleId, gameCode, id, dbChara.cards)) - return resResult(STATUS.ROUGE_PASSIVE_CARD_NOT_ENOUGH); - } - - let chara = await RougelikeCharaModel.putOnOrOffSkillCard(gameCode, charaCode, skillType, id); - if (!dbChara) return resResult(STATUS.NO_CARD); - // 更新图鉴 - await addSingleCollect(roleId, sid, gameCode, COLLECTION_TYPE.SKILL_CARD, id); - - // 任务 - let dicSkillCard = gameData.rougeSkillCard.get(id); - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT, { authorType: dicSkillCard.authorType, cardType: TASK_ROUGE_CARD_TYPE.SKILL, cardIds: [id] }); - - return resResult(STATUS.SUCCESS, { - curChara: new CommonChara(chara) - }) - } - - /** - * 安装或者卸下特性卡 - * @param msg - * @param session - */ - async putOnOrOffCard(msg: { gameCode: string, charaCode: string, cards: SlotCard[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let { gameCode, charaCode, cards } = msg; - - // 获取角色卡db数据 - let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode); - if (!dbChara) return resResult(STATUS.NO_CARD); - if (!dbChara.cards || dbChara.cards.length == 0) return resResult(STATUS.SLOT_UNLOCK); - let dbCharaCardsMap = dbChara.cards.reduce((result, cur) => { result.set(cur.index, cur); return result; }, new Map()); - - // 获取需要安装、卸下的特性卡db数据 - let cardCodes: string[] = []; - cards.forEach((ele) => { cardCodes.push(ele.cardCode); }); - dbChara.cards.forEach((ele) => { cardCodes.push(ele.cardCode); }) - let dbCards: RougelikeCardType[] = await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes); - if (dbCards.length == 0) return resResult(STATUS.NO_CARD); - let dbCardsMap = dbCards.reduce((result, cur) => { result.set(cur.cardCode, cur); return result; }, new Map()); - - let newCardsMap = new Map(); - for (let { index, cardCode } of cards) { - // 检测卡槽解锁 - let slot = dbCharaCardsMap.get(index) - if (!slot) return resResult(STATUS.SLOT_UNLOCK); - - //处理旧的cardCode - let oldSotCardCode = clone(slot.cardCode); - let updateObj = dbCardsMap.get(oldSotCardCode); - if (updateObj) { - updateObj.charaId = 0; - dbCardsMap.set(oldSotCardCode, updateObj); - newCardsMap.set(oldSotCardCode, updateObj); - } - - //处理新的cardCode安装 - let update = dbCardsMap.get(cardCode); - dbCharaCardsMap.set(index, { index, cardCode: cardCode, cardId: update?.cardId || 0 }); - if (update) { - if (update.type != ROUGE_LIKE_CARD_TYPE.PASSIVE) return resResult(STATUS.NO_PASSIVE); - update.charaId = dbChara.charaId; - dbCardsMap.set(cardCode, update); - newCardsMap.set(cardCode, update); - } - } - let newCards = Array.from(dbCharaCardsMap.values()); - let tempCards = new Map(); - for (let { cardId } of newCards) { - if (!cardId) continue; - if (tempCards.has(cardId)) return resResult(STATUS.ROUGE_NO_CAN_PUT_SAME_ID); - tempCards.set(cardId, cardId); - } - - // 如果卸下之后技能卡需要的被动卡不够,需要把技能卡卸下 - let { apSkill, roundSkill } = dbChara; - if (apSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, apSkill, newCards)) apSkill = 0; - if (roundSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, roundSkill, newCards)) roundSkill = 0; - - //更新角色卡db, 特性卡db - let newChara = await RougelikeCharaModel.updateByCode(gameCode, charaCode, { $set: { cards: newCards, apSkill, roundSkill } }); - await RougelikeCardModel.bulkWriteUpdate(Array.from(newCardsMap.values()).map(obj => ({ gameCode, cardCode: obj.cardCode, charaId: obj.charaId }))) - let curCards = Array.from(dbCardsMap.values()).map(obj => ({ cardCode: obj.cardCode, type: obj.type, charaId: obj.charaId, lv: obj.lv })); - - return resResult(STATUS.SUCCESS, { curCards, curChara: new CommonChara(newChara) }) - } - - - async exchangeChara(msg: { gameCode: string, oldCharaCode: string, newCharaCode: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - const { gameCode, oldCharaCode, newCharaCode } = msg; - const result = await RougelikeCharaModel.findByCodes(gameCode, [oldCharaCode, newCharaCode]); - if (result.length != 2) return (STATUS.NO_CARD); - let oldChara = {} as RougelikeCharaType, newChara = {} as RougelikeCharaType; - for (let val of result) { - if (val.charaCode == oldCharaCode) oldChara = val; - if (val.charaCode == newCharaCode) newChara = val; - } - - let temp = clone(newChara.seqId); - newChara.seqId = clone(oldChara.seqId); - oldChara.seqId = temp; - // 更新角色卡 - await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]); - let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas; - - - // // 处理新卡 - // let { charaCode, charaId, maxHp, seqId } = newChara; - // newChara = clone(oldChara); - // newChara.charaCode = charaCode; - // newChara.charaId = charaId; - // newChara.maxHp = maxHp; - - // let cardCodes = []; - // let updateArr: RougelikeCardPara[] = []; - // for (let val of newChara.cards) { - // cardCodes.push(val.cardCode); - // updateArr.push({ gameCode, cardCode: val.cardCode, charaId }); - // } - - // // 处理旧卡 - // oldChara.cards.forEach((cur) => { cur.cardCode = '', cur.cardId = 0 }); - // oldChara.ap = oldChara.apSkill = oldChara.roundSkill = 0; - // oldChara.seqId = seqId; - - // // 更新角色卡 - // await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]); - - // let cards = formateCharasOrCards(await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes), ROUGE_LIKE_CARD_TYPE.PASSIVE).cards; - // // 更新card - // await RougelikeCardModel.bulkWriteUpdate(updateArr); - - // let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas; - - return resResult(STATUS.SUCCESS, { charas }); - } - - /** - * 解锁科技点 - * @param msg - * @param session - */ - async unlockTech(msg: { techId: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - const { techId } = msg; - - let dicTech = gameData.rougeTech.get(techId); - if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let techRecord = await RougelikeTechModel.findByRoleId(roleId); - let { unlockedTech = [] } = techRecord || {}; - if (unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_TECH_HAS_UNLOCKED); - if (!checkPreRougeTech(techId, unlockedTech)) return resResult(STATUS.ROUGE_TECH_PRE_NOT_UNLOCKED); - - // 检查消耗 - let costResult = await handleCost(roleId, sid, dicTech.cost, ITEM_CHANGE_REASON.ROUGE_UNLOCK_TECH); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let circleIds = gameData.rougeCircleByTech.get(techId) || []; - techRecord = await RougelikeTechModel.unlockTech(roleId, techId, circleIds); - if (!techRecord) return resResult(STATUS.ROUGE_TECH_SCORE_NOT_ENOUGH); - await updateEffectId(techRecord); - - let resultData = getCurTechData(techRecord, techId); - //任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_TECH_OPEN, { count: 1 }); - - return resResult(STATUS.SUCCESS, { - ...resultData - }); - } - - /** - * 放置法阵 - * @param msg - * @param session - * @returns - */ - async putOnCircle(msg: { circleId: number, hid: number }, session: BackendSession) { - - let roleId: string = session.get('roleId'); - const { circleId, hid } = msg; - - let techId = gameData.rougeTechCircle.get(circleId); - if (!techId) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let dicTech = gameData.rougeTech.get(techId); - if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let techRecord = await RougelikeTechModel.findByRoleId(roleId); - if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); - let { unlockedTech = [] } = techRecord; - if (!unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); - - let ce = 0; - if (hid != 0) { - let hero = await HeroModel.findByHidAndRole(hid, roleId, 'ce'); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - ce = hero.ce || 0; - } - - techRecord = await RougelikeTechModel.putOnCircle(roleId, circleId, hid, ce); - if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); - await updateEffectId(techRecord); - - let resultData = getCurTechData(techRecord, techId); - return resResult(STATUS.SUCCESS, { - ...resultData - }); - } - - /** - * 领取图鉴奖励 - * @param msg - * @param session - * @returns - */ - async receiveCollectionReward(msg: { type: number, id: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let { type, id } = msg; - - let dic: DicRougePassiveCollect | DicRougeHolyCard | DicRougeSkillCard | DicRougeOptionGroup; - let num = 1; - if (type == COLLECTION_TYPE.PASSIVE_CARD_SUM) { - dic = gameData.rougePassiceCollect.get(id); - num = dic?.num || 0; - } else if (type == COLLECTION_TYPE.HOLY_CARD) { - dic = gameData.rougeHolyCard.get(id); - } else if (type == COLLECTION_TYPE.SKILL_CARD) { - dic = gameData.rougeSkillCard.get(id); - } else if (type == COLLECTION_TYPE.EVENT) { - dic = gameData.rougeOptionGroup.get(id); - } - if (!dic) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let collect = await RougelikeCollectionModel.findByRoleAndId(roleId, type, id); - if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH); - if (collect.received.includes(id)) return resResult(STATUS.ROUGE_COLLECT_HAS_RECEIVED); - - collect = await RougelikeCollectionModel.receive(roleId, type, id, num); - if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH); - let goods = await addItems(roleId, roleName, sid, dic.collectReward, ITEM_CHANGE_REASON.RECEIVE_COLLECT_REWARD); - - return resResult(STATUS.SUCCESS, { - goods, curCollection: new CollectionReturnParam(collect) - }); - } - - /** - * 领取积分奖励 - * @param msg - * @param session - * @returns - */ - async receiveScore(msg: { index: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let roleName: string = session.get('roleName'); - let { index } = msg; - const lastMaxLv = await RougelikeExtendModel.getLastMaxLv(roleId); - const rougeScoreRewardByLvData = gameData.rougeScoreRewardByLv.get(lastMaxLv); - if (!rougeScoreRewardByLvData) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicScore = rougeScoreRewardByLvData.get(index); - if (!dicScore) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let scoreData = await RougelikeScoreModel.findByRoleId(roleId); - if (!scoreData || scoreData.score < dicScore.score) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH); - if (scoreData.received.includes(index)) return resResult(STATUS.ROUGE_SCORE_HAS_RECEIVED); - - scoreData = await RougelikeScoreModel.receive(roleId, dicScore.score, index); - if (!scoreData) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH); - - let goods = await addItems(roleId, roleName, sid, dicScore.reward, ITEM_CHANGE_REASON.RECEIVE_ROUGE_SCORE_REWARD); - return resResult(STATUS.SUCCESS, { - receivedScore: scoreData.received, - goods - }); - } - - async challengeRandom(msg: { detailCode: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - const { detailCode } = msg; - let dbDetail = await RougelikeRecordDetailModel.findByDetailCode(detailCode); - if (!dbDetail) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - let { gameCode, layer, nodeId, nodeType, rewards = [], challenge } = dbDetail; - if (rewards.length > 0 || nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE || (challenge?.status || 0) < 2) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - - const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode); - if (!dbRecord) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - const { authorType, type, grade } = dbRecord; - - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - if (!typeGradeData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); - if (!layerPlanData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer); - if (!result || !result.rewards) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - rewards = result.rewards; - - dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards } }); - if (!dbDetail || !dbDetail.rewards) resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); - - return resResult(STATUS.SUCCESS, { gameCode, detailCode, reward: { rewards: dbDetail.rewards } }) - } - - /** - * debug接口,清空科技树 - * @param msg - * @param session - * @returns - */ - async debugClearTech(msg: {}, session: BackendSession) { - let roleId: string = session.get('roleId'); - await RougelikeTechModel.clearTech(roleId); - return resResult(STATUS.SUCCESS); - } - - async debugAddCard(msg: { type: number, id: number }, session: BackendSession) { - let { type, id } = msg; - - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); - if (!dbRecord) { - return resResult(STATUS.NO_ROUGELIKE_GAME); - } - - let handleAddFun = new HandleAddCard(session, dbRecord.gameCode); - if (type == ROUGE_LIKE_CARD_TYPE.CHARA) { - handleAddFun.pushChara(id, await getMaxHp(roleId, dbRecord?.gameCode || '', id, dbRecord.type, dbRecord.grade), []); - } else if (type == ROUGE_LIKE_CARD_TYPE.HOLY) { - handleAddFun.pushHolyCard(id); - } else if (type == ROUGE_LIKE_CARD_TYPE.PASSIVE) { - handleAddFun.pushPassiveCard(id); - } else { - return resResult(STATUS.WRONG_PARMS); - } - let result = await handleAddFun.save(); - result = await handleAddFun.getHolyEffect(); - return resResult(STATUS.SUCCESS, result); - } - - // debug接口 - async debugAddCollection(msg: { type: number, id: number }, session: BackendSession) { - let { type, id } = msg; - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); - if (!dbRecord) { - return resResult(STATUS.NO_ROUGELIKE_GAME); - } - await addSingleCollect(roleId, sid, dbRecord.gameCode, type, id); - - return resResult(STATUS.SUCCESS); - } - - async debugAddScore(msg: { score: number }, session: BackendSession) { - let { score } = msg; - let roleId: string = session.get('roleId'); - let result = await RougelikeScoreModel.incScore(roleId, score); - return resResult(STATUS.SUCCESS, { weeklyScore: result.score }) - } - - async debugRepaireScoreReward() { - await repaireSendScoreReward(); - return resResult(STATUS.SUCCESS); - } - /** - * debug添加试炼通关 - * @param msg - * @param session - * @returns - */ - async debugAddLimitId(msg: { id: number }, session: BackendSession) { - const { id } = msg; - const roleId: string = session.get('roleId'); - const typeGradeByIdData = gameData.rougeTypeGradeById.get(id); - if (typeGradeByIdData) { - // for (let i = 3; i <= 42; i++) { - await RougelikeExtendModel.update(roleId, id, [], genCode(8)); - - // } - } - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { RougelikeRecordModel } from '@db/RougelikeRecord'; +import { genCode, getRandEelmWithWeight, resResult } from '@pubUtils/util'; +import { COLLECTION_TYPE, ITEM_CHANGE_REASON, REST_POINT_TYPE, ROUGE_LIKE_CARD_TYPE, ROUGE_LIKE_CHOOSE_REWARD, ROUGE_LIKE_NODE_TYPE, ROUGE_LIKE_STATUS, TASK_ROUGE_CARD_TYPE, TASK_TYPE } from '../../../consts'; +import { Quest, RestPoint, RougelikeRecordDetailModel } from '@db/RougelikeRecordDetail'; +import { STATUS } from '@consts/statusCode'; +import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from '@db/RougelikeCard'; +import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from '@db/RougelikeChara'; +import { CollectionReturnParam, CommonCard, CommonChara, RewardInter, RewardOption, RougeDamageInter, SlotCard, layerNode } from '@pubUtils/interface'; +import { clone } from 'underscore'; +import { RougelikeScoreModel } from '@db/RougelikeScore'; +import { RougelikeTechModel } from '@db/RougelikeTech'; +import { RougelikeCollectionModel } from '@db/RougelikeCollection'; +import { RougelikeLayerModel, RougelikeLayerType } from '@db/RougelikeLayer'; +import { RoleModel } from '@db/Role'; +import { gameData } from '@pubUtils/data'; +import { chooseNode, getCardCount, getGame, getInitCharaCard, getLayerNodeReward, getLayerRewardOneData, getMap, getMaxHp, getRandomSpirit, getRougeData, repaireSendScoreReward, updateChalleng, updateMaxHp } from '../../../services/battle/rougeService'; +import { checkPreRougeTech, getCurTechData, updateEffectId } from '../../../services/battle/rougeTechService'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { HeroModel } from '@db/Hero'; +import { ROUGELIKE } from '@pubUtils/dicParam'; +import { HandleAddCard, addSameTypeCollect, addSingleCollect, formateCharasOrCards } from '../../../services/battle/rougeCollectService'; +import { DicRougePassiveCollect } from '@pubUtils/dictionary/DicRougePassiveCollect'; +import { DicRougeHolyCard } from '@pubUtils/dictionary/DicRougeHolyCard'; +import { DicRougeSkillCard } from '@pubUtils/dictionary/DicRougeSkillCard'; +import { DicRougeOptionGroup } from '@pubUtils/dictionary/DicRougeOptionGroup'; +import { addItems, getRougeTechScoreObject, handleCost } from '../../../services/role/rewardService'; +import { getEffectWhenGameStart, getCharaHp, getAddCoin, getNoBossRecoveryHp, getBattleRecoveryNum, getRecoveryExtendHp, getTrainCardDiscount, checkCanChooseSkillCard, checkCanReRandomReward, getEnterGame } from '../../../services/battle/rougeEffectService'; +import { RougelikeExtendModel } from '@db/RougelikeExtend'; +import * as util from 'util'; +import { DicRougePassiveCard } from '@pubUtils/dictionary/DicRougePassiveCard'; +import { checkTask } from '../../../services/task/taskService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RougeHandler(app); +} + +export class RougeHandler { + constructor(private app: Application) { + } + + + /** + * 获取大界面数据(即进入游戏获取当前是否有进行中的一场数据) + * @param msg + * @param session + * @returns + */ + async getData(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + + let data = await getRougeData(roleId); + return resResult(STATUS.SUCCESS, data); + } + + + /** + * 获取一场试炼正在进行中的游戏数据 + * @param msg + * @param session + */ + async getGame(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + + return resResult(STATUS.SUCCESS, { ...await getGame(roleId) }) + } + + + + /** + * 获取初始角色卡 + * @param msg + * @param session + * @returns + */ + async getInitCharaCard(msg: { type: number, grade: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + const { type, grade } = msg; + + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS) + // 存在一场正在进行中,不能开启新一场 + if (dbRecord) return resResult(STATUS.ROUGELIKE_GAME_PLAYING); + + let typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE); + + const { lv = 0 } = await RoleModel.findByRoleId(roleId, 'lv'); + if (lv < (typeGradeData.lvLimit || 0)) return resResult(STATUS.LIMIT_LV); + + // 开启新一场 + const gameCode = genCode(8); + + const charaCards = getInitCharaCard() || []; + + let handleAddFun = new HandleAddCard(session, gameCode); + for (let ele of charaCards) { + handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []); + } + let result = await handleAddFun.save(); + await RougelikeRecordModel.updateByGameCode(gameCode, { + $set: { + roleId, grade, type, authorType: 0, curLayer: 0, + maxLayer: typeGradeData.layerCount, status: 0, takeoutReward: [], + }, + $inc: { score: 0, coin: 0, techScore: 0 } + }) + + return resResult(STATUS.SUCCESS, { gameCode, ...result }) + } + + /** + * 角色卡刷新 + * @param msg + * @param session + * @returns + */ + async refreshInitCharaCard(msg: { gameCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + + const { gameCode } = msg; + + let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + const { type = 0, grade = 0 } = dbRecord; + + await RougelikeCharaModel.deleteCharaByRoleId(roleId); + const charaCards = getInitCharaCard() || []; + let handleAddFun = new HandleAddCard(session, gameCode); + for (let ele of charaCards) { + handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []); + } + let result = await handleAddFun.save(); + + return resResult(STATUS.SUCCESS, { gameCode, charas: result?.addCharas || [] }) + } + + + /** + * 开启一场游戏 + * @param msg + * @param session + * @returns + */ + async startGame(msg: { gameCode: string, authorType: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + const { gameCode, authorType } = msg; + + // 检测流派 + const authorTypeData = gameData.rougeAuthorType.get(authorType); + if (!authorTypeData) return resResult(STATUS.NO_AUTHOR_TYPE); + + let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + // 未选角色 + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME) + // 存在一场正在进行中,不能开启新一场 + if (dbRecord.status != ROUGE_LIKE_STATUS.CHOOSECHARA) return resResult(STATUS.ROUGELIKE_GAME_PLAYING); + + const { type, grade, curLayer, maxLayer, } = dbRecord + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE); + + const typeGradeByIdData = gameData.rougeTypeGradeById.get(typeGradeData.limitId); + if (typeGradeByIdData) { + const dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.limitId) + if (!dbExtend) return resResult(STATUS.TYPE_UNLOCK); + } + + let nodes = getMap(typeGradeData.layerPlan, typeGradeData.layerCount); + + await RougelikeLayerModel.bulkWriteUpdate(nodes.map(cur => { return { ...cur, gameCode, roleId, status: 0 }; })); + await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { authorType, status: ROUGE_LIKE_STATUS.INPROGRESS } }); + + let { addCoin, cardIds } = await getEffectWhenGameStart(roleId, gameCode, authorType); + dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: addCoin, coinTotal: addCoin } }); + //任务 + if (addCoin > 0) { + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin }); + } + + + + const charas: CommonChara[] = formateCharasOrCards(await RougelikeCharaModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; + let handleAddFun = new HandleAddCard(session, gameCode); + handleAddFun.pushHolyCards(cardIds); + let result = await handleAddFun.save(); + result = await handleAddFun.getHolyEffect(); + + + return resResult(STATUS.SUCCESS, { gameCode, grade, coin: dbRecord.coin, coinTotal: dbRecord.coinTotal, type, authorType, curLayer, maxLayer, nodes, charas: [...charas, ...result.addCharas], cards: result.addCards }) + + } + + /** + * 结束游戏 + * @param msg + * @param session + * @returns + */ + async gameEnd(msg: { gameCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + const { gameCode } = msg; + let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + let { type, grade, status = 0, takeoutReward = [], hasReceivedTakeout = false, curLayer = 0, } = dbRecord; + if (status == ROUGE_LIKE_STATUS.SUCCESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + status = ROUGE_LIKE_STATUS.SUCCESS; + + const dbLayers = await RougelikeLayerModel.findByGameCode(gameCode); + + let takeoutRewardMap = takeoutReward.reduce((map, cur) => { map.set(cur.id, cur.count); return map; }, new Map()); + let spiritIds: number[] = []; + let addScore = 0, addTech = 0, isPass = true; + if (dbLayers.length == 0) isPass = false; + for (const { layer, hasPass = false, layerNodes } of dbLayers) { + if (layer > dbRecord.curLayer) { + isPass = false; + continue; + }; + const layerNodeOne = layerNodes.find(cur => cur.isChoose == 1); + let nodeType = layerNodeOne?.type || 0; + const detailCode = layerNodeOne?.detailCode; + + //忽略挑战关 + if (!hasPass && nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) { + isPass = false; + continue; + } + if (nodeType == ROUGE_LIKE_NODE_TYPE.QUEST_POINT) { + const dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode) + nodeType = dbDetail?.questType || 0; + } + const layerReward = getLayerRewardOneData(type, grade, layer, nodeType); + const { takeoutReward = [], score = 0, tech = 0, spiritPlan } = clone(layerReward); + addScore += score, addTech += tech; + for (const { id, count } of takeoutReward) takeoutRewardMap.set(id, takeoutRewardMap.get(id) || 0 + count); + for (const { id, count } of spiritPlan) { spiritIds.push(...getRandomSpirit(id, count)); } + } + let spiritMap = new Map(); + spiritIds.forEach((spiritId) => { + spiritMap.set(spiritId, { id: spiritId, count: (spiritMap.get(spiritId)?.count || 0) + 1 }); + }) + + takeoutReward = [...Array.from(takeoutRewardMap, ([id, count]) => ({ id, count })), ...spiritMap.values()]; + + + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { status, takeoutReward }, $inc: { score: addScore, techScore: addTech } }); + + let { score = 0, techScore = 0 } = dbRecord; + let dbScore = await RougelikeScoreModel.incScore(roleId, score); + let goods = await addItems(roleId, roleName, sid, [getRougeTechScoreObject(techScore)], ITEM_CHANGE_REASON.ROUGE_TECH_SCORE); + + let firstReward = []; + if (isPass) { + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + if (!typeGradeData || !typeGradeData.id) return resResult(STATUS.NO_TYPE_GRADE); + let dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.id); + if ((dbExtend?.limitId || 0) != typeGradeData.id) { + firstReward = await addItems(roleId, roleName, sid, typeGradeData?.firstReward || [], ITEM_CHANGE_REASON.ROUGE_FIRST_REWARD); + await RougelikeExtendModel.update(roleId, typeGradeData.id, firstReward, gameCode); + } + await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_ROUGE, { rougeId: typeGradeData.id, count: 1 }); + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GAME_COUNT, { count: 1 }); + } + + return resResult(STATUS.SUCCESS, { + gameCode, goods, score, techScore, hasReceivedTakeout, firstReward, + takeoutReward, weeklyScore: dbScore?.score || 0, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0 + }); + + } + + /** + * 选择外带奖励 + * @param msg + * @param session + */ + async takeoutReward(msg: { gameCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + const { gameCode } = msg; + let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + let { takeoutReward, hasReceivedTakeout } = dbRecord; + if (hasReceivedTakeout) return resResult(STATUS.ROUGELIKE_TAKEOUT_HAS_RECEIVED); + + let dbScore = await RougelikeScoreModel.receiveTakeoutReward(roleId, ROUGELIKE.TAKEOUT_REWARD_CNT); + if (!dbScore) return resResult(STATUS.ROUGELIKE_TAKEOUT_CNT_NOT_ENOUGH); + + dbRecord = await RougelikeRecordModel.takeout(gameCode); + + let goods = await addItems(roleId, roleName, sid, takeoutReward, ITEM_CHANGE_REASON.ROUGE_TAKE_OUT_REWARD) + + return resResult(STATUS.SUCCESS, { gameCode, hasReceivedTakeout: dbRecord?.hasReceivedTakeout || false, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0, goods }); + } + + /** + * 选择关卡节点 + * @param msg + * @param session + */ + async chooseNode(msg: { gameCode: string, layer: number, detailCode: string }, session: BackendSession) { + let chooseNodeStartTime = Date.now(); + + let roleId = session.get('roleId'); + const { gameCode, layer, detailCode } = msg; + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + const { curLayer, maxLayer, type, grade } = dbRecord; + + if (layer < curLayer || layer > maxLayer) return resResult(STATUS.NODE_NO_CHOOSE); + + let dbCurLayer = {} as RougelikeLayerType, dbPreLayer = {} as RougelikeLayerType; + let dbLayerNodes = await RougelikeLayerModel.findByGameCodeAndLayers(gameCode, [layer, layer - 1]); + + if (!dbLayerNodes) return resResult(STATUS.NODE_NO_CHOOSE); + for (let val of dbLayerNodes) { + if (val.layer == layer) { + if (val.hasPass) return resResult(STATUS.NODE_NO_CHOOSE);//当前关完成 + dbCurLayer = val; + } + // 注意过滤挑战点 + if ((val.layer || 0) == layer - 1 && layer - 1 > 0) { + let dbDetail = await RougelikeRecordDetailModel.findByGameCodeAndLayer(gameCode, layer - 1); + if (!val.hasPass && (!dbDetail || dbDetail.nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE)) return resResult(STATUS.NODE_NO_CHOOSE);//前一关未完成 + dbPreLayer = val; + } + } + + let dbIsChoose = dbCurLayer.layerNodes.find(cur => cur.isChoose == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE); + if (dbIsChoose && dbIsChoose.detailCode != detailCode) return resResult(STATUS.NODE_NO_CHOOSE); //该层已经选择过一关卡,不能再次选择其他关卡 + let dbCurLayerChooseNode: layerNode = dbCurLayer.layerNodes.find(cur => cur.detailCode == detailCode); + if (!dbCurLayerChooseNode) return resResult(STATUS.NODE_NO_CHOOSE); + if (dbPreLayer && Object.keys(dbPreLayer).length > 0) { + let dbPreLayerChooseNode = dbPreLayer.layerNodes.find(cur => cur.isChoose != 0); + if (dbCurLayerChooseNode.preNodeIndexs.indexOf(dbPreLayerChooseNode.index) == -1) return resResult(STATUS.NODE_NO_CHOOSE); + } + + + const curNode = await chooseNode(dbRecord, dbCurLayerChooseNode, layer) + + console.log('*********************************nodeType=%s, chooseNodeTime=%s', curNode?.nodeType, Date.now() - chooseNodeStartTime); + + return resResult(STATUS.SUCCESS, { detailCode, layer, curNode }) + } + + // 挑战关卡 + async checkBattle(msg: { gameCode: string, detailCode: string, warId: number, charaCodes: string[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + + const { gameCode, detailCode, warId, charaCodes } = msg; + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); + let { status = 0, rewards, layer, nodeType, warId: detailWarId = 0 } = dbDetail; + + if (status != 0 || warId != detailWarId) return resResult(STATUS.WAR_NO_CHOOSE); + + let dicWar = gameData.war.get(detailWarId); + if (!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const battleCode = genCode(8); // 关卡唯一值 + const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, charaCodes); + if (!dbCharas || dbCharas.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE); + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId: warId, status: 0, warName: dicWar.gk_name, warType: dicWar.warType, + record: { + rougeOriginal: dbCharas.map(cur => { + const { charaId, cards = [], hp = 0, ap = 0, shield = 0, roundSkill = 0, apSkill = 0 } = cur; + return { charaId, cards, hp, ap, roundSkill, apSkill } + }) + } + } + }, true); + return resResult(STATUS.SUCCESS, { gameCode, battleCode }); + } + + + /** + * 结束关卡 + * @param msg + * @param session + * @returns + */ + async battleEnd(msg: { gameCode: string, detailCode: string, battleCode: string, warId: number, status: number, round: number, rougeDamage: RougeDamageInter[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + let { gameCode, detailCode, battleCode, warId, status, round, rougeDamage } = msg; + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail || (dbDetail.warId || 0) != warId || warId == 0 || (dbDetail.status || 0) != 0) return resResult(STATUS.WAR_NO_CHOOSE); + let { layer, nodeType, questType = 0 } = dbDetail; + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, rougeDamage.map(cur => { return cur.charaCode })); + if (!dbCharas || dbCharas.length == 0 || dbCharas.length != rougeDamage.length) return resResult(STATUS.REWARD_NO_CHOOSE); + + await BattleRecordModel.findOneAndUpdate({ battleCode }, { + $set: { status, 'record.round': round, 'record.rougeDamage': rougeDamage, } + }, { new: true, upsert: true }).lean(true); + + const dbCharaMap = dbCharas.reduce((result, cur) => { result.set(cur.charaCode, { ...cur }); return result; }, new Map()); + + let isAp: boolean = false, isRound: boolean = false, arrAuthorType: number[] = [], isHpZero = false; + for (let obj of rougeDamage) { + if (obj.isAp) isAp = true; + if (obj.isRound) isRound = true; + const chara = dbCharaMap.get(obj.charaCode); + if (!chara) return resResult(STATUS.BATTLE_ABNORMAL) + obj.maxHp = (chara.maxHp || 0); + + if (!chara.cards || chara.cards.length == 0) console; + for (const { cardId } of chara.cards) { + const passiveCardData = gameData.rougePassiveCard.get(cardId); + if (nodeType == ROUGE_LIKE_NODE_TYPE.BOSS && passiveCardData && passiveCardData.authorType) arrAuthorType.push(passiveCardData.authorType); + } + if (!obj.hp || obj.hp == 0) isHpZero = true; + } + await updateChalleng(dbRecord, roleId, sid, gameCode, layer, rougeDamage, isAp, isRound); + + let updateCharas: RougelikeCharaPara[] = [], charas: CommonChara[] = []; + + + let recoveryHp = false; + if (status != 1 && nodeType != ROUGE_LIKE_NODE_TYPE.BOSS && isHpZero) { + recoveryHp = await getNoBossRecoveryHp(roleId, gameCode); + if (recoveryHp) status = 1; + } + + let hpRatio = 0; + if (status == 1) { + hpRatio = await getCharaHp(roleId, gameCode); + } + const minHp = rougeDamage.reduce((min, cur) => { return Math.min(min, cur.hp); }, Infinity); + let recoveryNum = 0; + if (minHp == 0) recoveryNum = await getBattleRecoveryNum(roleId, gameCode); + + + let updateCharasMap = new Map(); + for (let { charaCode, hp, ap, shield, others } of rougeDamage) { + const chara = dbCharaMap.get(charaCode); + if (!chara) return resResult(STATUS.BATTLE_ABNORMAL) + if (chara.maxHp < hp) hp = chara.maxHp; + + if (recoveryHp && hp == 0) hp = chara.maxHp; + if (hpRatio > 0 && hp != 0) hp = Math.min(Math.floor(hp + (chara.maxHp * hpRatio / 100)), chara.maxHp); + + if ((recoveryNum--) > 0 && hp == 0) { hp = chara.maxHp; } + + charas.push({ charaCode, charaId: chara.charaId, seqId: chara.seqId, cards: chara.cards, hp, maxHp: chara.maxHp, ap, shield, others, apSkill: chara.apSkill, roundSkill: chara.roundSkill }) + updateCharas.push({ gameCode, charaCode, hp, ap, shield, others }); + updateCharasMap.set(charaCode, { hp, ap, shield, others }); + } + + let incCoin = 0; + if (status == 1) { + let { coinRatio, coinAdd } = await getAddCoin(roleId, gameCode, nodeType); + let newNodeType = nodeType; + if (questType > 0) newNodeType = questType; + const layerReward = getLayerRewardOneData(dbRecord.type, dbRecord.grade, layer, newNodeType); + incCoin = Math.floor((layerReward.coin || 0) * (1 + coinRatio / 100) + coinAdd); + await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } }); + + //battleEnd 主动将hasPass置为true + await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }); + } + + // let coinReward = rewards.find(cur => cur.rewardType == 0); + // if (coinReward) coinReward.chooseNum = Math.floor(coinReward.chooseNum * (1 + coinRatio / 100) + coinAdd); + // if (coinRatio != 0 || coinAdd != 0) { + // await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.rewardType': 0 }, { 'rewards.$.chooseNum': coinReward.chooseNum, }, { new: true, upsert: true }).lean(true); + // } + + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } }) + + if (incCoin > 0) { + charas = await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade, updateCharasMap) + + //任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin: incCoin }); + + } else { + await RougelikeCharaModel.bulkWriteUpdate(updateCharas); + } + + if (status == 1 && arrAuthorType.length > 0 && arrAuthorType.every(cur => cur == arrAuthorType[0])) { + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_BOSS_PASS, { authorType: arrAuthorType[0], count: 1 }); + } + + await getEnterGame(roleId, gameCode); + + return resResult(STATUS.SUCCESS, { status, gameCode, detailCode, charas, incCoin }); + } + + // 重置 + async reRandomReward(msg: { gameCode: string, detailCode: string, rewardType: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const { gameCode, detailCode, rewardType } = msg; + + // 检查数量 + let { canReRandom, costCoin } = await checkCanReRandomReward(roleId, gameCode, rewardType); + if (!canReRandom) return resResult(STATUS.ROUGE_TECH_NOT_UNLOCKED); + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); + + let dbDetailReward = dbDetail.rewards.find(cur => cur.rewardType == rewardType); + if (!dbDetailReward || dbDetailReward.reRandRewardCnt > 0) return resResult(STATUS.ROUGE_RE_RANDOM_CNT_OVER); + + const typeGradeData = gameData.rougeTypeGrade.get(dbRecord.type + '_' + dbRecord.grade); + const nodeData = gameData.rougeNode.get(dbDetail.nodeId); + if (!typeGradeData || !nodeData) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + dbDetail.layer); + if (!layerPlanData) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let costResult = await RougelikeRecordModel.costCoin(gameCode, costCoin); + if (!costResult) return resResult(STATUS.COIN_NOT_ENOUGH); + + let replaceReward = await getLayerNodeReward(roleId, gameCode, dbRecord.authorType, dbDetail.nodeId, layerPlanData.rewardPlan, dbDetail.layer, dbDetail.questType); + let { rewards } = dbDetail; + if (replaceReward && replaceReward.rewards.length > 0) { + let newRewards = [...rewards.filter(reward => reward.rewardType != rewardType), ...replaceReward.rewards.filter(reward => reward.rewardType == rewardType)].map(reward => ({ ...reward, reRandRewardCnt: 1 })).sort((a, b) => a.groupIndex - b.groupIndex); + dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards: newRewards } }); + } + + return resResult(STATUS.SUCCESS, { rewards: dbDetail.rewards }); + } + + /** + * 选择奖励 + * @param msg + * @param session + * @returns + */ + async chooseReward(msg: { gameCode: string, detailCode: string, groupIndex: number, optionIndexs: number[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + const { gameCode, detailCode, groupIndex, optionIndexs } = msg; + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE); + let { status, rewards, layer, nodeType, warId = 0, challenge } = dbDetail; + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + // 检测有关卡的是否挑战成功 + if (warId != 0 && status != 1) return resResult(STATUS.REWARD_NO_CHOOSE); + + if (!rewards || rewards.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE); + let { rewardType, options, groupStatus, chooseNum } = rewards.find((obj) => obj.groupIndex == groupIndex); + + // if (groupStatus == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return resResult(STATUS.REWARD_NO_CHOOSE); + + let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); + let incCoin = 0, redCoin = 0; + // //处理下试炼币 + // if (rewardType == 0) { + // incCoin = chooseNum; + // groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; + // const result = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.groupIndex': groupIndex }, { 'rewards.$.groupStatus': groupStatus, }, { new: true, upsert: true }).lean(true); + // if (result.rewards.find((obj) => obj.groupStatus != ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) == undefined) { + // await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) + // } + // await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } }) + // return resResult(STATUS.SUCCESS, { addCharas: await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade), addCards: [], incCoin, redCoin }); + // } + + + // 特性卡可以选多次 + let passiveChooseCount = 0; + if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE || rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) { + passiveChooseCount = options.reduce((accumulator, obj) => { + if (obj.optionStatus === ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return accumulator + 1; + return accumulator; + }, 0); + if (chooseNum - passiveChooseCount < optionIndexs.length) return resResult(STATUS.REWARD_NO_CHOOSE); + } + + if (optionIndexs.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE); + + let tempOptions: RewardOption[] = options.filter(opt => optionIndexs.includes(opt.optionIndex)); + if (tempOptions.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE); + + for (let { rewardId, passiveCardIds, optionStatus, optionIndex } of tempOptions) { + if (optionStatus != 0) return resResult(STATUS.REWARD_NO_CHOOSE); + let cardCode = genCode(8); + if (rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) { + // 更新角色卡 + handleAddFun.pushChara(rewardId, await getMaxHp(roleId, gameCode, rewardId, dbRecord.type, dbRecord.grade), passiveCardIds || []); + //休整点 消耗 + if (nodeType == ROUGE_LIKE_NODE_TYPE.REST_POINT) { + let charaData = gameData.rougeChara.get(rewardId); + if (!charaData) return; + redCoin += charaData.recruitConsume || 0; + } + } else { + // 更新特性卡or圣物 + handleAddFun.pushCard(rewardId, rewardType); + } + optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; + options.forEach((ele) => { if (ele.optionIndex == optionIndex) ele.optionStatus = optionStatus; }); + } + + if ((dbRecord.coin || 0) < redCoin) return resResult(STATUS.COIN_NOT_ENOUGH); + if (redCoin > 0) await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -redCoin } }); + + groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; + + if (nodeType == ROUGE_LIKE_NODE_TYPE.CHALLENGE) { + // 挑战关领奖更新 + await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) + } else { + // 更新进度 + await updateChalleng(dbRecord, roleId, sid, gameCode, layer, []); // 更新挑战进度 + } + + await RougelikeRecordDetailModel.updateRewardByGroupIndex(gameCode, detailCode, groupIndex, groupStatus, options); + + let addResult = await handleAddFun.save(); + addResult = await handleAddFun.getHolyEffect(); + + return resResult(STATUS.SUCCESS, { ...addResult, incCoin, redCoin }); + + } + + + /** + * 商店购买 + * @param msg + * @param session + * @returns + */ + async shopBuy(msg: { gameCode: string, detailCode: string, optionIndex: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + let { gameCode, detailCode, optionIndex } = msg; + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.SHOP_NO_BUY); + + let { status = 0, shops, layer, nodeType } = dbDetail; + if (status == 1 || !shops || shops.length == 0) return resResult(STATUS.SHOP_NO_BUY); + + let shop = shops.find((obj) => obj.optionIndex == optionIndex); + if (!shop || shop.optionStatus != ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE) return resResult(STATUS.SHOP_NO_BUY); + + let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode); + if (!dbRecord || (dbRecord.coin || 0) < shop.discountPrice) return resResult(STATUS.COIN_NOT_ENOUGH); + + + shop.optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE; + + await RougelikeRecordDetailModel.updateShopByCode(gameCode, detailCode, optionIndex, shop.optionStatus); + await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { coin: (dbRecord.coin || 0) - shop.discountPrice } }); + + let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); + handleAddFun.pushCard(shop.rewardId, shop.rewardType); + let result = await handleAddFun.save(); + result = await handleAddFun.getHolyEffect(); + + return resResult(STATUS.SUCCESS, { curShop: shop, ...result, redCoin: -shop.discountPrice }); + + } + + /** + * 结束这一节点 + * @param msg + * @param session + * @returns + */ + async nodeEnd(msg: { gameCode: string, detailCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + const { gameCode, detailCode } = msg; + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.NO_EXIT_NODE); + let { layer, nodeType, status = 0, shops, warId = 0 } = dbDetail; + if ((warId != 0 && status != 1)) { + //检测关卡是否挑战成功 + return resResult(STATUS.NODE_NO_END) + } + status = 1; + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } }); + if (nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) { + await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }); + } + + return resResult(STATUS.SUCCESS, { gameCode, detailCode, status, ...await getGame(roleId) }) + } + + + /** + * 问号点选择题 + * @param msg + * @param session + * @returns + */ + async chooseOption(msg: { gameCode: string, detailCode: string, eventOptions: number[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + const { gameCode, detailCode, eventOptions } = msg; + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); + let { layer, nodeType, status = 0, question = {} as Quest } = dbDetail; + if (status == 1) return resResult(STATUS.NODE_NO_CHOOSE); + + let checkAfterGroup = 0, optionGroupIds: number[] = []; + let handleAddFun = new HandleAddCard(session, gameCode, dbDetail); + for (let [index, id] of eventOptions.entries()) { + const rougeEventOptionData = gameData.rougeEventOption.get(id); + if (!rougeEventOptionData) return resResult(STATUS.NODE_NO_CHOOSE); + const { randomEventId, optionGroup, afterGroup, holyCardPlan } = rougeEventOptionData; + + if (randomEventId != (question.randomEventId || 0)) return resResult(STATUS.NODE_NO_CHOOSE); + + if (index != 0 && checkAfterGroup != optionGroup) return resResult(STATUS.NODE_NO_CHOOSE); + if (!optionGroupIds.includes(optionGroup)) optionGroupIds.push(optionGroup); + + if (!question.EventOptions) question.EventOptions = []; + question.EventOptions.push(id); + checkAfterGroup = afterGroup; + + const rougeHolyCardPlanData = gameData.rougeHolyCardPlan.get(holyCardPlan); + if (!rougeHolyCardPlanData || rougeHolyCardPlanData.length == 0) continue; + let newCards = []; + let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); + for (let obj of rougeHolyCardPlanData) { + let holyCardData = gameData.rougeHolyCard.get(obj.cardId); + if (!holyCardData) continue; + const getLimit = cardsMap.get(obj.cardId) || 0; + if (getLimit >= (holyCardData?.getLimit || 0)) continue; //处理限制获取数量 + newCards.push(obj); + } + let cardId = 0; + if (newCards.length > 0) { + cardId = getRandEelmWithWeight(newCards).dic.cardId; + } + + if (cardId > 0) handleAddFun.pushHolyCard(cardId); + } + + status = 1; + + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { question, status } }) + await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } }) + + let result = await handleAddFun.save(); + await handleAddFun.getHolyEffect(); + + await addSameTypeCollect(roleId, sid, gameCode, COLLECTION_TYPE.EVENT, optionGroupIds); + //任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_EVENT_COLLECT, { eventGroups: optionGroupIds }); + + return resResult(STATUS.SUCCESS, { ...result }) + } + + + /** + * 休整点恢复 + * @param msg + * @param session + * @returns + */ + async recovery(msg: { gameCode: string, detailCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + + const { gameCode, detailCode } = msg; + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); + let { restPoints = [], nodeType, status, rewards } = dbDetail; + if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE); + + let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.RECOVERY) || new RestPoint(); + if (restPoint.recoveryCnt && restPoint.recoveryCnt > 0) return resResult(STATUS.NO_TIME_RECOVERY); + restPoint.recoveryCnt = 1; + restPoint.restType = REST_POINT_TYPE.RECOVERY; + restPoint.recoveryCharas = []; + let dbCharas = await RougelikeCharaModel.findByGameCode(gameCode); + let updateCharas: RougelikeCharaPara[] = []; + + let hpRatio = await getRecoveryExtendHp(roleId, gameCode); + for (let { gameCode, charaCode, charaId, cards, hp = 0, maxHp = 0, ap, shield, roundSkill, apSkill } of dbCharas) { + if (hp == 0) continue; + let beforeHp = hp; + hp = Math.floor(Math.min(hp + maxHp * ROUGELIKE.RECOVERY_RATIO / 100 + maxHp * hpRatio / 100, maxHp)); + updateCharas.push({ gameCode, charaCode, hp }); + restPoint.recoveryCharas.push({ charaCode, charaId, beforeHp, afterHp: hp }); + } + restPoints.push({ restType: restPoint.restType, recoveryCnt: restPoint.recoveryCnt, recoveryCharas: restPoint.recoveryCharas }); + + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } }); + await RougelikeCharaModel.bulkWriteUpdate(updateCharas); + + const charas: CommonChara[] = formateCharasOrCards(dbCharas, ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; + + return resResult(STATUS.SUCCESS, { restPoints, charas, reward: { rewards } }) + } + + /** + * 休整点强化 + * @param msg + * @param session + */ + async trainCard(msg: { gameCode: string, detailCode: string, cardCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + + const { gameCode, detailCode, cardCode } = msg; + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode) + if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME); + if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END); + + let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE); + let { layer, nodeType, status = 0, question, restPoints = [], rewards } = dbDetail; + if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE); + + let dbCard = await RougelikeCardModel.findByCode(gameCode, cardCode); + if (!dbCard) return resResult(STATUS.NO_CARD); + let { type, cardId, charaId = 0, lv = 0 } = dbCard; + + const passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData) return resResult(STATUS.NO_CARD); + const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0); + if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return resResult(STATUS.HIGH_LV); + let passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map()); + if (!passiveCardDataMap.has(lv + 1)) return resResult(STATUS.HIGH_LV); + + const strengthConsume = passiveCardData.strengthConsume || 0; + const { lv: cardLv, id } = passiveCardDataMap.get(lv + 1); + if (lv == cardLv) return resResult(STATUS.HIGH_LV); + + let realConsume = Math.floor(strengthConsume * await getTrainCardDiscount(roleId, gameCode) / 100); + if ((dbRecord.coin || 0) < realConsume) return (STATUS.COIN_NOT_ENOUGH); + + let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.TRAIN) || new RestPoint(); + restPoint.restType = REST_POINT_TYPE.TRAIN; + if (!restPoint.trainCardCnt) restPoint.trainCardCnt = 0; + restPoint.trainCardCnt += 1; + if (!restPoint.trainCards) restPoint.trainCards = []; + restPoint.trainCards.push({ cardCode, cardId: id, beforeLv: lv, afterLv: lv + 1 }); + + if (restPoints.find(cur => cur.restType == restPoint.restType) == undefined) { + restPoints.push({ restType: restPoint.restType, trainCardCnt: restPoint.trainCardCnt, trainCards: restPoint.trainCards }) + } + else restPoints.forEach(obj => { + if (obj.restType == restPoint.restType) { + obj.trainCardCnt = restPoint.trainCardCnt; + obj.trainCards = restPoint.trainCards; + } + + }) + await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -realConsume } }); + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } }); + const newDbCard = await RougelikeCardModel.updateByCode(gameCode, cardCode, { $set: { cardId: id }, $inc: { lv: 1 } }); + const cards: CommonCard[] = formateCharasOrCards([newDbCard], ROUGE_LIKE_CARD_TYPE.PASSIVE)?.cards || []; + + if (charaId > 0) { + const dbCharas = await RougelikeCharaModel.findByGameCodeAndCharaId(gameCode, charaId); + let isEnd = false; + for (let { cards = [], charaCode } of dbCharas) { + for (let obj of cards) { + if (cardCode != obj.cardCode) continue; + obj.cardId = id; + await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode, 'cards.cardCode': cardCode }, { 'cards.$.cardId': id }, { new: true, upsert: true }).lean(true); + isEnd = true; + break; + } + if (isEnd) break; + } + } + + return resResult(STATUS.SUCCESS, { restPoints, cards, reward: { rewards }, redCoin: -realConsume, }) + + } + + /** + * 选择一张技能卡 + * @param msg + * @returns + */ + async chooseSkillCard(msg: { gameCode: string, charaCode: string, skillType: number, id: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + const { gameCode, charaCode, skillType, id } = msg; + + let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode); + if (!dbChara) return resResult(STATUS.NO_CARD); + + if (id > 0) { + const dicSkillCard = gameData.rougeSkillCard.get(id); + if (!dicSkillCard) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicSkillCard.skillType != skillType) return resResult(STATUS.WRONG_PARMS); + + // 检查数量 + if (!await checkCanChooseSkillCard(roleId, gameCode, id, dbChara.cards)) + return resResult(STATUS.ROUGE_PASSIVE_CARD_NOT_ENOUGH); + } + + let chara = await RougelikeCharaModel.putOnOrOffSkillCard(gameCode, charaCode, skillType, id); + if (!dbChara) return resResult(STATUS.NO_CARD); + // 更新图鉴 + await addSingleCollect(roleId, sid, gameCode, COLLECTION_TYPE.SKILL_CARD, id); + + // 任务 + let dicSkillCard = gameData.rougeSkillCard.get(id); + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT, { authorType: dicSkillCard.authorType, cardType: TASK_ROUGE_CARD_TYPE.SKILL, cardIds: [id] }); + + return resResult(STATUS.SUCCESS, { + curChara: new CommonChara(chara) + }) + } + + /** + * 安装或者卸下特性卡 + * @param msg + * @param session + */ + async putOnOrOffCard(msg: { gameCode: string, charaCode: string, cards: SlotCard[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let { gameCode, charaCode, cards } = msg; + + // 获取角色卡db数据 + let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode); + if (!dbChara) return resResult(STATUS.NO_CARD); + if (!dbChara.cards || dbChara.cards.length == 0) return resResult(STATUS.SLOT_UNLOCK); + let dbCharaCardsMap = dbChara.cards.reduce((result, cur) => { result.set(cur.index, cur); return result; }, new Map()); + + // 获取需要安装、卸下的特性卡db数据 + let cardCodes: string[] = []; + cards.forEach((ele) => { cardCodes.push(ele.cardCode); }); + dbChara.cards.forEach((ele) => { cardCodes.push(ele.cardCode); }) + let dbCards: RougelikeCardType[] = await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes); + if (dbCards.length == 0) return resResult(STATUS.NO_CARD); + let dbCardsMap = dbCards.reduce((result, cur) => { result.set(cur.cardCode, cur); return result; }, new Map()); + + let newCardsMap = new Map(); + for (let { index, cardCode } of cards) { + // 检测卡槽解锁 + let slot = dbCharaCardsMap.get(index) + if (!slot) return resResult(STATUS.SLOT_UNLOCK); + + //处理旧的cardCode + let oldSotCardCode = clone(slot.cardCode); + let updateObj = dbCardsMap.get(oldSotCardCode); + if (updateObj) { + updateObj.charaId = 0; + dbCardsMap.set(oldSotCardCode, updateObj); + newCardsMap.set(oldSotCardCode, updateObj); + } + + //处理新的cardCode安装 + let update = dbCardsMap.get(cardCode); + dbCharaCardsMap.set(index, { index, cardCode: cardCode, cardId: update?.cardId || 0 }); + if (update) { + if (update.type != ROUGE_LIKE_CARD_TYPE.PASSIVE) return resResult(STATUS.NO_PASSIVE); + update.charaId = dbChara.charaId; + dbCardsMap.set(cardCode, update); + newCardsMap.set(cardCode, update); + } + } + let newCards = Array.from(dbCharaCardsMap.values()); + let tempCards = new Map(); + for (let { cardId } of newCards) { + if (!cardId) continue; + if (tempCards.has(cardId)) return resResult(STATUS.ROUGE_NO_CAN_PUT_SAME_ID); + tempCards.set(cardId, cardId); + } + + // 如果卸下之后技能卡需要的被动卡不够,需要把技能卡卸下 + let { apSkill, roundSkill } = dbChara; + if (apSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, apSkill, newCards)) apSkill = 0; + if (roundSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, roundSkill, newCards)) roundSkill = 0; + + //更新角色卡db, 特性卡db + let newChara = await RougelikeCharaModel.updateByCode(gameCode, charaCode, { $set: { cards: newCards, apSkill, roundSkill } }); + await RougelikeCardModel.bulkWriteUpdate(Array.from(newCardsMap.values()).map(obj => ({ gameCode, cardCode: obj.cardCode, charaId: obj.charaId }))) + let curCards = Array.from(dbCardsMap.values()).map(obj => ({ cardCode: obj.cardCode, type: obj.type, charaId: obj.charaId, lv: obj.lv })); + + return resResult(STATUS.SUCCESS, { curCards, curChara: new CommonChara(newChara) }) + } + + + async exchangeChara(msg: { gameCode: string, oldCharaCode: string, newCharaCode: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + const { gameCode, oldCharaCode, newCharaCode } = msg; + const result = await RougelikeCharaModel.findByCodes(gameCode, [oldCharaCode, newCharaCode]); + if (result.length != 2) return (STATUS.NO_CARD); + let oldChara = {} as RougelikeCharaType, newChara = {} as RougelikeCharaType; + for (let val of result) { + if (val.charaCode == oldCharaCode) oldChara = val; + if (val.charaCode == newCharaCode) newChara = val; + } + + let temp = clone(newChara.seqId); + newChara.seqId = clone(oldChara.seqId); + oldChara.seqId = temp; + // 更新角色卡 + await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]); + let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas; + + + // // 处理新卡 + // let { charaCode, charaId, maxHp, seqId } = newChara; + // newChara = clone(oldChara); + // newChara.charaCode = charaCode; + // newChara.charaId = charaId; + // newChara.maxHp = maxHp; + + // let cardCodes = []; + // let updateArr: RougelikeCardPara[] = []; + // for (let val of newChara.cards) { + // cardCodes.push(val.cardCode); + // updateArr.push({ gameCode, cardCode: val.cardCode, charaId }); + // } + + // // 处理旧卡 + // oldChara.cards.forEach((cur) => { cur.cardCode = '', cur.cardId = 0 }); + // oldChara.ap = oldChara.apSkill = oldChara.roundSkill = 0; + // oldChara.seqId = seqId; + + // // 更新角色卡 + // await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]); + + // let cards = formateCharasOrCards(await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes), ROUGE_LIKE_CARD_TYPE.PASSIVE).cards; + // // 更新card + // await RougelikeCardModel.bulkWriteUpdate(updateArr); + + // let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas; + + return resResult(STATUS.SUCCESS, { charas }); + } + + /** + * 解锁科技点 + * @param msg + * @param session + */ + async unlockTech(msg: { techId: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + const { techId } = msg; + + let dicTech = gameData.rougeTech.get(techId); + if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let techRecord = await RougelikeTechModel.findByRoleId(roleId); + let { unlockedTech = [] } = techRecord || {}; + if (unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_TECH_HAS_UNLOCKED); + if (!checkPreRougeTech(techId, unlockedTech)) return resResult(STATUS.ROUGE_TECH_PRE_NOT_UNLOCKED); + + // 检查消耗 + let costResult = await handleCost(roleId, sid, dicTech.cost, ITEM_CHANGE_REASON.ROUGE_UNLOCK_TECH); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let circleIds = gameData.rougeCircleByTech.get(techId) || []; + techRecord = await RougelikeTechModel.unlockTech(roleId, techId, circleIds); + if (!techRecord) return resResult(STATUS.ROUGE_TECH_SCORE_NOT_ENOUGH); + await updateEffectId(techRecord); + + let resultData = getCurTechData(techRecord, techId); + //任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_TECH_OPEN, { count: 1 }); + + return resResult(STATUS.SUCCESS, { + ...resultData + }); + } + + /** + * 放置法阵 + * @param msg + * @param session + * @returns + */ + async putOnCircle(msg: { circleId: number, hid: number }, session: BackendSession) { + + let roleId: string = session.get('roleId'); + const { circleId, hid } = msg; + + let techId = gameData.rougeTechCircle.get(circleId); + if (!techId) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let dicTech = gameData.rougeTech.get(techId); + if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let techRecord = await RougelikeTechModel.findByRoleId(roleId); + if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); + let { unlockedTech = [] } = techRecord; + if (!unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); + + let ce = 0; + if (hid != 0) { + let hero = await HeroModel.findByHidAndRole(hid, roleId, 'ce'); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + ce = hero.ce || 0; + } + + techRecord = await RougelikeTechModel.putOnCircle(roleId, circleId, hid, ce); + if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK); + await updateEffectId(techRecord); + + let resultData = getCurTechData(techRecord, techId); + return resResult(STATUS.SUCCESS, { + ...resultData + }); + } + + /** + * 领取图鉴奖励 + * @param msg + * @param session + * @returns + */ + async receiveCollectionReward(msg: { type: number, id: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let { type, id } = msg; + + let dic: DicRougePassiveCollect | DicRougeHolyCard | DicRougeSkillCard | DicRougeOptionGroup; + let num = 1; + if (type == COLLECTION_TYPE.PASSIVE_CARD_SUM) { + dic = gameData.rougePassiceCollect.get(id); + num = dic?.num || 0; + } else if (type == COLLECTION_TYPE.HOLY_CARD) { + dic = gameData.rougeHolyCard.get(id); + } else if (type == COLLECTION_TYPE.SKILL_CARD) { + dic = gameData.rougeSkillCard.get(id); + } else if (type == COLLECTION_TYPE.EVENT) { + dic = gameData.rougeOptionGroup.get(id); + } + if (!dic) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let collect = await RougelikeCollectionModel.findByRoleAndId(roleId, type, id); + if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH); + if (collect.received.includes(id)) return resResult(STATUS.ROUGE_COLLECT_HAS_RECEIVED); + + collect = await RougelikeCollectionModel.receive(roleId, type, id, num); + if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH); + let goods = await addItems(roleId, roleName, sid, dic.collectReward, ITEM_CHANGE_REASON.RECEIVE_COLLECT_REWARD); + + return resResult(STATUS.SUCCESS, { + goods, curCollection: new CollectionReturnParam(collect) + }); + } + + /** + * 领取积分奖励 + * @param msg + * @param session + * @returns + */ + async receiveScore(msg: { index: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let roleName: string = session.get('roleName'); + let { index } = msg; + const lastMaxLv = await RougelikeExtendModel.getLastMaxLv(roleId); + const rougeScoreRewardByLvData = gameData.rougeScoreRewardByLv.get(lastMaxLv); + if (!rougeScoreRewardByLvData) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicScore = rougeScoreRewardByLvData.get(index); + if (!dicScore) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let scoreData = await RougelikeScoreModel.findByRoleId(roleId); + if (!scoreData || scoreData.score < dicScore.score) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH); + if (scoreData.received.includes(index)) return resResult(STATUS.ROUGE_SCORE_HAS_RECEIVED); + + scoreData = await RougelikeScoreModel.receive(roleId, dicScore.score, index); + if (!scoreData) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH); + + let goods = await addItems(roleId, roleName, sid, dicScore.reward, ITEM_CHANGE_REASON.RECEIVE_ROUGE_SCORE_REWARD); + return resResult(STATUS.SUCCESS, { + receivedScore: scoreData.received, + goods + }); + } + + async challengeRandom(msg: { detailCode: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + const { detailCode } = msg; + let dbDetail = await RougelikeRecordDetailModel.findByDetailCode(detailCode); + if (!dbDetail) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + let { gameCode, layer, nodeId, nodeType, rewards = [], challenge } = dbDetail; + if (rewards.length > 0 || nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE || (challenge?.status || 0) < 2) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + + const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode); + if (!dbRecord) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + const { authorType, type, grade } = dbRecord; + + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + if (!typeGradeData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); + if (!layerPlanData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer); + if (!result || !result.rewards) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + rewards = result.rewards; + + dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards } }); + if (!dbDetail || !dbDetail.rewards) resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL); + + return resResult(STATUS.SUCCESS, { gameCode, detailCode, reward: { rewards: dbDetail.rewards } }) + } + + /** + * debug接口,清空科技树 + * @param msg + * @param session + * @returns + */ + async debugClearTech(msg: {}, session: BackendSession) { + let roleId: string = session.get('roleId'); + await RougelikeTechModel.clearTech(roleId); + return resResult(STATUS.SUCCESS); + } + + async debugAddCard(msg: { type: number, id: number }, session: BackendSession) { + let { type, id } = msg; + + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); + if (!dbRecord) { + return resResult(STATUS.NO_ROUGELIKE_GAME); + } + + let handleAddFun = new HandleAddCard(session, dbRecord.gameCode); + if (type == ROUGE_LIKE_CARD_TYPE.CHARA) { + handleAddFun.pushChara(id, await getMaxHp(roleId, dbRecord?.gameCode || '', id, dbRecord.type, dbRecord.grade), []); + } else if (type == ROUGE_LIKE_CARD_TYPE.HOLY) { + handleAddFun.pushHolyCard(id); + } else if (type == ROUGE_LIKE_CARD_TYPE.PASSIVE) { + handleAddFun.pushPassiveCard(id); + } else { + return resResult(STATUS.WRONG_PARMS); + } + let result = await handleAddFun.save(); + result = await handleAddFun.getHolyEffect(); + return resResult(STATUS.SUCCESS, result); + } + + // debug接口 + async debugAddCollection(msg: { type: number, id: number }, session: BackendSession) { + let { type, id } = msg; + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); + if (!dbRecord) { + return resResult(STATUS.NO_ROUGELIKE_GAME); + } + await addSingleCollect(roleId, sid, dbRecord.gameCode, type, id); + + return resResult(STATUS.SUCCESS); + } + + async debugAddScore(msg: { score: number }, session: BackendSession) { + let { score } = msg; + let roleId: string = session.get('roleId'); + let result = await RougelikeScoreModel.incScore(roleId, score); + return resResult(STATUS.SUCCESS, { weeklyScore: result.score }) + } + + async debugRepaireScoreReward() { + await repaireSendScoreReward(); + return resResult(STATUS.SUCCESS); + } + /** + * debug添加试炼通关 + * @param msg + * @param session + * @returns + */ + async debugAddLimitId(msg: { id: number }, session: BackendSession) { + const { id } = msg; + const roleId: string = session.get('roleId'); + const typeGradeByIdData = gameData.rougeTypeGradeById.get(id); + if (typeGradeByIdData) { + // for (let i = 3; i <= 42; i++) { + await RougelikeExtendModel.update(roleId, id, [], genCode(8)); + + // } + } + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/battle/handler/towerBattleHandler.ts b/game-server/app/servers/battle/handler/towerBattleHandler.ts index 68baacef9..d43936561 100644 --- a/game-server/app/servers/battle/handler/towerBattleHandler.ts +++ b/game-server/app/servers/battle/handler/towerBattleHandler.ts @@ -1,399 +1,400 @@ -import { STATUS } from './../../../consts/statusCode'; -import { HANG_UP_CONSTS, ITEM_CHANGE_REASON, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE, REDIS_KEY } from './../../../consts'; -import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from './../../../db/TowerTaskRec'; -import { HangUpSpdUpRecModel } from './../../../db/HangUpSpdUpRec'; -import { HangUpRecordModel } from './../../../db/HangUpRecord'; -import { RoleModel } from './../../../db/Role'; -import { TowerRecordModel, WarStatus } from './../../../db/TowerRecord'; -import { Application, BackendSession } from 'pinus'; -import { resResult, genCode, shouldRefresh } from '../../../pubUtils/util'; -import { calcuHangUpReward, refreshTasks, treatTask, getRemainTime, getTowerStatus, getHungupRewards, getTasks, checkTaskRewards, getTowerTaskCostGold, getManyHangSpdUpCostGold, getTaskStatus, checkForbiddenChar, checkAndStartHungUp, createNewTowerRecord, getTowerRecByLv, getTowerStatusByWarId, getTowerHeroCe, getWarStatusByLv } from '../../../services/battleService'; -import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { checkBattleHeroes } from '../../../services/normalBattleService'; -import { gameData } from '../../../pubUtils/data'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { HeroModel } from '../../../db/Hero'; -import { vipCanSkipTower } from '../../../services/activity/monthlyTicketService'; -import { pushTowerMsg } from '../../../services/sysChatService'; -import { WarStar } from '../../../domain/dbGeneral'; -import { ItemInter, RewardInter } from '../../../pubUtils/interface'; -import { combineItems } from '../../../services/role/util'; -import { checkTaskInSkipTower } from '../../../services/task/taskService'; -import { Rank } from '../../../services/rankService'; -import { checkPopUpCondition } from '../../../services/activity/popUpShopService'; -import { isHeroHidden } from '../../../services/dataService'; - -export default function(app: Application) { - return new TowerBattleHandler(app); -} - -export class TowerBattleHandler { - constructor(private app: Application) { - } - - /** - * 获取天梯当前挑战状态 - * @param session - */ - async getStatus(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let role = await RoleModel.findByRoleId(roleId, 'roleId serverId towerLv towerReceived'); - let data = await getTowerStatus(role); - - return resResult(STATUS.SUCCESS, data); - } - - /** - * 重置天梯当前层的挑战记录 - * @param towerLv 要重置的天梯层数 - * @param session - */ - async resetLv(msg: {towerLv: number}, session: BackendSession) { - let roleId = session.get('roleId'); - let { towerLv } = await RoleModel.findByRoleId(roleId); - if (msg.towerLv !== towerLv) { - return resResult(STATUS.TOWER_RESET_ERR); - } - const record = await TowerRecordModel.resetRecordByLv(roleId, towerLv); - if (!record) { - return resResult(STATUS.TOWER_NOT_FOUND); - } - - return resResult(STATUS.SUCCESS, { - roleId: record.roleId, - curLv: record.lv, - heroes: record.heroes, - warStatus: record.warStatus, - speedUpCnt: record.speedUpCnt, - speedUpTime: record.speedUpTime, - hangUpTime: record.hangUpTime, - passed: record.passed - - }); - } - - /** - * 查询当前挂机可得奖励 - * @param msg - * @param session - * @returns - */ - async checkHangUpRewards(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let result = await getHungupRewards(roleId); - if(!result) { - return resResult(STATUS.TOWER_HANG_UP_NOT_START); - } - return resResult(STATUS.SUCCESS, result); - } - - /** - * 领取当前挂机可得奖励 - * @param msg - * @param session - * @returns - */ - async recHangUpRewards(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - let role = await RoleModel.findByRoleId(roleId); - const result = await calcuHangUpReward(role); - if(!result) { - return resResult(STATUS.TOWER_HANG_UP_NOT_START); - } - let { timeReward, endLv, endTime, deltaTime, needReceiveGoods } = result; - - const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD); - await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods); - - return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), goods }); - } - - /** - * 加速挂机 - * @param {{speedUpCnt: number}} msg 加速次数 - * @param session - * @returns - */ - async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let { speedUpCnt } = msg; - - const curTime = new Date(); - - let role = await RoleModel.findByRoleId(roleId); - let { hangUpSpdUpCnt, gold, lastSpdUpTime } = role; - if (shouldRefresh(lastSpdUpTime, curTime)) { - hangUpSpdUpCnt = 0; - } - if (speedUpCnt + hangUpSpdUpCnt > dicParam.TOWER_BOOST.TOWER_BOOSTTIME) { - return resResult(STATUS.TOWER_NOT_ENOUGH_HANG_UP_TIME) - } - - const calResult = await calcuHangUpReward(role, true, msg.speedUpCnt, curTime); - if(!calResult) { - return resResult(STATUS.TOWER_HANG_UP_FAILED); - } - let { timeReward, endLv, deltaTime, needReceiveGoods } = calResult; - - const costGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, msg.speedUpCnt); - if(costGold > gold) { - return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); - } - - await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.TOWER_HUNG_UP_SDP_UP) - - const spdUpResult = await RoleModel.hangUpSpdUp(roleId, msg.speedUpCnt, curTime); - if (!spdUpResult) { - return resResult(STATUS.TOWER_HANG_UP_FAILED); - } - const spdUpRec = await HangUpSpdUpRecModel.updateRec(roleId, roleName, msg.speedUpCnt, endLv, needReceiveGoods); - const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD); - let nextCostGold = getManyHangSpdUpCostGold(spdUpResult.hangUpSpdUpCnt, 1); - - return resResult(STATUS.SUCCESS, { goods, hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - spdUpResult.hangUpSpdUpCnt, nextCostGold, hangUpPassTime: Math.floor(deltaTime/1000), rewardLv: endLv, costGold }); - } - - async getTasks(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - - let result = await getTasks(roleId); - - return resResult(STATUS.SUCCESS, result); - } - - async refreshTasks(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let curTime = new Date(); - let { towerLv, towerTaskRefTime, towerTaskReCnt=0 } = await RoleModel.findByRoleId(roleId); - if(towerTaskReCnt >= dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE) { // 付费刷新次数 - return resResult(STATUS.TOWER_REF_CNT_NOT_ENOUGH); - } - let costGold = getTowerTaskCostGold(towerTaskReCnt, towerTaskRefTime); - let {gold} = await RoleModel.findByRoleId(roleId); - if(costGold > gold) { - return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); - } - - // 只刷掉当前面板上没有做派遣的任务 - let batchCode = genCode(8); - let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 - for(let task of curTasks) { - if(task) batchCode = task.batchCode; - } - curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, curTasks); - let newRole = await RoleModel.increaseTowerRefCnt(roleId, 1); - - let refRemainTime = getRemainTime(curTime); - let nextCostGold = getTowerTaskCostGold(newRole.towerTaskReCnt, newRole.towerTaskRefTime); - return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), costGold, nextCostGold, refRemainTime, towerTaskReCnt: newRole.towerTaskReCnt }); - } - - async sendTaskHero(msg: {batchCode: string, tasks: {taskCode: string, heroes: number[]}[]}, session: BackendSession) { - let roleId = session.get('roleId'); - - let batchCode = msg.batchCode; - const curTime = new Date(); - let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前一批的任务 - if (!curTasks || curTasks.length == 0) { - return resResult(STATUS.TOWER_TASK_NOT_FOUND); - } - let usedHeroes: number[] = [], tasks: {taskCode:string, heroes: TaskHero[], completeTime: number}[] = []; - const tasksCode: string[] = []; - const taskMap = new Map() - curTasks.forEach(task => { - let getStatusResult = getTaskStatus(task.status, task.completeTime, curTime); - if(getStatusResult.status == 1) { - for(let { seqId } of task.heroes) { - usedHeroes.push(seqId); - } - } - tasksCode.push(task.taskCode); - taskMap.set(task.taskCode, task); - batchCode = task.batchCode; - }); - for (let { taskCode, heroes: seqIds } of msg.tasks) { - let curTask = taskMap.get(taskCode); // 数据库中,这个任务的数据 - if(!curTask) { - return resResult(STATUS.TOWER_TASK_MISSING) - } - let dicTask = gameData.towerTask.get(curTask.taskId); - if (seqIds.length !== dicTask.actorNeeded) { // 武将数,从策划表中读取 - return resResult(STATUS.TOWER_TASK_MAX_HERO); - } - let { isOK, heroes, hids } = await checkBattleHeroes(roleId, seqIds); - if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); - if (tasksCode.indexOf(taskCode) === -1) { - return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND); - } - if (usedHeroes.length > 0) { // 是否在其他任务重使用了武将 - let used = !!seqIds.find(seqId => usedHeroes.indexOf(seqId) !== -1); - if (used) { - return resResult(STATUS.TOWER_TASK_HERO_HAS_USED); - } - } - - let taskHeroes = heroes.map(hero => { - return new TaskHero(hero); - }); - tasks.push({ taskCode, heroes: taskHeroes, completeTime: dicTask.completeTime}) - - } - const recs = await TowerTaskRecModel.sendHeroes(roleId, batchCode, tasks, curTime,); - if (!recs || recs.length === 0) { - return resResult(STATUS.TOWER_TASK_SEND_ERR); - } - let role = await RoleModel.increaseTowerCnt(roleId, tasks.length) - let refRemainTime = getRemainTime(curTime); - - curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 - let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); - return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold: costGold }); - } - - async settleTask(msg: {batchCode: string, taskCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - const { batchCode, taskCode } = msg; - let allFlag = !taskCode; - - const curTime = new Date(); - let tasks: TowerTaskRecType[] = []; - if(allFlag) { - tasks = await TowerTaskRecModel.getCurTasks(roleId); - } else { - let task = await TowerTaskRecModel.getTaskByCode(roleId, taskCode); - if(task) tasks.push(task); - } - if (!tasks || tasks.length == 0) { - return resResult(STATUS.TOWER_TASK_NOT_FOUND); - } - const checkResult = checkTaskRewards(batchCode, tasks); - if (!checkResult) { - return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE); - } - const { compTasks, rewards } = checkResult; - if(compTasks.length <= 0) return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE) - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_TASK_REWARD); - await TowerTaskRecModel.finishTask(msg.batchCode, compTasks); - let refRemainTime = getRemainTime(curTime); - - let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 - let role = await RoleModel.findByRoleId(roleId); - let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); - return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold }); - } - - async skipTower(msg: { toLv: number }, session: BackendSession) { - const { toLv } = msg; - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - - let role = await RoleModel.findByRoleId(roleId); - let oldTowerLv = role.towerLv; - if(toLv <= oldTowerLv) return resResult(STATUS.TOWER_CANNOT_SKIP); - let dicTower = gameData.tower.get(oldTowerLv); - if(!dicTower.canSkip) { - return resResult(STATUS.TOWER_CANNOT_SKIP); - } - - // 检查战力是否足够 - let towerRec = await TowerRecordModel.getRecordByLv(roleId, oldTowerLv); - let heroes = await HeroModel.findByRole(roleId, [{ field: 'ce', sortBy: -1 }], 'hid ce job', true); - let newWarStar: WarStar[] = [], resultGoods: { towerLv: number, goods: { id: number, count: number }[] }[] = [], rewards: ItemInter[] = []; - - for(let lv = oldTowerLv; lv < toLv; lv++) { - let dicTower = gameData.tower.get(lv); - let warArray = dicTower?.warArray||[]; - - let recommendCeSum = 0, heroesCeSum = 0; - for(let warId of warArray) { - if(!getTowerStatusByWarId(warId, towerRec?.warStatus)) { - let dicWar = gameData.war.get(warId); - recommendCeSum += dicWar.recommendedPower; - heroesCeSum += getTowerHeroCe(warId, heroes, towerRec.heroes); - newWarStar.push({ id: warId, warType: dicWar.warType, star: 0, stars: [] }) - } - } - if(!vipCanSkipTower(recommendCeSum, heroesCeSum, role.vipStartTime)) { - return resResult(STATUS.TOWER_SKIP_POWER_NOT_ENOUGH) - } - resultGoods.push({ towerLv: lv, goods: dicTower.reward }); - rewards.push(...dicTower.reward); - } - - // 更新towerRecord - let warStatus: WarStatus[] = getWarStatusByLv(toLv); - await TowerRecordModel.skipTower(roleId, role.towerLv, toLv, warStatus); - await checkAndStartHungUp(roleId, roleName, role.towerLv); - // 更新玩家表 - role = await RoleModel.setTowerLv(roleId, toLv, newWarStar); - - await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_BATTLE_END); - pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1); - - let data = await getTowerStatus(role); - - // 更新redis - let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role); - await checkTaskInSkipTower(serverId, roleId, sid, role.towerLv); - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: oldTowerLv - 1, newLv: role.towerLv - 1 }) - - return resResult(STATUS.SUCCESS, { ...data, resultGoods }); - } - - /** - * 获取节点奖励 - * @param session - */ - async receiveBox(msg: { id: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let { id } = msg; // id为0表示一键领取 - - let role = await RoleModel.findByRoleId(roleId, 'towerLv towerReceived'); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let { towerLv, towerReceived = [] } = role; - let rewards: RewardInter[] = [], newReceived: number[] = []; - if(id == 0) { - for(let [ id, dicTowerGift ] of gameData.towerGift) { - if(towerLv > dicTowerGift.towerLv && towerReceived.indexOf(id) == -1) { - rewards.push(...dicTowerGift.reward); - newReceived.push(id); - } - } - if(newReceived.length <= 0) return resResult(STATUS.TOWER_BOX_NO_RECEIVE); - } else { - let dicTowerGift = gameData.towerGift.get(id); - if(!dicTowerGift) return resResult(STATUS.WRONG_PARMS); - if(towerLv <= dicTowerGift.towerLv) { - return resResult(STATUS.TOWER_LV_NOT_ENOUGH); - } - if(towerReceived.indexOf(id) != -1) { - return resResult(STATUS.TOWER_BOX_HAS_RECEIVED); - } - rewards.push(...dicTowerGift.reward); - newReceived.push(id); - } - role = await RoleModel.receiveTowerBox(roleId, newReceived); - let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.RECEIVE_TOWER_BOX); - - return resResult(STATUS.SUCCESS, { goods, receivedBox: newReceived }); - } -} +import { STATUS } from './../../../consts/statusCode'; +import { HANG_UP_CONSTS, ITEM_CHANGE_REASON, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE, REDIS_KEY } from './../../../consts'; +import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from './../../../db/TowerTaskRec'; +import { HangUpSpdUpRecModel } from './../../../db/HangUpSpdUpRec'; +import { HangUpRecordModel } from './../../../db/HangUpRecord'; +import { RoleModel } from './../../../db/Role'; +import { TowerRecordModel, WarStatus } from './../../../db/TowerRecord'; +import { Application, BackendSession } from 'pinus'; +import { resResult, genCode, shouldRefresh } from '@pubUtils/util'; +import { calcuHangUpReward, refreshTasks, treatTask, getRemainTime, getTowerStatus, getHungupRewards, getTasks, checkTaskRewards, getTowerTaskCostGold, getManyHangSpdUpCostGold, getTaskStatus, checkForbiddenChar, checkAndStartHungUp, createNewTowerRecord, getTowerRecByLv, getTowerStatusByWarId, getTowerHeroCe, getWarStatusByLv } from '../../../services/battleService'; +import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { checkBattleHeroes } from '../../../services/normalBattleService'; +import { gameData } from '@pubUtils/data'; +import * as dicParam from '@pubUtils/dicParam'; +import { HeroModel } from '@db/Hero'; +import { vipCanSkipTower } from '../../../services/activity/monthlyTicketService'; +import { pushTowerMsg } from '../../../services/sysChatService'; +import { WarStar } from '@domain/dbGeneral'; +import { ItemInter, RewardInter } from '@pubUtils/interface'; +import { combineItems } from '../../../services/role/util'; +import { checkTaskInSkipTower } from '../../../services/task/taskService'; +import { Rank } from '../../../services/rankService'; +import { checkPopUpCondition } from '../../../services/activity/popUpShopService'; +import { isHeroHidden } from '../../../services/dataService'; + +export default function(app: Application) { + return new TowerBattleHandler(app); +} + +export class TowerBattleHandler { + constructor(private app: Application) { + } + + /** + * 获取天梯当前挑战状态 + * @param session + */ + async getStatus(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let role = await RoleModel.findByRoleId(roleId, 'roleId serverId towerLv towerReceived'); + let data = await getTowerStatus(role); + + return resResult(STATUS.SUCCESS, data); + } + + /** + * 重置天梯当前层的挑战记录 + * @param towerLv 要重置的天梯层数 + * @param session + */ + async resetLv(msg: {towerLv: number}, session: BackendSession) { + let roleId = session.get('roleId'); + let { towerLv } = await RoleModel.findByRoleId(roleId); + if (msg.towerLv !== towerLv) { + return resResult(STATUS.TOWER_RESET_ERR); + } + const record = await TowerRecordModel.resetRecordByLv(roleId, towerLv); + if (!record) { + return resResult(STATUS.TOWER_NOT_FOUND); + } + + return resResult(STATUS.SUCCESS, { + roleId: record.roleId, + curLv: record.lv, + heroes: record.heroes, + warStatus: record.warStatus, + speedUpCnt: record.speedUpCnt, + speedUpTime: record.speedUpTime, + hangUpTime: record.hangUpTime, + passed: record.passed + + }); + } + + /** + * 查询当前挂机可得奖励 + * @param msg + * @param session + * @returns + */ + async checkHangUpRewards(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let result = await getHungupRewards(roleId); + if(!result) { + return resResult(STATUS.TOWER_HANG_UP_NOT_START); + } + return resResult(STATUS.SUCCESS, result); + } + + /** + * 领取当前挂机可得奖励 + * @param msg + * @param session + * @returns + */ + async recHangUpRewards(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + let role = await RoleModel.findByRoleId(roleId); + const result = await calcuHangUpReward(role); + if(!result) { + return resResult(STATUS.TOWER_HANG_UP_NOT_START); + } + let { timeReward, endLv, endTime, deltaTime, needReceiveGoods } = result; + + const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD); + await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods); + + return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), goods }); + } + + /** + * 加速挂机 + * @param {{speedUpCnt: number}} msg 加速次数 + * @param session + * @returns + */ + async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let { speedUpCnt } = msg; + + const curTime = new Date(); + + let role = await RoleModel.findByRoleId(roleId); + let { hangUpSpdUpCnt, gold, lastSpdUpTime } = role; + if (shouldRefresh(lastSpdUpTime, curTime)) { + hangUpSpdUpCnt = 0; + } + if (speedUpCnt + hangUpSpdUpCnt > dicParam.TOWER_BOOST.TOWER_BOOSTTIME) { + return resResult(STATUS.TOWER_NOT_ENOUGH_HANG_UP_TIME) + } + + const calResult = await calcuHangUpReward(role, true, msg.speedUpCnt, curTime); + if(!calResult) { + return resResult(STATUS.TOWER_HANG_UP_FAILED); + } + let { timeReward, endLv, deltaTime, needReceiveGoods } = calResult; + + const costGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, msg.speedUpCnt); + if(costGold > gold) { + return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); + } + + await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.TOWER_HUNG_UP_SDP_UP) + + const spdUpResult = await RoleModel.hangUpSpdUp(roleId, msg.speedUpCnt, curTime); + if (!spdUpResult) { + return resResult(STATUS.TOWER_HANG_UP_FAILED); + } + const spdUpRec = await HangUpSpdUpRecModel.updateRec(roleId, roleName, msg.speedUpCnt, endLv, needReceiveGoods); + const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD); + let nextCostGold = getManyHangSpdUpCostGold(spdUpResult.hangUpSpdUpCnt, 1); + + return resResult(STATUS.SUCCESS, { goods, hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - spdUpResult.hangUpSpdUpCnt, nextCostGold, hangUpPassTime: Math.floor(deltaTime/1000), rewardLv: endLv, costGold }); + } + + async getTasks(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + + let result = await getTasks(roleId); + + return resResult(STATUS.SUCCESS, result); + } + + async refreshTasks(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let curTime = new Date(); + let { towerLv, towerTaskRefTime, towerTaskReCnt=0 } = await RoleModel.findByRoleId(roleId); + if(towerTaskReCnt >= dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE) { // 付费刷新次数 + return resResult(STATUS.TOWER_REF_CNT_NOT_ENOUGH); + } + let costGold = getTowerTaskCostGold(towerTaskReCnt, towerTaskRefTime); + let {gold} = await RoleModel.findByRoleId(roleId); + if(costGold > gold) { + return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH); + } + + // 只刷掉当前面板上没有做派遣的任务 + let batchCode = genCode(8); + let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 + for(let task of curTasks) { + if(task) batchCode = task.batchCode; + } + curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, curTasks); + let newRole = await RoleModel.increaseTowerRefCnt(roleId, 1); + + let refRemainTime = getRemainTime(curTime); + let nextCostGold = getTowerTaskCostGold(newRole.towerTaskReCnt, newRole.towerTaskRefTime); + return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), costGold, nextCostGold, refRemainTime, towerTaskReCnt: newRole.towerTaskReCnt }); + } + + async sendTaskHero(msg: {batchCode: string, tasks: {taskCode: string, heroes: number[]}[]}, session: BackendSession) { + let roleId = session.get('roleId'); + + let batchCode = msg.batchCode; + const curTime = new Date(); + let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前一批的任务 + if (!curTasks || curTasks.length == 0) { + return resResult(STATUS.TOWER_TASK_NOT_FOUND); + } + let usedHeroes: number[] = [], tasks: {taskCode:string, heroes: TaskHero[], completeTime: number}[] = []; + const tasksCode: string[] = []; + const taskMap = new Map() + curTasks.forEach(task => { + let getStatusResult = getTaskStatus(task.status, task.completeTime, curTime); + if(getStatusResult.status == 1) { + for(let { seqId } of task.heroes) { + usedHeroes.push(seqId); + } + } + tasksCode.push(task.taskCode); + taskMap.set(task.taskCode, task); + batchCode = task.batchCode; + }); + for (let { taskCode, heroes: seqIds } of msg.tasks) { + let curTask = taskMap.get(taskCode); // 数据库中,这个任务的数据 + if(!curTask) { + return resResult(STATUS.TOWER_TASK_MISSING) + } + let dicTask = gameData.towerTask.get(curTask.taskId); + if (seqIds.length !== dicTask.actorNeeded) { // 武将数,从策划表中读取 + return resResult(STATUS.TOWER_TASK_MAX_HERO); + } + let { isOK, heroes, hids } = await checkBattleHeroes(roleId, seqIds); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); + if (tasksCode.indexOf(taskCode) === -1) { + return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND); + } + if (usedHeroes.length > 0) { // 是否在其他任务重使用了武将 + let used = !!seqIds.find(seqId => usedHeroes.indexOf(seqId) !== -1); + if (used) { + return resResult(STATUS.TOWER_TASK_HERO_HAS_USED); + } + } + + let taskHeroes = heroes.map(hero => { + return new TaskHero(hero); + }); + tasks.push({ taskCode, heroes: taskHeroes, completeTime: dicTask.completeTime}) + + } + const recs = await TowerTaskRecModel.sendHeroes(roleId, batchCode, tasks, curTime,); + if (!recs || recs.length === 0) { + return resResult(STATUS.TOWER_TASK_SEND_ERR); + } + let role = await RoleModel.increaseTowerCnt(roleId, tasks.length) + let refRemainTime = getRemainTime(curTime); + + curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 + let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); + return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold: costGold }); + } + + async settleTask(msg: {batchCode: string, taskCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + const { batchCode, taskCode } = msg; + let allFlag = !taskCode; + + const curTime = new Date(); + let tasks: TowerTaskRecType[] = []; + if(allFlag) { + tasks = await TowerTaskRecModel.getCurTasks(roleId); + } else { + let task = await TowerTaskRecModel.getTaskByCode(roleId, taskCode); + if(task) tasks.push(task); + } + if (!tasks || tasks.length == 0) { + return resResult(STATUS.TOWER_TASK_NOT_FOUND); + } + const checkResult = checkTaskRewards(batchCode, tasks); + if (!checkResult) { + return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE); + } + const { compTasks, rewards } = checkResult; + if(compTasks.length <= 0) return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE) + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_TASK_REWARD); + await TowerTaskRecModel.finishTask(msg.batchCode, compTasks); + let refRemainTime = getRemainTime(curTime); + + let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 + let role = await RoleModel.findByRoleId(roleId); + let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); + return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold }); + } + + async skipTower(msg: { toLv: number }, session: BackendSession) { + const { toLv } = msg; + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + + let role = await RoleModel.findByRoleId(roleId); + let oldTowerLv = role.towerLv; + if(toLv <= oldTowerLv) return resResult(STATUS.TOWER_CANNOT_SKIP); + let dicTower = gameData.tower.get(oldTowerLv); + if(!dicTower.canSkip) { + return resResult(STATUS.TOWER_CANNOT_SKIP); + } + + // 检查战力是否足够 + let towerRec = await TowerRecordModel.getRecordByLv(roleId, oldTowerLv); + let heroes = await HeroModel.findByRole(roleId, [{ field: 'ce', sortBy: -1 }], 'hid ce job', true); + let newWarStar: WarStar[] = [], resultGoods: { towerLv: number, goods: { id: number, count: number }[] }[] = [], rewards: ItemInter[] = []; + + for(let lv = oldTowerLv; lv < toLv; lv++) { + let dicTower = gameData.tower.get(lv); + let warArray = dicTower?.warArray||[]; + + let recommendCeSum = 0, heroesCeSum = 0; + for(let warId of warArray) { + if(!getTowerStatusByWarId(warId, towerRec?.warStatus)) { + let dicWar = gameData.war.get(warId); + recommendCeSum += dicWar.recommendedPower; + heroesCeSum += getTowerHeroCe(warId, heroes, towerRec.heroes); + newWarStar.push({ id: warId, warType: dicWar.warType, star: 0, stars: [] }) + } + } + if(!vipCanSkipTower(recommendCeSum, heroesCeSum, role.vipStartTime)) { + return resResult(STATUS.TOWER_SKIP_POWER_NOT_ENOUGH) + } + resultGoods.push({ towerLv: lv, goods: dicTower.reward }); + rewards.push(...dicTower.reward); + } + + // 更新towerRecord + let warStatus: WarStatus[] = getWarStatusByLv(toLv); + await TowerRecordModel.skipTower(roleId, role.towerLv, toLv, warStatus); + await checkAndStartHungUp(roleId, roleName, role.towerLv); + // 更新玩家表 + role = await RoleModel.setTowerLv(roleId, toLv, newWarStar); + + await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_BATTLE_END); + pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1); + + let data = await getTowerStatus(role); + + // 更新redis + let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role); + await checkTaskInSkipTower(serverId, roleId, sid, role.towerLv); + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: oldTowerLv - 1, newLv: role.towerLv - 1 }) + + return resResult(STATUS.SUCCESS, { ...data, resultGoods }); + } + + /** + * 获取节点奖励 + * @param session + */ + async receiveBox(msg: { id: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let { id } = msg; // id为0表示一键领取 + + let role = await RoleModel.findByRoleId(roleId, 'towerLv towerReceived'); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let { towerLv, towerReceived = [] } = role; + let rewards: RewardInter[] = [], newReceived: number[] = []; + if(id == 0) { + for(let [ id, dicTowerGift ] of gameData.towerGift) { + if(towerLv > dicTowerGift.towerLv && towerReceived.indexOf(id) == -1) { + rewards.push(...dicTowerGift.reward); + newReceived.push(id); + } + } + if(newReceived.length <= 0) return resResult(STATUS.TOWER_BOX_NO_RECEIVE); + } else { + let dicTowerGift = gameData.towerGift.get(id); + if(!dicTowerGift) return resResult(STATUS.WRONG_PARMS); + if(towerLv <= dicTowerGift.towerLv) { + return resResult(STATUS.TOWER_LV_NOT_ENOUGH); + } + if(towerReceived.indexOf(id) != -1) { + return resResult(STATUS.TOWER_BOX_HAS_RECEIVED); + } + rewards.push(...dicTowerGift.reward); + newReceived.push(id); + } + role = await RoleModel.receiveTowerBox(roleId, newReceived); + let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.RECEIVE_TOWER_BOX); + + return resResult(STATUS.SUCCESS, { goods, receivedBox: newReceived }); + } +} + diff --git a/game-server/app/servers/battle/remote/battleRemote.ts b/game-server/app/servers/battle/remote/battleRemote.ts index 8f35feca7..43b93ac46 100644 --- a/game-server/app/servers/battle/remote/battleRemote.ts +++ b/game-server/app/servers/battle/remote/battleRemote.ts @@ -1,218 +1,219 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { PVPConfigModel, PVPConfigType } from '../../../db/PvpConfig'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { setApiIsClose } from '../../../services/chatService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { setServerGroup } from '../../../services/serverService'; -import { savePvpSeasonMemory } from '../../../services/log/memoryLogService'; -import { setKvToMemory } from '../../../services/pushService'; -import { getPvpTime } from '../../../services/pvpService'; -import { taflush } from '../../../services/sdkService'; -import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; -import { errlogger } from '../../../util/logger'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new BattleRemote(app); -} - -export class BattleRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - - /** - * Add user into chat channel. - * - * @param {String} uid unique id for user - * @param {String} sid server id - * @param {boolean} flag channel parameter - * - */ - public async add(uid: string, sid: string, serverId: number, flag: boolean) { - let name = `server-${serverId}`; - console.log('BattleRemote add: ', name, flag); - let channel = this.channelService.getChannel(name, flag); - if (!!channel && !this.get(name, false).includes(uid)) { - if (!!channel) { - channel.add(uid, sid); - } - } - return this.get(name, flag); - } - - /** - * Get user from chat channel. - * - * @param {Object} opts parameters for request - * @param {String} name channel name - * @param {boolean} flag channel parameter - * @return {Array} users uids in channel - * - */ - private get(name: string, flag: boolean) { - let users: string[] = []; - let channel = this.channelService.getChannel(name, flag); - if (!!channel) { - users = channel.getMembers(); - } - for (let i = 0; i < users.length; i++) { - users[i] = users[i].split('*')[0]; - } - return users; - } - - /** - * Kick user out chat channel. - * - * @param {String} uid unique id for user - * @param {String} sid server id - * - */ - public async kick(uid: string, sid: string, serverId: number) { - let name = `server-${serverId}`; - let channel = this.channelService.getChannel(name, false); - // leave channel - if (!!channel) { - channel.leave(uid, sid); - } - } - - /** - * 重载json资源 - */ - public reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSettleSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async getPvpTime() { - try { - return getPvpTime(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public savePvpSeasonMemory() { - try { - return savePvpSeasonMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - return setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { PVPConfigModel, PVPConfigType } from '@db/PvpConfig'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { setApiIsClose } from '../../../services/chatService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { setServerGroup } from '../../../services/serverService'; +import { savePvpSeasonMemory } from '../../../services/log/memoryLogService'; +import { setKvToMemory } from '../../../services/pushService'; +import { getPvpTime } from '../../../services/pvpService'; +import { taflush } from '../../../services/sdkService'; +import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; +import { errlogger } from '../../../util/logger'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new BattleRemote(app); +} + +export class BattleRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + + /** + * Add user into chat channel. + * + * @param {String} uid unique id for user + * @param {String} sid server id + * @param {boolean} flag channel parameter + * + */ + public async add(uid: string, sid: string, serverId: number, flag: boolean) { + let name = `server-${serverId}`; + console.log('BattleRemote add: ', name, flag); + let channel = this.channelService.getChannel(name, flag); + if (!!channel && !this.get(name, false).includes(uid)) { + if (!!channel) { + channel.add(uid, sid); + } + } + return this.get(name, flag); + } + + /** + * Get user from chat channel. + * + * @param {Object} opts parameters for request + * @param {String} name channel name + * @param {boolean} flag channel parameter + * @return {Array} users uids in channel + * + */ + private get(name: string, flag: boolean) { + let users: string[] = []; + let channel = this.channelService.getChannel(name, flag); + if (!!channel) { + users = channel.getMembers(); + } + for (let i = 0; i < users.length; i++) { + users[i] = users[i].split('*')[0]; + } + return users; + } + + /** + * Kick user out chat channel. + * + * @param {String} uid unique id for user + * @param {String} sid server id + * + */ + public async kick(uid: string, sid: string, serverId: number) { + let name = `server-${serverId}`; + let channel = this.channelService.getChannel(name, false); + // leave channel + if (!!channel) { + channel.leave(uid, sid); + } + } + + /** + * 重载json资源 + */ + public reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSettleSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async getPvpTime() { + try { + return getPvpTime(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public savePvpSeasonMemory() { + try { + return savePvpSeasonMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + return setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/chat/handler/chatHandler.ts b/game-server/app/servers/chat/handler/chatHandler.ts index ebf8c9558..58595e286 100644 --- a/game-server/app/servers/chat/handler/chatHandler.ts +++ b/game-server/app/servers/chat/handler/chatHandler.ts @@ -1,229 +1,230 @@ -import { CHANNEL_PREFIX, MSG_SOURCE, getChannelType } from './../../../consts/constModules/chatConst'; -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { genCode, resResult } from '../../../pubUtils/util'; -import { DEFAULT_MSG_PER_PAGE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, STATUS, TASK_TYPE } from '../../../consts'; -import { createAccuseData, createGroupMsg, createPrivateMsg, getPrivateMessages, pushGroupMsgToRoom, pushMsgToRole, updatePrivateMsgReadInfo, recentPrivateChatInfos, recentWorldMsgs, recentSysMsgs, recentGuildMsgs, updatePrivateMsgIsTop, delPrivateMsg, recentServerGroupMsgs, recentLeagueMsgs } from '../../../services/chatService'; -import { getSimpleRoleInfo } from '../../../services/roleService'; -import { checkTask } from '../../../services/task/taskService'; -import { RoleModel } from '../../../db/Role'; -import { getFriendRelationType } from '../../../services/friendService'; -import { GVGLeagueModel } from '../../../db/GVGLeague'; -import { getAllGroupOfServer } from '../../../services/serverService'; -import { getGuildCodeString } from '../../../services/gvg/gvgRecService'; -import { GroupMessageType } from '../../../db/GroupMessage'; -import { pushMsg37 } from '../../../services/sdkService'; -import { gameData } from '../../../pubUtils/data'; -import { pushClientMsg } from '../../../services/pushService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new ChatHandler(app); -} - -export class ChatHandler { - constructor(private app: Application) { - } - - /** - * @description 群聊发送接口 - * @param {{ channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg - * @param {BackendSession} session - * @memberof ChatHandler - */ - async sendGroupMessage(msg: { channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { - const { channel, type, content, targetRoleId, targetMsgCode } = msg; - if (channel === CHANNEL_PREFIX.SYS) return resResult(STATUS.SYS_CHANNEL_AUTH_NOT_ENOUGH); - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const sid = session.get('sid'); - let channelIds: (string|number)[] = [], otherInfo = ''; - if (channel === CHANNEL_PREFIX.WORLD) channelIds.push(serverId); - if (channel === CHANNEL_PREFIX.GUILD) channelIds.push(guildCode); - if (channel === CHANNEL_PREFIX.GVG) { - let groupIds = await getAllGroupOfServer(serverId); - groupIds.forEach(groupId => channelIds.push(groupId)); - otherInfo = genCode(10); - } - if (channel == CHANNEL_PREFIX.LEAGUE) { - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_NOT_JOIN_LEAGUE); - channelIds.push(myLeague.leagueCode); - otherInfo = getGuildCodeString(myLeague); - } - let msgData: GroupMessageType; - for(let channelId of channelIds) { - msgData = await createGroupMsg(roleId, roleName, channel, `${channelId}`, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, otherInfo); - if (!msgData) return resResult(STATUS.WRONG_PARMS); - await pushGroupMsgToRoom(msgData); - } - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType(channel) }); - - return resResult(STATUS.SUCCESS, msgData); - } - - /** - * @description 私聊发送接口 - * @param {{ type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg - * @param {BackendSession} session - * @memberof ChatHandler - */ - async sendPrivateMessage(msg: { type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { - const { type, content, targetRoleId, targetMsgCode } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const roleName = session.get('roleName'); - - const sid = session.get('sid'); - let relation = await getFriendRelationType(roleId, targetRoleId); - const msgData = await createPrivateMsg(roleId, roleName, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, relation); - await pushMsgToRole(msgData); - if (!msgData) return resResult(STATUS.WRONG_PARMS); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType('private') }); - return resResult(STATUS.SUCCESS, msgData); - } - - /** - * @description 获取初始聊天消息,数据和登录时返回的一致 - * @param {{}} msg - * @memberof ChatHandler - */ - async getInitMessage(msg: {}, session: BackendSession) { - - } - - /** - * @description 获取最近私聊对象列表 - * @param {{}} msg - * @param session - */ - async getRecentPrivateChats(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - - const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName) || []; - - return resResult(STATUS.SUCCESS, { - recentPrivateChats - }); - } - - /** - * @description 获取群组聊天记录 - * @param {{}} msg - * @param session - */ - async getGroupMessages(msg: {}, session: BackendSession) { - const serverId: number = session.get('serverId'); - const guildCode: string = session.get('guildCode'); - - const worldMsgs = await recentWorldMsgs(serverId); - const sysMsgs = await recentSysMsgs(serverId); - const guildMsgs = await recentGuildMsgs(guildCode); - const gvgMsgs = await recentServerGroupMsgs(serverId); - const leagueMsgs = await recentLeagueMsgs(guildCode); - - return resResult(STATUS.SUCCESS, { worldMsgs, sysMsgs, guildMsgs, gvgMsgs, leagueMsgs }) - } - - /** - * @description 获取私聊历史消息 - * @param {{targetRoleId: string, fromSeqId: number, count: number}} msg 聊天对象;聊天消息的顺序 id,不传为从最新开始;count 为消息条数 - * @memberof ChatHandler - */ - async getPrivateMessage(msg: { targetRoleId: string, fromSeqId: number, count: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const { targetRoleId, fromSeqId = Infinity, count = DEFAULT_MSG_PER_PAGE } = msg; - const msgs = await getPrivateMessages(roleId, targetRoleId, fromSeqId, count); - const targetRoleInfo = await getSimpleRoleInfo(targetRoleId); - return resResult(STATUS.SUCCESS, { targetRoleId, msgs, targetRoleInfo }); - } - - /** - * @description 查看私聊,主要用于更新最后查看时间和未读消息数 - * @param {{ targetRoleId: string }} msg - * @param {BackendSession} session - * @returns - * @memberof ChatHandler - */ - async readPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const { targetRoleId } = msg; - const result = await updatePrivateMsgReadInfo(roleId, targetRoleId); - if (!result) { - return resResult(STATUS.UPDATE_PRIVATE_MSG_READ_TIME_ERR); - } - return resResult(STATUS.SUCCESS, result); - } - - /** - * @description 设置置顶 - * @param {{ targetRoleId: string, isTop: boolean }} msg - * @param {BackendSession} session - * @returns - * @memberof ChatHandler - */ - async setPrivateMessageTop(msg: { targetRoleId: string, isTop: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - const { targetRoleId, isTop } = msg; - const result = await updatePrivateMsgIsTop(roleId, targetRoleId, isTop); - if (!result) { - return resResult(STATUS.SET_PRIVATE_MSG_TOP_ERR); - } - return resResult(STATUS.SUCCESS, result); - } - - /** - * @description 删除私聊 - * @param {{ targetRoleId: string }} msg - * @param {BackendSession} session - * @returns - * @memberof ChatHandler - */ - async delPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const { targetRoleId } = msg; - const result = await delPrivateMsg(roleId, targetRoleId); - if (!result) { - return resResult(STATUS.DEL_PRIVATE_MSG_ERR); - } - return resResult(STATUS.SUCCESS, result); - } - - /** - * @description 举报玩家的消息 - * @param {{targetRoleId: string, targetMsgCode: string; reason: number}} msg 被举报玩家的 Id,被举报的消息编号,举报原因 - * @param {BackendSession} session - * @returns - * @memberof ChatHandler - */ - async accuse(msg: { targetRoleId: string, targetMsgCode: string; reason: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const { targetRoleId, targetMsgCode, reason } = msg; - let targetRole = await RoleModel.findByRoleId(targetRoleId); - if(!targetRoleId) return resResult(STATUS.ROLE_NOT_FOUND); - const accuseRec = await createAccuseData(roleId, roleName, targetRoleId, targetRole.roleName, targetMsgCode, reason); - if (!accuseRec) return resResult(STATUS.WRONG_PARMS); - return resResult(STATUS.SUCCESS, accuseRec); - } - - // 客户端推送消息 - async debugPushMessage(msg: { uid: number }, session: BackendSession) { - let dic = gameData.dicPushMessage.get(SDK_PUSH_MSG_TYPE.GUILD_ACTIVITY_START); - if(!dic) return resResult(STATUS.WRONG_PARMS); - let result = await pushMsg37(Date.now().toString(), dic, SDK_PUSH_TARGET_TYPE.SINGLE, `${msg.uid}`); - - // await pushClientMsg(SDK_PUSH_MSG_TYPE.AFK_ATTENTION); - - return resResult(STATUS.SUCCESS, result); - } -} +import { CHANNEL_PREFIX, MSG_SOURCE, getChannelType } from './../../../consts/constModules/chatConst'; +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { genCode, resResult } from '@pubUtils/util'; +import { DEFAULT_MSG_PER_PAGE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, STATUS, TASK_TYPE } from '../../../consts'; +import { createAccuseData, createGroupMsg, createPrivateMsg, getPrivateMessages, pushGroupMsgToRoom, pushMsgToRole, updatePrivateMsgReadInfo, recentPrivateChatInfos, recentWorldMsgs, recentSysMsgs, recentGuildMsgs, updatePrivateMsgIsTop, delPrivateMsg, recentServerGroupMsgs, recentLeagueMsgs } from '../../../services/chatService'; +import { getSimpleRoleInfo } from '../../../services/roleService'; +import { checkTask } from '../../../services/task/taskService'; +import { RoleModel } from '@db/Role'; +import { getFriendRelationType } from '../../../services/friendService'; +import { GVGLeagueModel } from '@db/GVGLeague'; +import { getAllGroupOfServer } from '../../../services/serverService'; +import { getGuildCodeString } from '../../../services/gvg/gvgRecService'; +import { GroupMessageType } from '@db/GroupMessage'; +import { pushMsg37 } from '../../../services/sdkService'; +import { gameData } from '@pubUtils/data'; +import { pushClientMsg } from '../../../services/pushService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new ChatHandler(app); +} + +export class ChatHandler { + constructor(private app: Application) { + } + + /** + * @description 群聊发送接口 + * @param {{ channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg + * @param {BackendSession} session + * @memberof ChatHandler + */ + async sendGroupMessage(msg: { channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { + const { channel, type, content, targetRoleId, targetMsgCode } = msg; + if (channel === CHANNEL_PREFIX.SYS) return resResult(STATUS.SYS_CHANNEL_AUTH_NOT_ENOUGH); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const sid = session.get('sid'); + let channelIds: (string|number)[] = [], otherInfo = ''; + if (channel === CHANNEL_PREFIX.WORLD) channelIds.push(serverId); + if (channel === CHANNEL_PREFIX.GUILD) channelIds.push(guildCode); + if (channel === CHANNEL_PREFIX.GVG) { + let groupIds = await getAllGroupOfServer(serverId); + groupIds.forEach(groupId => channelIds.push(groupId)); + otherInfo = genCode(10); + } + if (channel == CHANNEL_PREFIX.LEAGUE) { + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_NOT_JOIN_LEAGUE); + channelIds.push(myLeague.leagueCode); + otherInfo = getGuildCodeString(myLeague); + } + let msgData: GroupMessageType; + for(let channelId of channelIds) { + msgData = await createGroupMsg(roleId, roleName, channel, `${channelId}`, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, otherInfo); + if (!msgData) return resResult(STATUS.WRONG_PARMS); + await pushGroupMsgToRoom(msgData); + } + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType(channel) }); + + return resResult(STATUS.SUCCESS, msgData); + } + + /** + * @description 私聊发送接口 + * @param {{ type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg + * @param {BackendSession} session + * @memberof ChatHandler + */ + async sendPrivateMessage(msg: { type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { + const { type, content, targetRoleId, targetMsgCode } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const roleName = session.get('roleName'); + + const sid = session.get('sid'); + let relation = await getFriendRelationType(roleId, targetRoleId); + const msgData = await createPrivateMsg(roleId, roleName, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, relation); + await pushMsgToRole(msgData); + if (!msgData) return resResult(STATUS.WRONG_PARMS); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType('private') }); + return resResult(STATUS.SUCCESS, msgData); + } + + /** + * @description 获取初始聊天消息,数据和登录时返回的一致 + * @param {{}} msg + * @memberof ChatHandler + */ + async getInitMessage(msg: {}, session: BackendSession) { + + } + + /** + * @description 获取最近私聊对象列表 + * @param {{}} msg + * @param session + */ + async getRecentPrivateChats(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + + const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName) || []; + + return resResult(STATUS.SUCCESS, { + recentPrivateChats + }); + } + + /** + * @description 获取群组聊天记录 + * @param {{}} msg + * @param session + */ + async getGroupMessages(msg: {}, session: BackendSession) { + const serverId: number = session.get('serverId'); + const guildCode: string = session.get('guildCode'); + + const worldMsgs = await recentWorldMsgs(serverId); + const sysMsgs = await recentSysMsgs(serverId); + const guildMsgs = await recentGuildMsgs(guildCode); + const gvgMsgs = await recentServerGroupMsgs(serverId); + const leagueMsgs = await recentLeagueMsgs(guildCode); + + return resResult(STATUS.SUCCESS, { worldMsgs, sysMsgs, guildMsgs, gvgMsgs, leagueMsgs }) + } + + /** + * @description 获取私聊历史消息 + * @param {{targetRoleId: string, fromSeqId: number, count: number}} msg 聊天对象;聊天消息的顺序 id,不传为从最新开始;count 为消息条数 + * @memberof ChatHandler + */ + async getPrivateMessage(msg: { targetRoleId: string, fromSeqId: number, count: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const { targetRoleId, fromSeqId = Infinity, count = DEFAULT_MSG_PER_PAGE } = msg; + const msgs = await getPrivateMessages(roleId, targetRoleId, fromSeqId, count); + const targetRoleInfo = await getSimpleRoleInfo(targetRoleId); + return resResult(STATUS.SUCCESS, { targetRoleId, msgs, targetRoleInfo }); + } + + /** + * @description 查看私聊,主要用于更新最后查看时间和未读消息数 + * @param {{ targetRoleId: string }} msg + * @param {BackendSession} session + * @returns + * @memberof ChatHandler + */ + async readPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const { targetRoleId } = msg; + const result = await updatePrivateMsgReadInfo(roleId, targetRoleId); + if (!result) { + return resResult(STATUS.UPDATE_PRIVATE_MSG_READ_TIME_ERR); + } + return resResult(STATUS.SUCCESS, result); + } + + /** + * @description 设置置顶 + * @param {{ targetRoleId: string, isTop: boolean }} msg + * @param {BackendSession} session + * @returns + * @memberof ChatHandler + */ + async setPrivateMessageTop(msg: { targetRoleId: string, isTop: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + const { targetRoleId, isTop } = msg; + const result = await updatePrivateMsgIsTop(roleId, targetRoleId, isTop); + if (!result) { + return resResult(STATUS.SET_PRIVATE_MSG_TOP_ERR); + } + return resResult(STATUS.SUCCESS, result); + } + + /** + * @description 删除私聊 + * @param {{ targetRoleId: string }} msg + * @param {BackendSession} session + * @returns + * @memberof ChatHandler + */ + async delPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const { targetRoleId } = msg; + const result = await delPrivateMsg(roleId, targetRoleId); + if (!result) { + return resResult(STATUS.DEL_PRIVATE_MSG_ERR); + } + return resResult(STATUS.SUCCESS, result); + } + + /** + * @description 举报玩家的消息 + * @param {{targetRoleId: string, targetMsgCode: string; reason: number}} msg 被举报玩家的 Id,被举报的消息编号,举报原因 + * @param {BackendSession} session + * @returns + * @memberof ChatHandler + */ + async accuse(msg: { targetRoleId: string, targetMsgCode: string; reason: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const { targetRoleId, targetMsgCode, reason } = msg; + let targetRole = await RoleModel.findByRoleId(targetRoleId); + if(!targetRoleId) return resResult(STATUS.ROLE_NOT_FOUND); + const accuseRec = await createAccuseData(roleId, roleName, targetRoleId, targetRole.roleName, targetMsgCode, reason); + if (!accuseRec) return resResult(STATUS.WRONG_PARMS); + return resResult(STATUS.SUCCESS, accuseRec); + } + + // 客户端推送消息 + async debugPushMessage(msg: { uid: number }, session: BackendSession) { + let dic = gameData.dicPushMessage.get(SDK_PUSH_MSG_TYPE.GUILD_ACTIVITY_START); + if(!dic) return resResult(STATUS.WRONG_PARMS); + let result = await pushMsg37(Date.now().toString(), dic, SDK_PUSH_TARGET_TYPE.SINGLE, `${msg.uid}`); + + // await pushClientMsg(SDK_PUSH_MSG_TYPE.AFK_ATTENTION); + + return resResult(STATUS.SUCCESS, result); + } +} + diff --git a/game-server/app/servers/chat/remote/chatRemote.ts b/game-server/app/servers/chat/remote/chatRemote.ts index 9231be1d0..738579b28 100644 --- a/game-server/app/servers/chat/remote/chatRemote.ts +++ b/game-server/app/servers/chat/remote/chatRemote.ts @@ -1,211 +1,212 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { _checkFilterWords, taflush } from '../../../services/sdkService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { errlogger } from '../../../util/logger'; -import { addUserToChannel, sendMessageToChannel, sendMessgeToChannelByBatch, setKvToMemory } from '../../../services/pushService'; -import { setApiIsClose } from '../../../services/chatService'; -import { setServerGroup } from '../../../services/serverService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ChatRemote(app); -} - -// rpc 定义挪到单独的定义文件(user.rpc.define.ts)。解决ts-node 有可能找不到定义的问题。 -// 你也可以用其它方法解决,或者没有遇到过这个问题的话,定义还是可以放在这里。 - -// UserRpc的命名空间自动合并 -// declare global { -// interface UserRpc { -// chat: { -// chatRemote: RemoterClass; -// }; -// } -// } -export class ChatRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - // getTire(); - } - - private channelService: ChannelService; - - /** - * @description 添加用户到频道 - * @param {string} channelName 频道名 - * @param {string} roleId 要添加的用户名 - * @param {string} sid 用户连接的前端服务器名 - * @memberof ChatRemote - */ - public async addChannel(channelName: string, roleId: string, sid: string) { - try { - let channel = this.channelService.getChannel(channelName, true); - if (!channel) return; - addUserToChannel(channel, roleId, sid); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * @description 从频道中删除用户 - * @param {string} channelName - * @param {string} roleId - * @param {string} sid - * @memberof ChatRemote - */ - public async leaveChannel(channelName: string, roleId: string, sid: string) { - try { - let channel = this.channelService.getChannel(channelName, false); - // leave channel - if (!channel) return; - channel.leave(roleId, sid); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 向频道推送消息 - * @param roomId 房间号 - * @param path 推送地址 - * @param data 推送数据 - * @returns - */ - public async pushMessage(roomId: string, path: string, data: any, isBatch = false) { - try { - let channel = this.channelService.getChannel(roomId, false); - if (!channel) return; - if(isBatch) { // 分批推送 - sendMessgeToChannelByBatch(channel, path, data); - } else { - sendMessageToChannel(channel, path, data); - } - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async deleteChannel(roomId: string) { - try { - let channel = this.channelService.getChannel(roomId, false); - if (!channel) return; - channel.destroy(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async checkFilterWords(word: string) { - try { - return await _checkFilterWords(word); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - return setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { _checkFilterWords, taflush } from '../../../services/sdkService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { errlogger } from '../../../util/logger'; +import { addUserToChannel, sendMessageToChannel, sendMessgeToChannelByBatch, setKvToMemory } from '../../../services/pushService'; +import { setApiIsClose } from '../../../services/chatService'; +import { setServerGroup } from '../../../services/serverService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ChatRemote(app); +} + +// rpc 定义挪到单独的定义文件(user.rpc.define.ts)。解决ts-node 有可能找不到定义的问题。 +// 你也可以用其它方法解决,或者没有遇到过这个问题的话,定义还是可以放在这里。 + +// UserRpc的命名空间自动合并 +// declare global { +// interface UserRpc { +// chat: { +// chatRemote: RemoterClass; +// }; +// } +// } +export class ChatRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + // getTire(); + } + + private channelService: ChannelService; + + /** + * @description 添加用户到频道 + * @param {string} channelName 频道名 + * @param {string} roleId 要添加的用户名 + * @param {string} sid 用户连接的前端服务器名 + * @memberof ChatRemote + */ + public async addChannel(channelName: string, roleId: string, sid: string) { + try { + let channel = this.channelService.getChannel(channelName, true); + if (!channel) return; + addUserToChannel(channel, roleId, sid); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * @description 从频道中删除用户 + * @param {string} channelName + * @param {string} roleId + * @param {string} sid + * @memberof ChatRemote + */ + public async leaveChannel(channelName: string, roleId: string, sid: string) { + try { + let channel = this.channelService.getChannel(channelName, false); + // leave channel + if (!channel) return; + channel.leave(roleId, sid); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 向频道推送消息 + * @param roomId 房间号 + * @param path 推送地址 + * @param data 推送数据 + * @returns + */ + public async pushMessage(roomId: string, path: string, data: any, isBatch = false) { + try { + let channel = this.channelService.getChannel(roomId, false); + if (!channel) return; + if(isBatch) { // 分批推送 + sendMessgeToChannelByBatch(channel, path, data); + } else { + sendMessageToChannel(channel, path, data); + } + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async deleteChannel(roomId: string) { + try { + let channel = this.channelService.getChannel(roomId, false); + if (!channel) return; + channel.destroy(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async checkFilterWords(word: string) { + try { + return await _checkFilterWords(word); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + return setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/comBattle/handler/comBattleHandler.ts b/game-server/app/servers/comBattle/handler/comBattleHandler.ts index 94c48044b..323678506 100644 --- a/game-server/app/servers/comBattle/handler/comBattleHandler.ts +++ b/game-server/app/servers/comBattle/handler/comBattleHandler.ts @@ -1,831 +1,832 @@ -import { ComBattleInvitation, MemComBtlTeam } from '../../../domain/battleField/ComBattleTeamField'; -import { difference, pick } from 'underscore'; -/* - * @Author: 梁桐川 - * @Date: 2020-11-30 15:05:48 - * @Last Modified by: 梁桐川 - * @Last Modified time: 2021-08-27 17:47:56 - */ -import { IT_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, COM_TEAM_STATUS, COM_BTL_CONST, CONSUME_TYPE, MSG_SOURCE, ROLE_SELECT, TASK_TYPE, KING_EXP_RATIO_TYPE, ITEM_CHANGE_REASON, getChannelType, CHANNEL_PREFIX, DEBUG_MAGIC_WORD, PUSH_ROUTE, POPULATE_TYPE } from '../../../consts'; -import Role, { RoleModel } from '../../../db/Role'; -import { STATUS } from '../../../consts/statusCode'; -import { Application, BackendSession } from 'pinus'; -import { resResult, getRandSingleEelm, cal } from '../../../pubUtils/util'; -import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, BossHp, ComRoleStatusHero } from '../../../db/ComBattleTeam'; -import { ItemModel, ItemType } from '../../../db/Item'; -import { addItems, handleCost } from '../../../services/role/rewardService'; -import { checkRoleInQueue, getServerName, redisClient, rmCreatedTeamFromRedis, rmRoleFromQueue, setTeamSearchReq } from '../../../services/redisService'; -import { getRandBlueprtId, getFrd, updateRobotHurtByTime, comBtlLvInvalid, clearRobotHurtTimer, setDismissTimer, dismissTeam, handleComBtlProgress, getComBattleFriendAdd, teammateInBlackList, blueprtIdValid, hasEnoughBlueprt, addRoleToTeam, addRoleStToTeam, addValidSearchingRoles, validToJoin, addRobotsToTeam, addRobotsLater, teamIsFullToStart, oneTeamNotInBlack, getAllAssistCnt, checkHasMyTeam, checkTeamStatusAndSend, getComBtlLvByPlayerLv, addToSearchingTeams, getCapFrd, getCapExtraCnt, startTeam } from '../../../services/battle/comBattleService'; -import { setAp } from '../../../services/actionPointService'; -import { roleLevelup } from '../../../services/normalBattleService'; -import { getSimpleRoleInfo } from '../../../services/roleService'; -import { pushComBtlTeamMsg, pushFriendTeamInviteMsg, pushNormalItemMsg, pushTeamInviteMsg } from '../../../services/chatService'; -import { EXTERIOR, INFO_WINDOW } from '../../../pubUtils/dicParam'; -import { getZeroPointD, getTimeFunD, getSeconds, nowSeconds } from '../../../pubUtils/timeUtil'; -import { FriendParams } from '../../../domain/roleField/friend'; -import { checkTask, checkTaskInComBattleStart } from '../../../services/task/taskService'; -import { gameData, getWarByBlueprtId } from '../../../pubUtils/data'; -import { HeroModel } from '../../../db/Hero'; -import { addUserToTeamChannel, delTeamChannel, removeFromTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; -import { getFriendRelationType, getRecommendType } from '../../../services/friendService'; -import { FriendRelationModel } from '../../../db/FriendRelation'; -import { isHeroHidden } from '../../../services/dataService'; -import { addComTeam, clearComBtlTimer,deleteComBattle,getComTeamByCode } from '../../../services/memoryCache/comBattleData'; -import { clearComBattleRoute } from '../../../pubUtils/dispatcher'; - -export default function(app: Application) { - return new ComBattleHandler(app); -} -export class ComBattleHandler { - constructor(private app: Application) { - } - - /** - * @description 队长创建队伍 - * @param {{blueprtId: number, pub: boolean, ceLimit: number}} msg 藏宝图Id,是否公开,战力限制 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async createTeam(msg: {blueprtId: number, pub: boolean, ceLimit: number}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let teamCode = session.get('teamCode'); - const { blueprtId, pub, ceLimit } = msg; - - // console.log('createTeam msg: ', msg); - // 检查藏宝图Id是否合法 - if (!blueprtIdValid(blueprtId)) return resResult(STATUS.COM_BATTLE_BLUEPRT_INVALID); - const enoughBlueprt = await hasEnoughBlueprt(roleId, sid, blueprtId); - if (!enoughBlueprt) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); - - const roleInfo = await RoleModel.findByRoleId(roleId, null, true); - const { lv, topLineupCe } = roleInfo; - if (lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - if(ceLimit && ceLimit > topLineupCe * (1 + COM_BTL_CONST.ROBOT_CE_RATIO)) { - return resResult(STATUS.COM_BATTLE_CREATE_CE_LIMIT) - } - - // 创建队伍数据结构 - let comTeam = new MemComBtlTeam(teamCode, pub, blueprtId, roleId, ceLimit, sid); - - let isFrd = await getCapFrd(roleId); - addRoleToTeam(comTeam, roleInfo, sid, true, isFrd); - addUserToTeamChannel(teamCode, true, roleId, sid); - // 将正在匹配的符合要求的玩家加入队伍,并推送入队消息 - if(pub == true) await addValidSearchingRoles(comTeam); - - // 队伍数据持久化 - const team = await ComBattleTeamModel.createTeam(comTeam); - if (!team) { - delTeamChannel(teamCode); - return resResult(STATUS.COM_BATTLE_CREATE_ERR); - } - addComTeam(teamCode, comTeam) - - // 倒计时一定时间给队长匹配机器人 - if (pub === true) { - await addRobotsLater(comTeam, roleInfo); - } - setDismissTimer(comTeam, roleId); - return resResult(STATUS.SUCCESS, { teamCode, roleStatus: comTeam.roleStatus }); - } - - /** - * @description 匹配队伍 - * @param {{ lv: number }} msg 要匹配藏宝图品阶 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async searchTeam(msg: { lv: number[], magicWord: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - const { lv: lvs = [], magicWord } = msg; - const roleInfo = await RoleModel.findByRoleId(roleId, null, true); - const { lv: playerLv } = roleInfo; - let { topLineupCe = 1000 } = roleInfo; - - if(await checkHasMyTeam(roleId) && magicWord != DEBUG_MAGIC_WORD) { - return resResult(STATUS.COM_BATTLE_IS_RUNNING); - } - - if (comBtlLvInvalid(playerLv, lvs)) { - return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); - } - - const teams = await ComBattleTeamModel.getOtherTeamByLvAndSt(roleId, lvs, COM_TEAM_STATUS.DEFAULT, topLineupCe); - const team: ComBattleTeamType = await oneTeamNotInBlack(teams, roleId); - if (team && team.roleIds.length < 3 && team.status === COM_TEAM_STATUS.DEFAULT && team.roleIds.indexOf(roleId) === -1 && team.blacklist && team.blacklist.indexOf(roleId) === -1) { - return resResult(STATUS.SUCCESS, {teamCode: team.teamCode}); - } - - let teamCode = session.get('teamCode'); - - let hasAdd = await addToSearchingTeams(roleId, sid, lvs); - if(hasAdd) return(STATUS.SUCCESS); - - await setTeamSearchReq(roleId, sid, lvs); - let thiz = this; - // 倒计时匹配两个机器人 - setTimeout(async () => { - let inQueue = await checkRoleInQueue(roleId, sid, lvs); - if (!inQueue) return; - await rmRoleFromQueue(roleId, sid, lvs); - // 创建队伍 - let blueprtId = getRandBlueprtId(lvs).pop(); - let comTeam = new MemComBtlTeam(teamCode, false, blueprtId, 'robot', 0, '') - - let isFrd = await getFrd(roleId); - // 将玩家加入队伍 - addRoleToTeam(comTeam, roleInfo, sid, false, isFrd); - addUserToTeamChannel(teamCode, true, roleId, sid); - - // 创建并添加机器人 - await addRobotsToTeam(comTeam, roleId, topLineupCe, playerLv, 2); - - await ComBattleTeamModel.createTeam(comTeam); - addComTeam(teamCode, comTeam); - // 机器人队伍 3 秒直接开战 - setTimeout(async () => { - thiz.startBattle({teamCode}, session); - }, 3000); - }, COM_BTL_CONST.ASSIST_TIME); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 取消匹配 - * @param {{}} msg - * @param {BackendSession} session - * @memberof ComBattleHandler - */ - async cancelSearch(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - await rmRoleFromQueue(roleId, sid); - let teamCode = session.get('teamCode'); - if(teamCode) clearComBattleRoute(redisClient(), teamCode); - - return resResult(STATUS.SUCCESS); - } - - /** - * @description 当匹配 searchTeam 匹配到其它队伍时,需要调用此接口加入 - * @param {{teamCode: string, isFrd: boolean}} msg 要加入的队伍编号,是否情谊助战 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async joinTeam(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let { teamCode, isFrd } = msg; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if(teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_TEAM_NOT_DEFAULT); - if (teamIsFullToStart(teamStatus)) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); - if (teamStatus.roleIds.indexOf(roleId) !== -1) return resResult(STATUS.COM_BATTLE_DUP_ENTER); - if (teamStatus.blacklist.indexOf(roleId) != -1) return resResult(STATUS.COM_BATTLE_BE_KICKED); - - let role = await Role.findByRoleId(roleId, null, true); - - if (role.lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - if (comBtlLvInvalid(role.lv, [teamStatus.lv])) return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); - if (role.topLineupCe < teamStatus.ceLimit) return resResult(STATUS.COM_BATTLE_CE_LIMIT); - - if (!isFrd) { - isFrd = await getFrd(roleId); - } - - // 加入队伍 - if (!validToJoin(teamStatus, roleId)) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - let roleStatus = new RoleStatus(role, sid, false, isFrd); - const team = await ComBattleTeamModel.addRole(teamCode, roleStatus); - if (!team) { - return resResult(STATUS.COM_BATTLE_JOIN_ERR); - } - - addRoleStToTeam(teamStatus, roleStatus); - - // 推送队伍信息给所有玩家 - addUserToTeamChannel(teamCode, false, roleId, sid); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus }); - - setDismissTimer(teamStatus, roleId); - return resResult(STATUS.SUCCESS, { teamInfo: teamStatus}); - } - - /** - * @description 设置是否情谊助战 - * @param {{teamCode: string, isFrd: boolean}} msg 队伍编号;情谊助战要设置的值,true 为情谊助战 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async setFrdAssistance(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { - let roleId = session.get('roleId'); - let { isFrd, teamCode } = msg; - const isFrdPre = isFrd; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (teamStatus.capId === roleId) return resResult(STATUS.COM_BATTLE_SET_FRD_ERR); - if (!isFrd) { - isFrd = await getFrd(roleId); - } - if (isFrd !== isFrdPre) { - return resResult(STATUS.COM_BATTLE_ASSIST_NOT_ENOUGH); - } - teamStatus.roleStatus.forEach(async st => { - if(st.roleId == roleId) { - st.isFrd = isFrd; - await ComBattleTeamModel.updateRoleStFrd(teamCode, roleId, isFrd); - } - }); - return resResult(STATUS.SUCCESS, { teamCode, isFrd }); - } - - // /** - // * ! 获取队伍列表-deprecated - // * @param msg - // * @param session - // */ - // async getTeams(msg: { blueprtIds: number[] }, session: BackendSession) { - // let roleId = session.get('roleId'); - // let { lv } = await Role.findByRoleId(roleId); - // if (lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); - // const teams = await ComBattleTeamModel.getTeamByBlueprt(msg.blueprtIds, COM_TEAM_STATUS.DEFAULT, true); - // if (!teams) return resResult(STATUS.COM_BATTLE_NO_VALID_TEAM); - // return resResult(STATUS.SUCCESS, { teamInfos: teams}); - // } - - // /** - // * ! deprecate - // * @description 队伍准备 - // * @param {{teamCode: string, heroes: number[]}} msg - // * @param {BackendSession} session - // * @returns - // * @memberof ComBattleHandler - // */ - // async teammateReady(msg: {teamCode: string, heroes: number[]}, session: BackendSession) { - // let roleId = session.get('roleId'); - // let { teamCode, heroes: hids } = msg; - // let teamStatus = this.teamMap.get(teamCode); - // if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - - // const heroDBs = await HeroModel.findByHidRange(hids, roleId); - // const heroes = heroDBs.map(hero => { - // return new ComRoleStatusHero(hero); - // }); - - // let team = await ComBattleTeamModel.updateHeroes(teamCode, roleId, heroes); - // if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); - - // teamStatus.roleStatus.forEach(st => { - // if (st && st.roleId === roleId) { - // st.heroes = heroes; - // } - // }); - - // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_READY, {teamCode, roleId, heroes}); - // return resResult(STATUS.SUCCESS); - // } - - /** - * @description 出兵时记录玩家阵容 - * @param {{teamCode: string, heroes: number[]}} msg 队伍编号;阵容 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async setupHeroes(msg: {teamCode: string, heroes: number[], battleCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let { teamCode, heroes: hids, battleCode = 'default' } = msg; - if (!hids || hids.length === 0) return resResult(STATUS.COM_BATTLE_HEROES_ERR); - if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - - const heroDBs = await HeroModel.findByHidRange(hids, roleId); - const heroes = heroDBs.map(hero => { - return new ComRoleStatusHero(hero); - }); - - let team = await ComBattleTeamModel.setupBattleInfo(teamCode, roleId, heroes, battleCode); - if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); - - teamStatus.roleStatus.forEach(st => { - if (st && st.roleId === roleId) { - st.heroes = heroes; - st.battleCode = battleCode; - } - }); - - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_READY, {teamCode, roleId, heroes}); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 从队伍中移除玩家 - * @param {{teamCode: string, roleIdToRm: string}} msg 队伍编号;要移除的玩家 Id - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async rmTeammate(msg: {teamCode: string, roleIdToRm: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let { teamCode, roleIdToRm } = msg; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (roleId === teamStatus.capId && roleId === roleIdToRm) return resResult(STATUS.COM_BATTLE_RM_SELF); // 队长移除自己视为解散,提示确认 - if (roleId !== teamStatus.capId && roleId !== roleIdToRm) return resResult(STATUS.COM_BATTLE_CAN_NOT_RM); - // if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); // 只有队长可以移除玩家 - - // 移除操作 - let team = await ComBattleTeamModel.removeRole(teamCode, roleIdToRm); - if (!team) return resResult(STATUS.COM_BATTLE_RM_TEAMMATE_ERR); - - teamStatus.roleStatus.some((elem, idx) => { - if (elem.roleId === roleIdToRm) { - teamStatus.roleStatus.splice(idx, 1); - } - }); - teamStatus.roleIds = teamStatus.roleStatus.map(cur => cur.roleId); - if(roleId === teamStatus.capId) { // 队长移除队友,并把他加入黑名单 - teamStatus.blacklist.push(roleIdToRm); - } - - // 先推送离队消息,再将玩家从房间中移除 - sendMessageToTeam(teamCode, PUSH_ROUTE.LEAVE_TEAM, {teamCode, roleId: roleIdToRm}); - removeFromTeamChannel(teamCode, roleIdToRm); - clearComBtlTimer(teamCode); // 移除队员停止解散计时 - let thiz = this; - setTimeout(async () => { - let curTeamStatus = getComTeamByCode(teamCode); - if (validToJoin(curTeamStatus)) { - let roleSt: RoleStatus; - for (let st of curTeamStatus.roleStatus) { - if (st.isCap) { - roleSt = st; - } - } - if (!roleSt) return; - let { roleId, topLineupCe, lv } = roleSt; - await addRobotsToTeam(curTeamStatus, roleId, topLineupCe, lv, 3 - curTeamStatus.roleIds.length); - } - }, COM_BTL_CONST.ASSIST_TIME); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 队长解散队伍 - * @param {{teamCode: string}} msg 要解散的队伍编号 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async dismiss(msg: {teamCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let { teamCode } = msg; - let teamStatus = getComTeamByCode(teamCode); - if(!teamStatus) return resResult(STATUS.SUCCESS); - let result = await dismissTeam(teamStatus, roleId); - return result; - } - - /** - * @description 开始战斗,队长操作或机器人队伍操作 - * @param {{teamCode: string}} msg 队伍编号 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async startBattle(msg: {teamCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let { teamCode } = msg; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (teamStatus.capId !== roleId && teamStatus.capId !== 'robot') return resResult(STATUS.COM_BATTLE_CAP_ONLY); - if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_ALREADY_START); - - startTeam(teamStatus); - let team = await ComBattleTeamModel.updateStatusByCode(teamCode, teamStatus.status, teamStatus.startTime, teamStatus.endTime, teamStatus.hasTimeExtraReward); - if (!team) return resResult(STATUS.COM_BATTLE_START_ERR); - - rmCreatedTeamFromRedis(teamCode, teamStatus.lv); - clearComBtlTimer(teamCode); // 战斗开始停止解散计时 - await getComBattleFriendAdd(teamStatus.roleStatus); - sendMessageToTeam(teamCode, PUSH_ROUTE.COMBATTLE_START, {teamCode, roleStatus: teamStatus.roleStatus}); - // 每场倒计时结算 - let thiz = this; - setTimeout(async () => { - let teamStatus = getComTeamByCode(teamCode); - if (teamStatus && teamStatus.status === COM_TEAM_STATUS.FIGHTING) { - clearRobotHurtTimer(teamStatus); - let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr}, true); - if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); - teamStatus.timeout = true; - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: false, timeout: true}); - deleteComBattle(teamCode); - clearComBattleRoute(redisClient(), teamCode) - } - }, COM_BTL_CONST.BTL_TIME_LMT); - teamStatus.roleStatus.forEach((st, idx) => { - if (st.isRobot === true) { - updateRobotHurtByTime(teamStatus, st, COM_BTL_CONST.ROBOT_BASE_TIME_INTERVAL + idx); - } - }); - await checkTaskInComBattleStart(teamStatus.roleStatus, teamStatus.capId, teamStatus.blueprtId); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 战场中的状态同步,战斗结果判定 - * @param {{teamCode: string, bossHurts: Array<{dataId: number, hurtHp: number}>, killed: number[], curRnd: number}} msg 队伍编号;boss 承伤;武将阵亡;当前回合 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async action(msg: {teamCode: string, bossHurts: Array<{hid: number, dataId: number, hurtHp: number}>, killed: number[], curRnd: number, timegap: number, roundTime: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let { teamCode, killed, bossHurts, curRnd, timegap = 0, roundTime = 0 } = msg; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) { - checkTeamStatusAndSend(teamCode, roleId, sid); - return resResult(STATUS.SUCCESS); - } - if (teamStatus.status !== COM_TEAM_STATUS.FIGHTING) { - checkTeamStatusAndSend(teamCode, roleId, sid); - return resResult(STATUS.SUCCESS); - } - for (let st of teamStatus.roleStatus) { - if (st.roleId === roleId && (!st.heroes || st.heroes.length === 0)) { - return resResult(STATUS.SUCCESS); - } - } - // 重置总血量,计算真实伤害 - const roleSt = teamStatus.findMemberByRoleId(roleId); - if(!roleSt) return resResult(STATUS.SUCCESS); - if(!roleSt.startActionTime || roleSt.startActionTime == 0) { // 第一次调用设置初始 - roleSt.startActionTime = nowSeconds(); - } - if ((roundTime > 0 && roundTime < 500) || (timegap - (nowSeconds() - roleSt.startActionTime) > 5)) { // 前后端误差超过5秒拦截 - return resResult(STATUS.SUCCESS, { - isError: true, - timegap: nowSeconds() - roleSt.startActionTime - }); - } - - let actBossHurts: {dataId: number, hurtHp: number}[] = []; - let totalHurtHp = 0; - teamStatus.bossHpArr.forEach(boss => { - for (let bh of bossHurts) { - if (boss.dataId === bh.dataId && bh.hurtHp < 0) { - let deltaHp = Math.abs(bh.hurtHp); - if (boss.curHp >= deltaHp) { - actBossHurts.push({dataId: boss.dataId, hurtHp: deltaHp}); - totalHurtHp = cal.add(totalHurtHp, deltaHp); - boss.curHp = cal.sub(boss.curHp, deltaHp); - } else if (boss.curHp > 0) { - actBossHurts.push({dataId: boss.dataId, hurtHp: boss.curHp}); - totalHurtHp = cal.add(totalHurtHp, boss.curHp); - boss.curHp = 0; - } - if(bh.hid) { - roleSt.addHeroDamage(bh.hid, deltaHp); - } - } - } - }); - // 更新玩家武将阵亡情况,计算玩家总伤害 - roleSt.totalDmg = cal.add(roleSt.totalDmg, totalHurtHp); - if (killed && killed.length) { - roleSt.killed = Array.from(new Set([...roleSt.killed, ...killed])); - } - - teamStatus.curRnd = curRnd; - teamStatus.bossCurHp = cal.sub(teamStatus.bossCurHp, totalHurtHp); - if (teamStatus.bossCurHp < 0) teamStatus.bossCurHp = 0; - // 推送本次行动情况 - const roleStatus = teamStatus.roleStatus.map(st => {return {roleId: st.roleId, totalDmg: st.totalDmg, killed: st.killed}}); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus, actRoleId: roleId, actBossHurts }); - const result = await handleComBtlProgress(teamStatus); - if (result && result.code !== 0) return result; - return resResult(STATUS.SUCCESS, { - isError: false, - timegap: nowSeconds() - roleSt.startActionTime - }); - } - - // /** - // * ! 客户端给服务器的战斗结束通知-deprecated - // * @param msg - // * @param session - // */ - // async battleEnd(msg: {teamCode: string, isSuccess: boolean}, session: BackendSession) { - // let roleId = session.get('roleId'); - // let { teamCode, isSuccess } = msg; - // let teamStatus = this.teamMap.get(teamCode); - // if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - - // if (isSuccess && teamStatus.bossCurHp <= 0) { - // let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess); - // if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); - // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: isSuccess}); - // } else if (!isSuccess) { - // let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess); - // if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); - // if (team.status === COM_TEAM_STATUS.LOOSE) { - // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: isSuccess}); - // } else { - // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_ACT, {teamCode, bossCurHp: teamStatus.bossCurHp, roleStatus: {roleId, battleStatus: 2}}); - // } - // } - // return resResult(STATUS.SUCCESS, { bossCurHp: teamStatus.bossCurHp }); - // } - - /** - * @description 寻宝结算 - * @param {{teamCode: string}} msg 寻宝队伍编号 - * @param {BackendSession} session - * @returns 掉落物品和玩家升级信息 - * @memberof ComBattleHandler - */ - async comBattleEnd(msg: {teamCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let ip = session.get('ip'); - let serverId = session.get('serverId'); - - let { teamCode } = msg; - let team = await ComBattleTeamModel.getTeamByCode(teamCode); - clearRobotHurtTimer(team); - if (!team || team.status !== COM_TEAM_STATUS.WIN) return resResult(STATUS.COM_BATTLE_REWARD_ERR); - let { roleStatus, blueprtId, status, bossHpArr } = team; - let roleSt = roleStatus.find(st => st && st.roleId === roleId); - if(!roleSt) return resResult(STATUS.COM_BATTLE_REWARD_ERR); - - await ComBattleTeamModel.updateRewardSt(teamCode, roleId, true); - const goods = await addItems(roleId, roleName, sid, roleSt.rewards, ITEM_CHANGE_REASON.COM_BATTLE_END); - - return resResult(STATUS.SUCCESS, { battleGoods: goods, teamInfo: {status, teamCode, roleStatus, bossHpArr} }); - } - - async retreat(msg: {teamCode: string}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - let { teamCode } = msg; - let teamStatus = getComTeamByCode(teamCode); - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) { - checkTeamStatusAndSend(teamCode, roleId, sid); - return resResult(STATUS.SUCCESS); - } - if(teamStatus.roleStatus.length > 1) { - return resResult(STATUS.COM_BATTLE_RETREAT_ERR) - } - - clearRobotHurtTimer(teamStatus); - - let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: Date.now() }, false, true); - if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: false }); - - deleteComBattle(teamCode); - clearComBattleRoute(redisClient(), teamCode); - - return resResult(STATUS.SUCCESS, { teamInfo: pick(team, ['status', 'teamCode', 'roleStatus', 'bossHpArr']) }); - } - - async getComBtlStatus(msg: {teamCode: string}, session: BackendSession) { - let { teamCode } = msg; - let roleStatus: RoleStatus[], status: number, bossHpArr: BossHp[], timeout: boolean, endTime = 0; - let memTeam = getComTeamByCode(teamCode); - if (memTeam) { - ({ roleStatus, status, bossHpArr, timeout, endTime } = memTeam); - } else { - let dbTeam = await ComBattleTeamModel.getTeamByCode(teamCode); - if (!dbTeam) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - ({ roleStatus, status, bossHpArr, timeout, endTime } = dbTeam); - clearComBattleRoute(redisClient(), teamCode); - } - return resResult(STATUS.SUCCESS, { teamInfo: {status, teamCode, roleStatus, bossHpArr, timeout, endTime} }); - } - - /** - * @description 获取自己一段时间内的寻宝记录 - * @param {{}} msg - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async getTeamRec(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let timef = getTimeFunD(); - let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, timef.getBeforeDayWithHour(2)); - if (!teams) return resResult(STATUS.COM_BATTLE_NO_RECENT_REC); - - return resResult(STATUS.SUCCESS, {teamInfos: teams}); - } - - /** - * @description 获取藏宝图数量 - * @param {{ids: number[]}} msg 藏宝图Id数组,可选参数 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async getBlueprtCount(msg: {ids: number[]}, session: BackendSession) { - let roleId = session.get('roleId'); - let { ids } = msg; - let blueprts: ItemType[]; - if (ids && ids.length) { - blueprts = await ItemModel.findbyRoleAndIds(roleId, ids); - } else { - blueprts = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); - } - return resResult(STATUS.SUCCESS, { blueprts }); - } - - /** - * @description 获取今日已助战次数 - * @param {{}} msg - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async getAssistCnt(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let cnt = await getAllAssistCnt(roleId); - return resResult(STATUS.SUCCESS, {cnt}); - } - /** - * @description 获取寻宝可用次数,包含藏宝图数量和助战次数,分别用于创建和加入队伍 - * @param {{}} msg 无参数 - * @param {BackendSession} session - * @returns - * @memberof ComBattleHandler - */ - async getComBtlCnt(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let cnt = await getAllAssistCnt(roleId); - const blueprts = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); - let capExtraCnt = await getCapExtraCnt(roleId); - return resResult(STATUS.SUCCESS, { blueprts, assistCnt: cnt, capExtraCnt }); - } - - async sendTeamMsg(msg: { teamCode: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - - const { teamCode, type, content, targetRoleId, targetMsgCode } = msg; - const result = await pushComBtlTeamMsg(teamCode, roleId, roleName, type, MSG_SOURCE.TEAM_ROLE, content, targetRoleId, targetMsgCode); - if (!result) { - return resResult(STATUS.WRONG_PARMS); - } - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType(CHANNEL_PREFIX.TEAM) }); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 一键邀请,自动在世界频道发送消息 - * @param {{ teamCode: string }} msg - * @param {BackendSession} session - * @memberof ComBattleHandler - */ - async autoInvite(msg: { teamCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let guildCode = session.get('guildCode'); - if (!guildCode) return resResult(STATUS.COM_BATTLE_INVITE_GUILD_ERR); - - const { teamCode } = msg; - let teamStatus = getComTeamByCode(teamCode); - if(!teamStatus) return resResult(STATUS.WRONG_PARMS); - await pushTeamInviteMsg(roleId, roleName, guildCode, teamCode, teamStatus.blueprtId, teamStatus.lv, teamStatus.ceLimit); - await ComBattleTeamModel.invite(teamCode, guildCode); - return resResult(STATUS.SUCCESS); - } - - /** - * @description 邀请队友 - * @param {{ teamCode: string, targetRoleId: string }} msg - * @param {BackendSession} session - * @memberof ComBattleHandler - */ - async inviteTeammate(msg: { teamCode: string, targetRoleId: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let guildCode = session.get('guildCode'); - const { teamCode, targetRoleId } = msg; - - let teamStatus = getComTeamByCode(teamCode); - if(!teamStatus) return resResult(STATUS.WRONG_PARMS); - - let role = await RoleModel.findByRoleId(targetRoleId, 'lv'); - if(comBtlLvInvalid(role.lv, [teamStatus.lv])) { - return resResult(STATUS.COM_BATTLE_INVITE_LV_NOT_ENOUGH); - } - if (role.topLineupCe < teamStatus.ceLimit) { - return resResult(STATUS.COM_BATTLE_CE_LIMIT); - } - - await ComBattleTeamModel.invite(teamCode, targetRoleId); - let relation = await getFriendRelationType(roleId, targetRoleId); - const msgData = await pushFriendTeamInviteMsg(roleId, roleName, teamCode, teamStatus.blueprtId, targetRoleId, relation); - if (!msgData) return resResult(STATUS.WRONG_PARMS); - const roleInfo = await getSimpleRoleInfo(targetRoleId); - - let index = teamStatus.blacklist.indexOf(targetRoleId); - if(index != -1) { - teamStatus.blacklist.splice(index, 1); - } - - return resResult(STATUS.SUCCESS, {...msgData, roleInfo}); - } - - /** - * @description 最近组队过的队友列表 - * @param {} msg - * @param {BackendSession} session - */ - async getRecentTeammates(msg: { }, session: BackendSession) { - let roleId = session.get('roleId'); - - const teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, getZeroPointD()); - let roleIdList = new Array(); - for(let { roleIds } of teams) { - for(let r of roleIds) { - if(r != roleId) roleIdList.push(r); - } - } - const roles = await RoleModel.findByRoleIds(roleIdList, ROLE_SELECT.SHOW_SIMPLE, true); - let result = new Array(); - for(let role of roles) { - if(role.quitTime == role.loginTime) { - let r = new FriendParams(role); - result.push(r); - } - } - - return resResult(STATUS.SUCCESS, { list: result }); - } - - async getTeamInvitation(msg: { }, session: BackendSession) { - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - let role = await RoleModel.findByRoleId(roleId, 'lv topLineupCe'); - const assistCnt = await getAllAssistCnt(roleId); - - let { minLv, maxLv } = getComBtlLvByPlayerLv(role.lv); - let refreshTime = nowSeconds() - INFO_WINDOW.TEAM_INFORMATION_TIME; - const invitations = await ComBattleTeamModel.findInvitations(roleId, guildCode, minLv, maxLv, role.topLineupCe, refreshTime, INFO_WINDOW.TEAM_VIEW); - let roleIds = invitations.map(cur => cur.capId); - let roles = await RoleModel.findByRoleIds(roleIds); - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - const teams: ComBattleInvitation[] = []; - for(let invitation of invitations) { - let leader = roles.find(role => role.roleId == invitation.capId); - if(leader) { - let leaderParam = new FriendParams(leader); - let type = getRecommendType(myFriendRelation, roleId, leader.roleId); - leaderParam.setType(type); - - let serverName = await getServerName(leader.serverId); - leaderParam.setServerName(leader.serverId, serverName); - teams.push(new ComBattleInvitation(invitation, leaderParam)); - } - } - - return resResult(STATUS.SUCCESS, { teams, assistCnt }); - } - - // ! 测试接口 - /** - * 修改玩家的等级-方便测试组队 - * 寻宝创建队伍 - 会先调用这个接口 - * @param {{ targetLv: number }} msg - * @param {BackendSession} session - * @return {*} - * @memberof ComBattleHandler - */ - async debugSetRoleLv(msg: { magicWord: string, targetLv: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const { targetLv, magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let role = await RoleModel.updateRoleInfo(roleId, { lv: targetLv }); - return resResult(STATUS.SUCCESS, { lv: role.lv, roleId }); - } - -} +import { ComBattleInvitation, MemComBtlTeam } from '@domain/battleField/ComBattleTeamField'; +import { difference, pick } from 'underscore'; +/* + * @Author: 梁桐川 + * @Date: 2020-11-30 15:05:48 + * @Last Modified by: 梁桐川 + * @Last Modified time: 2021-08-27 17:47:56 + */ +import { IT_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, COM_TEAM_STATUS, COM_BTL_CONST, CONSUME_TYPE, MSG_SOURCE, ROLE_SELECT, TASK_TYPE, KING_EXP_RATIO_TYPE, ITEM_CHANGE_REASON, getChannelType, CHANNEL_PREFIX, DEBUG_MAGIC_WORD, PUSH_ROUTE, POPULATE_TYPE } from '../../../consts'; +import Role, { RoleModel } from '@db/Role'; +import { STATUS } from '@consts/statusCode'; +import { Application, BackendSession } from 'pinus'; +import { resResult, getRandSingleEelm, cal } from '@pubUtils/util'; +import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, BossHp, ComRoleStatusHero } from '@db/ComBattleTeam'; +import { ItemModel, ItemType } from '@db/Item'; +import { addItems, handleCost } from '../../../services/role/rewardService'; +import { checkRoleInQueue, getServerName, redisClient, rmCreatedTeamFromRedis, rmRoleFromQueue, setTeamSearchReq } from '../../../services/redisService'; +import { getRandBlueprtId, getFrd, updateRobotHurtByTime, comBtlLvInvalid, clearRobotHurtTimer, setDismissTimer, dismissTeam, handleComBtlProgress, getComBattleFriendAdd, teammateInBlackList, blueprtIdValid, hasEnoughBlueprt, addRoleToTeam, addRoleStToTeam, addValidSearchingRoles, validToJoin, addRobotsToTeam, addRobotsLater, teamIsFullToStart, oneTeamNotInBlack, getAllAssistCnt, checkHasMyTeam, checkTeamStatusAndSend, getComBtlLvByPlayerLv, addToSearchingTeams, getCapFrd, getCapExtraCnt, startTeam } from '../../../services/battle/comBattleService'; +import { setAp } from '../../../services/actionPointService'; +import { roleLevelup } from '../../../services/normalBattleService'; +import { getSimpleRoleInfo } from '../../../services/roleService'; +import { pushComBtlTeamMsg, pushFriendTeamInviteMsg, pushNormalItemMsg, pushTeamInviteMsg } from '../../../services/chatService'; +import { EXTERIOR, INFO_WINDOW } from '@pubUtils/dicParam'; +import { getZeroPointD, getTimeFunD, getSeconds, nowSeconds } from '@pubUtils/timeUtil'; +import { FriendParams } from '@domain/roleField/friend'; +import { checkTask, checkTaskInComBattleStart } from '../../../services/task/taskService'; +import { gameData, getWarByBlueprtId } from '@pubUtils/data'; +import { HeroModel } from '@db/Hero'; +import { addUserToTeamChannel, delTeamChannel, removeFromTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; +import { getFriendRelationType, getRecommendType } from '../../../services/friendService'; +import { FriendRelationModel } from '@db/FriendRelation'; +import { isHeroHidden } from '../../../services/dataService'; +import { addComTeam, clearComBtlTimer,deleteComBattle,getComTeamByCode } from '../../../services/memoryCache/comBattleData'; +import { clearComBattleRoute } from '@pubUtils/dispatcher'; + +export default function(app: Application) { + return new ComBattleHandler(app); +} +export class ComBattleHandler { + constructor(private app: Application) { + } + + /** + * @description 队长创建队伍 + * @param {{blueprtId: number, pub: boolean, ceLimit: number}} msg 藏宝图Id,是否公开,战力限制 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async createTeam(msg: {blueprtId: number, pub: boolean, ceLimit: number}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let teamCode = session.get('teamCode'); + const { blueprtId, pub, ceLimit } = msg; + + // console.log('createTeam msg: ', msg); + // 检查藏宝图Id是否合法 + if (!blueprtIdValid(blueprtId)) return resResult(STATUS.COM_BATTLE_BLUEPRT_INVALID); + const enoughBlueprt = await hasEnoughBlueprt(roleId, sid, blueprtId); + if (!enoughBlueprt) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); + + const roleInfo = await RoleModel.findByRoleId(roleId, null, true); + const { lv, topLineupCe } = roleInfo; + if (lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); + if(ceLimit && ceLimit > topLineupCe * (1 + COM_BTL_CONST.ROBOT_CE_RATIO)) { + return resResult(STATUS.COM_BATTLE_CREATE_CE_LIMIT) + } + + // 创建队伍数据结构 + let comTeam = new MemComBtlTeam(teamCode, pub, blueprtId, roleId, ceLimit, sid); + + let isFrd = await getCapFrd(roleId); + addRoleToTeam(comTeam, roleInfo, sid, true, isFrd); + addUserToTeamChannel(teamCode, true, roleId, sid); + // 将正在匹配的符合要求的玩家加入队伍,并推送入队消息 + if(pub == true) await addValidSearchingRoles(comTeam); + + // 队伍数据持久化 + const team = await ComBattleTeamModel.createTeam(comTeam); + if (!team) { + delTeamChannel(teamCode); + return resResult(STATUS.COM_BATTLE_CREATE_ERR); + } + addComTeam(teamCode, comTeam) + + // 倒计时一定时间给队长匹配机器人 + if (pub === true) { + await addRobotsLater(comTeam, roleInfo); + } + setDismissTimer(comTeam, roleId); + return resResult(STATUS.SUCCESS, { teamCode, roleStatus: comTeam.roleStatus }); + } + + /** + * @description 匹配队伍 + * @param {{ lv: number }} msg 要匹配藏宝图品阶 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async searchTeam(msg: { lv: number[], magicWord: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + const { lv: lvs = [], magicWord } = msg; + const roleInfo = await RoleModel.findByRoleId(roleId, null, true); + const { lv: playerLv } = roleInfo; + let { topLineupCe = 1000 } = roleInfo; + + if(await checkHasMyTeam(roleId) && magicWord != DEBUG_MAGIC_WORD) { + return resResult(STATUS.COM_BATTLE_IS_RUNNING); + } + + if (comBtlLvInvalid(playerLv, lvs)) { + return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); + } + + const teams = await ComBattleTeamModel.getOtherTeamByLvAndSt(roleId, lvs, COM_TEAM_STATUS.DEFAULT, topLineupCe); + const team: ComBattleTeamType = await oneTeamNotInBlack(teams, roleId); + if (team && team.roleIds.length < 3 && team.status === COM_TEAM_STATUS.DEFAULT && team.roleIds.indexOf(roleId) === -1 && team.blacklist && team.blacklist.indexOf(roleId) === -1) { + return resResult(STATUS.SUCCESS, {teamCode: team.teamCode}); + } + + let teamCode = session.get('teamCode'); + + let hasAdd = await addToSearchingTeams(roleId, sid, lvs); + if(hasAdd) return(STATUS.SUCCESS); + + await setTeamSearchReq(roleId, sid, lvs); + let thiz = this; + // 倒计时匹配两个机器人 + setTimeout(async () => { + let inQueue = await checkRoleInQueue(roleId, sid, lvs); + if (!inQueue) return; + await rmRoleFromQueue(roleId, sid, lvs); + // 创建队伍 + let blueprtId = getRandBlueprtId(lvs).pop(); + let comTeam = new MemComBtlTeam(teamCode, false, blueprtId, 'robot', 0, '') + + let isFrd = await getFrd(roleId); + // 将玩家加入队伍 + addRoleToTeam(comTeam, roleInfo, sid, false, isFrd); + addUserToTeamChannel(teamCode, true, roleId, sid); + + // 创建并添加机器人 + await addRobotsToTeam(comTeam, roleId, topLineupCe, playerLv, 2); + + await ComBattleTeamModel.createTeam(comTeam); + addComTeam(teamCode, comTeam); + // 机器人队伍 3 秒直接开战 + setTimeout(async () => { + thiz.startBattle({teamCode}, session); + }, 3000); + }, COM_BTL_CONST.ASSIST_TIME); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 取消匹配 + * @param {{}} msg + * @param {BackendSession} session + * @memberof ComBattleHandler + */ + async cancelSearch(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + await rmRoleFromQueue(roleId, sid); + let teamCode = session.get('teamCode'); + if(teamCode) clearComBattleRoute(redisClient(), teamCode); + + return resResult(STATUS.SUCCESS); + } + + /** + * @description 当匹配 searchTeam 匹配到其它队伍时,需要调用此接口加入 + * @param {{teamCode: string, isFrd: boolean}} msg 要加入的队伍编号,是否情谊助战 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async joinTeam(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let { teamCode, isFrd } = msg; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + if(teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_TEAM_NOT_DEFAULT); + if (teamIsFullToStart(teamStatus)) return resResult(STATUS.COM_BATTLE_MEMBER_LIMIT); + if (teamStatus.roleIds.indexOf(roleId) !== -1) return resResult(STATUS.COM_BATTLE_DUP_ENTER); + if (teamStatus.blacklist.indexOf(roleId) != -1) return resResult(STATUS.COM_BATTLE_BE_KICKED); + + let role = await Role.findByRoleId(roleId, null, true); + + if (role.lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); + if (comBtlLvInvalid(role.lv, [teamStatus.lv])) return resResult(STATUS.COM_BATTLE_ASSIST_LV_NOT_ENOUGH); + if (role.topLineupCe < teamStatus.ceLimit) return resResult(STATUS.COM_BATTLE_CE_LIMIT); + + if (!isFrd) { + isFrd = await getFrd(roleId); + } + + // 加入队伍 + if (!validToJoin(teamStatus, roleId)) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + let roleStatus = new RoleStatus(role, sid, false, isFrd); + const team = await ComBattleTeamModel.addRole(teamCode, roleStatus); + if (!team) { + return resResult(STATUS.COM_BATTLE_JOIN_ERR); + } + + addRoleStToTeam(teamStatus, roleStatus); + + // 推送队伍信息给所有玩家 + addUserToTeamChannel(teamCode, false, roleId, sid); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus }); + + setDismissTimer(teamStatus, roleId); + return resResult(STATUS.SUCCESS, { teamInfo: teamStatus}); + } + + /** + * @description 设置是否情谊助战 + * @param {{teamCode: string, isFrd: boolean}} msg 队伍编号;情谊助战要设置的值,true 为情谊助战 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async setFrdAssistance(msg: {teamCode: string, isFrd: boolean}, session: BackendSession) { + let roleId = session.get('roleId'); + let { isFrd, teamCode } = msg; + const isFrdPre = isFrd; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + if (teamStatus.capId === roleId) return resResult(STATUS.COM_BATTLE_SET_FRD_ERR); + if (!isFrd) { + isFrd = await getFrd(roleId); + } + if (isFrd !== isFrdPre) { + return resResult(STATUS.COM_BATTLE_ASSIST_NOT_ENOUGH); + } + teamStatus.roleStatus.forEach(async st => { + if(st.roleId == roleId) { + st.isFrd = isFrd; + await ComBattleTeamModel.updateRoleStFrd(teamCode, roleId, isFrd); + } + }); + return resResult(STATUS.SUCCESS, { teamCode, isFrd }); + } + + // /** + // * ! 获取队伍列表-deprecated + // * @param msg + // * @param session + // */ + // async getTeams(msg: { blueprtIds: number[] }, session: BackendSession) { + // let roleId = session.get('roleId'); + // let { lv } = await Role.findByRoleId(roleId); + // if (lv < COM_BTL_CONST.ENABLE_LV) return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH); + // const teams = await ComBattleTeamModel.getTeamByBlueprt(msg.blueprtIds, COM_TEAM_STATUS.DEFAULT, true); + // if (!teams) return resResult(STATUS.COM_BATTLE_NO_VALID_TEAM); + // return resResult(STATUS.SUCCESS, { teamInfos: teams}); + // } + + // /** + // * ! deprecate + // * @description 队伍准备 + // * @param {{teamCode: string, heroes: number[]}} msg + // * @param {BackendSession} session + // * @returns + // * @memberof ComBattleHandler + // */ + // async teammateReady(msg: {teamCode: string, heroes: number[]}, session: BackendSession) { + // let roleId = session.get('roleId'); + // let { teamCode, heroes: hids } = msg; + // let teamStatus = this.teamMap.get(teamCode); + // if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + + // const heroDBs = await HeroModel.findByHidRange(hids, roleId); + // const heroes = heroDBs.map(hero => { + // return new ComRoleStatusHero(hero); + // }); + + // let team = await ComBattleTeamModel.updateHeroes(teamCode, roleId, heroes); + // if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); + + // teamStatus.roleStatus.forEach(st => { + // if (st && st.roleId === roleId) { + // st.heroes = heroes; + // } + // }); + + // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_READY, {teamCode, roleId, heroes}); + // return resResult(STATUS.SUCCESS); + // } + + /** + * @description 出兵时记录玩家阵容 + * @param {{teamCode: string, heroes: number[]}} msg 队伍编号;阵容 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async setupHeroes(msg: {teamCode: string, heroes: number[], battleCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let { teamCode, heroes: hids, battleCode = 'default' } = msg; + if (!hids || hids.length === 0) return resResult(STATUS.COM_BATTLE_HEROES_ERR); + if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN); + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + + const heroDBs = await HeroModel.findByHidRange(hids, roleId); + const heroes = heroDBs.map(hero => { + return new ComRoleStatusHero(hero); + }); + + let team = await ComBattleTeamModel.setupBattleInfo(teamCode, roleId, heroes, battleCode); + if (!team) return resResult(STATUS.COM_BATTLE_UPDATE_HEROES_ERR); + + teamStatus.roleStatus.forEach(st => { + if (st && st.roleId === roleId) { + st.heroes = heroes; + st.battleCode = battleCode; + } + }); + + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_READY, {teamCode, roleId, heroes}); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 从队伍中移除玩家 + * @param {{teamCode: string, roleIdToRm: string}} msg 队伍编号;要移除的玩家 Id + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async rmTeammate(msg: {teamCode: string, roleIdToRm: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let { teamCode, roleIdToRm } = msg; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + if (roleId === teamStatus.capId && roleId === roleIdToRm) return resResult(STATUS.COM_BATTLE_RM_SELF); // 队长移除自己视为解散,提示确认 + if (roleId !== teamStatus.capId && roleId !== roleIdToRm) return resResult(STATUS.COM_BATTLE_CAN_NOT_RM); + // if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); // 只有队长可以移除玩家 + + // 移除操作 + let team = await ComBattleTeamModel.removeRole(teamCode, roleIdToRm); + if (!team) return resResult(STATUS.COM_BATTLE_RM_TEAMMATE_ERR); + + teamStatus.roleStatus.some((elem, idx) => { + if (elem.roleId === roleIdToRm) { + teamStatus.roleStatus.splice(idx, 1); + } + }); + teamStatus.roleIds = teamStatus.roleStatus.map(cur => cur.roleId); + if(roleId === teamStatus.capId) { // 队长移除队友,并把他加入黑名单 + teamStatus.blacklist.push(roleIdToRm); + } + + // 先推送离队消息,再将玩家从房间中移除 + sendMessageToTeam(teamCode, PUSH_ROUTE.LEAVE_TEAM, {teamCode, roleId: roleIdToRm}); + removeFromTeamChannel(teamCode, roleIdToRm); + clearComBtlTimer(teamCode); // 移除队员停止解散计时 + let thiz = this; + setTimeout(async () => { + let curTeamStatus = getComTeamByCode(teamCode); + if (validToJoin(curTeamStatus)) { + let roleSt: RoleStatus; + for (let st of curTeamStatus.roleStatus) { + if (st.isCap) { + roleSt = st; + } + } + if (!roleSt) return; + let { roleId, topLineupCe, lv } = roleSt; + await addRobotsToTeam(curTeamStatus, roleId, topLineupCe, lv, 3 - curTeamStatus.roleIds.length); + } + }, COM_BTL_CONST.ASSIST_TIME); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 队长解散队伍 + * @param {{teamCode: string}} msg 要解散的队伍编号 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async dismiss(msg: {teamCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let { teamCode } = msg; + let teamStatus = getComTeamByCode(teamCode); + if(!teamStatus) return resResult(STATUS.SUCCESS); + let result = await dismissTeam(teamStatus, roleId); + return result; + } + + /** + * @description 开始战斗,队长操作或机器人队伍操作 + * @param {{teamCode: string}} msg 队伍编号 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async startBattle(msg: {teamCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let { teamCode } = msg; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + if (teamStatus.capId !== roleId && teamStatus.capId !== 'robot') return resResult(STATUS.COM_BATTLE_CAP_ONLY); + if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_ALREADY_START); + + startTeam(teamStatus); + let team = await ComBattleTeamModel.updateStatusByCode(teamCode, teamStatus.status, teamStatus.startTime, teamStatus.endTime, teamStatus.hasTimeExtraReward); + if (!team) return resResult(STATUS.COM_BATTLE_START_ERR); + + rmCreatedTeamFromRedis(teamCode, teamStatus.lv); + clearComBtlTimer(teamCode); // 战斗开始停止解散计时 + await getComBattleFriendAdd(teamStatus.roleStatus); + sendMessageToTeam(teamCode, PUSH_ROUTE.COMBATTLE_START, {teamCode, roleStatus: teamStatus.roleStatus}); + // 每场倒计时结算 + let thiz = this; + setTimeout(async () => { + let teamStatus = getComTeamByCode(teamCode); + if (teamStatus && teamStatus.status === COM_TEAM_STATUS.FIGHTING) { + clearRobotHurtTimer(teamStatus); + let team = await ComBattleTeamModel.syncTeamData({teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr}, true); + if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); + teamStatus.timeout = true; + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: false, timeout: true}); + deleteComBattle(teamCode); + clearComBattleRoute(redisClient(), teamCode) + } + }, COM_BTL_CONST.BTL_TIME_LMT); + teamStatus.roleStatus.forEach((st, idx) => { + if (st.isRobot === true) { + updateRobotHurtByTime(teamStatus, st, COM_BTL_CONST.ROBOT_BASE_TIME_INTERVAL + idx); + } + }); + await checkTaskInComBattleStart(teamStatus.roleStatus, teamStatus.capId, teamStatus.blueprtId); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 战场中的状态同步,战斗结果判定 + * @param {{teamCode: string, bossHurts: Array<{dataId: number, hurtHp: number}>, killed: number[], curRnd: number}} msg 队伍编号;boss 承伤;武将阵亡;当前回合 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async action(msg: {teamCode: string, bossHurts: Array<{hid: number, dataId: number, hurtHp: number}>, killed: number[], curRnd: number, timegap: number, roundTime: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let { teamCode, killed, bossHurts, curRnd, timegap = 0, roundTime = 0 } = msg; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) { + checkTeamStatusAndSend(teamCode, roleId, sid); + return resResult(STATUS.SUCCESS); + } + if (teamStatus.status !== COM_TEAM_STATUS.FIGHTING) { + checkTeamStatusAndSend(teamCode, roleId, sid); + return resResult(STATUS.SUCCESS); + } + for (let st of teamStatus.roleStatus) { + if (st.roleId === roleId && (!st.heroes || st.heroes.length === 0)) { + return resResult(STATUS.SUCCESS); + } + } + // 重置总血量,计算真实伤害 + const roleSt = teamStatus.findMemberByRoleId(roleId); + if(!roleSt) return resResult(STATUS.SUCCESS); + if(!roleSt.startActionTime || roleSt.startActionTime == 0) { // 第一次调用设置初始 + roleSt.startActionTime = nowSeconds(); + } + if ((roundTime > 0 && roundTime < 500) || (timegap - (nowSeconds() - roleSt.startActionTime) > 5)) { // 前后端误差超过5秒拦截 + return resResult(STATUS.SUCCESS, { + isError: true, + timegap: nowSeconds() - roleSt.startActionTime + }); + } + + let actBossHurts: {dataId: number, hurtHp: number}[] = []; + let totalHurtHp = 0; + teamStatus.bossHpArr.forEach(boss => { + for (let bh of bossHurts) { + if (boss.dataId === bh.dataId && bh.hurtHp < 0) { + let deltaHp = Math.abs(bh.hurtHp); + if (boss.curHp >= deltaHp) { + actBossHurts.push({dataId: boss.dataId, hurtHp: deltaHp}); + totalHurtHp = cal.add(totalHurtHp, deltaHp); + boss.curHp = cal.sub(boss.curHp, deltaHp); + } else if (boss.curHp > 0) { + actBossHurts.push({dataId: boss.dataId, hurtHp: boss.curHp}); + totalHurtHp = cal.add(totalHurtHp, boss.curHp); + boss.curHp = 0; + } + if(bh.hid) { + roleSt.addHeroDamage(bh.hid, deltaHp); + } + } + } + }); + // 更新玩家武将阵亡情况,计算玩家总伤害 + roleSt.totalDmg = cal.add(roleSt.totalDmg, totalHurtHp); + if (killed && killed.length) { + roleSt.killed = Array.from(new Set([...roleSt.killed, ...killed])); + } + + teamStatus.curRnd = curRnd; + teamStatus.bossCurHp = cal.sub(teamStatus.bossCurHp, totalHurtHp); + if (teamStatus.bossCurHp < 0) teamStatus.bossCurHp = 0; + // 推送本次行动情况 + const roleStatus = teamStatus.roleStatus.map(st => {return {roleId: st.roleId, totalDmg: st.totalDmg, killed: st.killed}}); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus, actRoleId: roleId, actBossHurts }); + const result = await handleComBtlProgress(teamStatus); + if (result && result.code !== 0) return result; + return resResult(STATUS.SUCCESS, { + isError: false, + timegap: nowSeconds() - roleSt.startActionTime + }); + } + + // /** + // * ! 客户端给服务器的战斗结束通知-deprecated + // * @param msg + // * @param session + // */ + // async battleEnd(msg: {teamCode: string, isSuccess: boolean}, session: BackendSession) { + // let roleId = session.get('roleId'); + // let { teamCode, isSuccess } = msg; + // let teamStatus = this.teamMap.get(teamCode); + // if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + + // if (isSuccess && teamStatus.bossCurHp <= 0) { + // let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess); + // if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); + // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: isSuccess}); + // } else if (!isSuccess) { + // let team = await ComBattleTeamModel.updateResult(teamCode, roleId, isSuccess); + // if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); + // if (team.status === COM_TEAM_STATUS.LOOSE) { + // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, {teamCode, result: isSuccess}); + // } else { + // sendMessageToTeam(teamCode, PUSH_ROUTE.TEAMMATE_ACT, {teamCode, bossCurHp: teamStatus.bossCurHp, roleStatus: {roleId, battleStatus: 2}}); + // } + // } + // return resResult(STATUS.SUCCESS, { bossCurHp: teamStatus.bossCurHp }); + // } + + /** + * @description 寻宝结算 + * @param {{teamCode: string}} msg 寻宝队伍编号 + * @param {BackendSession} session + * @returns 掉落物品和玩家升级信息 + * @memberof ComBattleHandler + */ + async comBattleEnd(msg: {teamCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let ip = session.get('ip'); + let serverId = session.get('serverId'); + + let { teamCode } = msg; + let team = await ComBattleTeamModel.getTeamByCode(teamCode); + clearRobotHurtTimer(team); + if (!team || team.status !== COM_TEAM_STATUS.WIN) return resResult(STATUS.COM_BATTLE_REWARD_ERR); + let { roleStatus, blueprtId, status, bossHpArr } = team; + let roleSt = roleStatus.find(st => st && st.roleId === roleId); + if(!roleSt) return resResult(STATUS.COM_BATTLE_REWARD_ERR); + + await ComBattleTeamModel.updateRewardSt(teamCode, roleId, true); + const goods = await addItems(roleId, roleName, sid, roleSt.rewards, ITEM_CHANGE_REASON.COM_BATTLE_END); + + return resResult(STATUS.SUCCESS, { battleGoods: goods, teamInfo: {status, teamCode, roleStatus, bossHpArr} }); + } + + async retreat(msg: {teamCode: string}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + let { teamCode } = msg; + let teamStatus = getComTeamByCode(teamCode); + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) { + checkTeamStatusAndSend(teamCode, roleId, sid); + return resResult(STATUS.SUCCESS); + } + if(teamStatus.roleStatus.length > 1) { + return resResult(STATUS.COM_BATTLE_RETREAT_ERR) + } + + clearRobotHurtTimer(teamStatus); + + let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: COM_TEAM_STATUS.LOOSE, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: Date.now() }, false, true); + if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: false }); + + deleteComBattle(teamCode); + clearComBattleRoute(redisClient(), teamCode); + + return resResult(STATUS.SUCCESS, { teamInfo: pick(team, ['status', 'teamCode', 'roleStatus', 'bossHpArr']) }); + } + + async getComBtlStatus(msg: {teamCode: string}, session: BackendSession) { + let { teamCode } = msg; + let roleStatus: RoleStatus[], status: number, bossHpArr: BossHp[], timeout: boolean, endTime = 0; + let memTeam = getComTeamByCode(teamCode); + if (memTeam) { + ({ roleStatus, status, bossHpArr, timeout, endTime } = memTeam); + } else { + let dbTeam = await ComBattleTeamModel.getTeamByCode(teamCode); + if (!dbTeam) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + ({ roleStatus, status, bossHpArr, timeout, endTime } = dbTeam); + clearComBattleRoute(redisClient(), teamCode); + } + return resResult(STATUS.SUCCESS, { teamInfo: {status, teamCode, roleStatus, bossHpArr, timeout, endTime} }); + } + + /** + * @description 获取自己一段时间内的寻宝记录 + * @param {{}} msg + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async getTeamRec(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let timef = getTimeFunD(); + let teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, timef.getBeforeDayWithHour(2)); + if (!teams) return resResult(STATUS.COM_BATTLE_NO_RECENT_REC); + + return resResult(STATUS.SUCCESS, {teamInfos: teams}); + } + + /** + * @description 获取藏宝图数量 + * @param {{ids: number[]}} msg 藏宝图Id数组,可选参数 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async getBlueprtCount(msg: {ids: number[]}, session: BackendSession) { + let roleId = session.get('roleId'); + let { ids } = msg; + let blueprts: ItemType[]; + if (ids && ids.length) { + blueprts = await ItemModel.findbyRoleAndIds(roleId, ids); + } else { + blueprts = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); + } + return resResult(STATUS.SUCCESS, { blueprts }); + } + + /** + * @description 获取今日已助战次数 + * @param {{}} msg + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async getAssistCnt(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let cnt = await getAllAssistCnt(roleId); + return resResult(STATUS.SUCCESS, {cnt}); + } + /** + * @description 获取寻宝可用次数,包含藏宝图数量和助战次数,分别用于创建和加入队伍 + * @param {{}} msg 无参数 + * @param {BackendSession} session + * @returns + * @memberof ComBattleHandler + */ + async getComBtlCnt(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let cnt = await getAllAssistCnt(roleId); + const blueprts = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); + let capExtraCnt = await getCapExtraCnt(roleId); + return resResult(STATUS.SUCCESS, { blueprts, assistCnt: cnt, capExtraCnt }); + } + + async sendTeamMsg(msg: { teamCode: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + + const { teamCode, type, content, targetRoleId, targetMsgCode } = msg; + const result = await pushComBtlTeamMsg(teamCode, roleId, roleName, type, MSG_SOURCE.TEAM_ROLE, content, targetRoleId, targetMsgCode); + if (!result) { + return resResult(STATUS.WRONG_PARMS); + } + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType(CHANNEL_PREFIX.TEAM) }); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 一键邀请,自动在世界频道发送消息 + * @param {{ teamCode: string }} msg + * @param {BackendSession} session + * @memberof ComBattleHandler + */ + async autoInvite(msg: { teamCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let guildCode = session.get('guildCode'); + if (!guildCode) return resResult(STATUS.COM_BATTLE_INVITE_GUILD_ERR); + + const { teamCode } = msg; + let teamStatus = getComTeamByCode(teamCode); + if(!teamStatus) return resResult(STATUS.WRONG_PARMS); + await pushTeamInviteMsg(roleId, roleName, guildCode, teamCode, teamStatus.blueprtId, teamStatus.lv, teamStatus.ceLimit); + await ComBattleTeamModel.invite(teamCode, guildCode); + return resResult(STATUS.SUCCESS); + } + + /** + * @description 邀请队友 + * @param {{ teamCode: string, targetRoleId: string }} msg + * @param {BackendSession} session + * @memberof ComBattleHandler + */ + async inviteTeammate(msg: { teamCode: string, targetRoleId: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let guildCode = session.get('guildCode'); + const { teamCode, targetRoleId } = msg; + + let teamStatus = getComTeamByCode(teamCode); + if(!teamStatus) return resResult(STATUS.WRONG_PARMS); + + let role = await RoleModel.findByRoleId(targetRoleId, 'lv'); + if(comBtlLvInvalid(role.lv, [teamStatus.lv])) { + return resResult(STATUS.COM_BATTLE_INVITE_LV_NOT_ENOUGH); + } + if (role.topLineupCe < teamStatus.ceLimit) { + return resResult(STATUS.COM_BATTLE_CE_LIMIT); + } + + await ComBattleTeamModel.invite(teamCode, targetRoleId); + let relation = await getFriendRelationType(roleId, targetRoleId); + const msgData = await pushFriendTeamInviteMsg(roleId, roleName, teamCode, teamStatus.blueprtId, targetRoleId, relation); + if (!msgData) return resResult(STATUS.WRONG_PARMS); + const roleInfo = await getSimpleRoleInfo(targetRoleId); + + let index = teamStatus.blacklist.indexOf(targetRoleId); + if(index != -1) { + teamStatus.blacklist.splice(index, 1); + } + + return resResult(STATUS.SUCCESS, {...msgData, roleInfo}); + } + + /** + * @description 最近组队过的队友列表 + * @param {} msg + * @param {BackendSession} session + */ + async getRecentTeammates(msg: { }, session: BackendSession) { + let roleId = session.get('roleId'); + + const teams = await ComBattleTeamModel.getTeamByRoleAndTime(roleId, null, getZeroPointD()); + let roleIdList = new Array(); + for(let { roleIds } of teams) { + for(let r of roleIds) { + if(r != roleId) roleIdList.push(r); + } + } + const roles = await RoleModel.findByRoleIds(roleIdList, ROLE_SELECT.SHOW_SIMPLE, true); + let result = new Array(); + for(let role of roles) { + if(role.quitTime == role.loginTime) { + let r = new FriendParams(role); + result.push(r); + } + } + + return resResult(STATUS.SUCCESS, { list: result }); + } + + async getTeamInvitation(msg: { }, session: BackendSession) { + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + let role = await RoleModel.findByRoleId(roleId, 'lv topLineupCe'); + const assistCnt = await getAllAssistCnt(roleId); + + let { minLv, maxLv } = getComBtlLvByPlayerLv(role.lv); + let refreshTime = nowSeconds() - INFO_WINDOW.TEAM_INFORMATION_TIME; + const invitations = await ComBattleTeamModel.findInvitations(roleId, guildCode, minLv, maxLv, role.topLineupCe, refreshTime, INFO_WINDOW.TEAM_VIEW); + let roleIds = invitations.map(cur => cur.capId); + let roles = await RoleModel.findByRoleIds(roleIds); + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + const teams: ComBattleInvitation[] = []; + for(let invitation of invitations) { + let leader = roles.find(role => role.roleId == invitation.capId); + if(leader) { + let leaderParam = new FriendParams(leader); + let type = getRecommendType(myFriendRelation, roleId, leader.roleId); + leaderParam.setType(type); + + let serverName = await getServerName(leader.serverId); + leaderParam.setServerName(leader.serverId, serverName); + teams.push(new ComBattleInvitation(invitation, leaderParam)); + } + } + + return resResult(STATUS.SUCCESS, { teams, assistCnt }); + } + + // ! 测试接口 + /** + * 修改玩家的等级-方便测试组队 + * 寻宝创建队伍 - 会先调用这个接口 + * @param {{ targetLv: number }} msg + * @param {BackendSession} session + * @return {*} + * @memberof ComBattleHandler + */ + async debugSetRoleLv(msg: { magicWord: string, targetLv: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const { targetLv, magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let role = await RoleModel.updateRoleInfo(roleId, { lv: targetLv }); + return resResult(STATUS.SUCCESS, { lv: role.lv, roleId }); + } + +} + diff --git a/game-server/app/servers/comBattle/remote/comBattleRemote.ts b/game-server/app/servers/comBattle/remote/comBattleRemote.ts index 83b93becb..ad0e1cfca 100644 --- a/game-server/app/servers/comBattle/remote/comBattleRemote.ts +++ b/game-server/app/servers/comBattle/remote/comBattleRemote.ts @@ -1,145 +1,146 @@ -import { Application, ChannelService, FrontendSession, RemoterClass, HandlerService, pinus, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts'; -import { handleComBtlProgress, _addToSearchingTeams } from '../../../services/battle/comBattleService'; -import { MemComBtlTeam } from '../../../domain/battleField/ComBattleTeamField'; -import { errlogger } from '../../../util/logger'; -import { saveComBattleMemory } from '../../../services/log/memoryLogService'; -import { setApiIsClose } from '../../../services/chatService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import { setKvToMemory } from '../../../services/pushService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ComBattleRemote(app); -} - -export class ComBattleRemote { - bossHp = 10000; - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - - public async checkMyTeam(roleId: string ) { - try { - let teamMap: Map = this.app.get('teamMap'); - let hasMyTeam = false; - for(let [,team] of teamMap) { - if(team.roleIds.indexOf(roleId) > -1) { - hasMyTeam = true; break; - } - } - return hasMyTeam - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - - public async addToSearchingTeams(teamCode: string, roleId: string, sid: string) { - try { - await _addToSearchingTeams(teamCode, roleId, sid); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public saveComBattleMemory() { - try { - return saveComBattleMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, FrontendSession, RemoterClass, HandlerService, pinus, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '../../../consts'; +import { handleComBtlProgress, _addToSearchingTeams } from '../../../services/battle/comBattleService'; +import { MemComBtlTeam } from '@domain/battleField/ComBattleTeamField'; +import { errlogger } from '../../../util/logger'; +import { saveComBattleMemory } from '../../../services/log/memoryLogService'; +import { setApiIsClose } from '../../../services/chatService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import { setKvToMemory } from '../../../services/pushService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { gameData, reloadResources } from '@pubUtils/data'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ComBattleRemote(app); +} + +export class ComBattleRemote { + bossHp = 10000; + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + + public async checkMyTeam(roleId: string ) { + try { + let teamMap: Map = this.app.get('teamMap'); + let hasMyTeam = false; + for(let [,team] of teamMap) { + if(team.roleIds.indexOf(roleId) > -1) { + hasMyTeam = true; break; + } + } + return hasMyTeam + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + + public async addToSearchingTeams(teamCode: string, roleId: string, sid: string) { + try { + await _addToSearchingTeams(teamCode, roleId, sid); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public saveComBattleMemory() { + try { + return saveComBattleMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/connector/filter/global.ts b/game-server/app/servers/connector/filter/global.ts index 9a71add5b..78c07e02b 100644 --- a/game-server/app/servers/connector/filter/global.ts +++ b/game-server/app/servers/connector/filter/global.ts @@ -1,21 +1,21 @@ import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback, pinus, FrontendSession} from "pinus"; // import { checkEvent } from '../../../services/eventSercive'; -import { refresh } from '../../../services/refreshService'; -import { checkPrivateChat, checkGuildChat, checkOtherChat, checkRoleName, checkGuildName } from "../../../services/sdkService"; -import { resResult, genCode } from "../../../pubUtils/util"; -import { checkWhiteList, MsgEncrypt } from "../../../pubUtils/sysUtil"; -import { BLOCK_TYPE, CHANNEL_PREFIX, MSG_TYPE, PUSH_ROUTE, STATUS } from "../../../consts"; -import { nowSeconds } from "../../../pubUtils/timeUtil"; -import { getServerMainten } from "../../../services/gmService"; -import { errlogger, infologger } from "../../../util/logger"; -import { gameData } from "../../../pubUtils/data"; -import { sendMessageToUser } from "../../../services/pushService"; -import { isCheckWord, isSkipEncode } from "../../../pubUtils/sdkUtil"; -import { isDevelopEnv } from "../../../services/utilService"; +import { refresh } from "@pubUtils/refreshService"; +import { checkPrivateChat, checkGuildChat, checkOtherChat, checkRoleName, checkGuildName } from "@pubUtils/sdkService"; +import { resResult, genCode } from "@pubUtils/util"; +import { checkWhiteList, MsgEncrypt } from "@pubUtils/sysUtil"; +import { BLOCK_TYPE, CHANNEL_PREFIX, MSG_TYPE, PUSH_ROUTE, STATUS } from "@consts"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { getServerMainten } from "@pubUtils/gmService"; +import { errlogger, infologger } from "@pubUtils/logger"; +import { gameData } from "@pubUtils/data"; +import { sendMessageToUser } from "@pubUtils/pushService"; +import { isCheckWord, isSkipEncode } from "@pubUtils/sdkUtil"; +import { isDevelopEnv } from "@pubUtils/utilService"; import { isNumber } from "underscore"; -import { getServerCreateTime, redisClient } from "../../../services/redisService"; -import { checkRouteParam } from "../../../services/checkParam"; -import { isApiClose } from "../../../services/chatService"; +import { getServerCreateTime, redisClient } from "@pubUtils/redisService"; +import { checkRouteParam } from "@pubUtils/checkParam"; +import { isApiClose } from "@pubUtils/chatService"; export function globalFilter(app: Application) { return new Filter(app); @@ -29,13 +29,12 @@ class Filter { this.app = app; } - public async before (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { + public async before (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { const serverId: number = session.get('serverId'); const sid: string = session.get('sid'); const roleId: string = session.get('roleId'); const uid: number = session.get('userid'); const ip: string = session.get('ip'); - // console.log('*********** global before ip', ip) const version: string = session.get('version'); const isNewUser: boolean = session.get('isNewUser'); let guildCode = session.get('guildCode'); @@ -46,172 +45,293 @@ class Filter { if(!this.checkPassEncrypt(routeRecord.route)) { msg = this.decryptMsg(msg, session); if(!msg) return next(new Error('globalFilter'), resResult(STATUS.WRONG_PARMS, { route: routeRecord.route })); - - if(!this.checkTimeStamp(msg)) return next(new Error('globalFilter'), resResult(STATUS.TIMESTAMP_ERR, { route: routeRecord.route })); - if(!this.checkDuplicateAccess(msg)) return next(new Error('globalFilter'), resResult(STATUS.DUPLICATE_ACCESS, { route: routeRecord.route })) - } - msg = this.setMsg(msg, { logCode }); - // 访问频率控制 - if(!this.checkFrequency(routeRecord.route, msg, roleId)) { - return next(new Error('globalFilter'), resResult(STATUS.ACCESS_BUSY, { route: routeRecord.route })); - } - if(!this.checkFunction(routeRecord.route, msg)) { - return next(new Error('globalFilter'), resResult(STATUS.FUNCTION_CLOSE, { route: routeRecord.route })); + // @ts-ignore + if(!this.checkTimeStamp(msg)) return next(new Error('globalFilter'), resResult(STATUS.TIMESTAMP_ERR, { route: routeRecord.route })); } - if(!checkRouteParam(routeRecord.route, msg)) { - return next(new Error('globalFilter'), resResult(STATUS.WRONG_PARMS, { route: routeRecord.route })); + // @ts-ignore + if (isApiClose(routeRecord.route)) { + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.API_CLOSE, { route: routeRecord.route })); } - // 玩家屏蔽 - if(blockType == BLOCK_TYPE.BLOCK) return next(new Error('globalFilter'), resResult(STATUS.BLOCKED, { route: routeRecord.route })); - if(blockType == BLOCK_TYPE.BAN && this.checkBanRoute(routeRecord.route)) { - return next(new Error('globalFilter'), resResult(STATUS.BANNED, { route: routeRecord.route })); - } - - session.push('teamCode', () => {}); - - if(isCheckWord(isDevelopEnv())) { - let hasBlockWords = await this.checkHasBlockWord(routeRecord.route, msg, roleId, serverId, guildCode); - if(hasBlockWords) return next(new Error('globalFilter'), resResult(STATUS.BLOCK_WORDS, { route: routeRecord.route })); - } - - if(routeRecord.route == 'guild.guildHandler.createGuild') { - let guildCode = genCode(6); - msg.guildCode = guildCode; - } - - if(routeRecord.route != 'connector.entryHandler.enter' && await this.checkMainten(serverId, sid, ip, uid, isNewUser)) { - sendMessageToUser(roleId, PUSH_ROUTE.SERVER_MAINTENANCE, resResult(STATUS.SERVER_MAINTENANCE), sid); + if(await this.checkMainten(serverId, sid, ip, uid, isNewUser)) { const mainten = getServerMainten(serverId); - return next(new Error('globalFilter'), resResult(STATUS.SERVER_MAINTENANCE, { route: routeRecord.route, curVersion: version, minVersion: mainten.version })); + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.SERVER_MAINTAIN, { + route: routeRecord.route, + startTime: mainten.startTime, + endTime: mainten.endTime + })); } - next(null); - }; - - public async after (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { - //刷新 - await refresh(session); - - infologger.debug('global after', msg && msg.logCode, routeRecord.route, msg && JSON.stringify(msg), resp && JSON.stringify(resp), session && session.get('roleId')); - if(!this.checkPassEncrypt(routeRecord.route)) { - let data = this.encryptMsg(resp, session); - if(!data) return next(new Error('response data err')); - resp = this.setResp(resp, data); - } - - next(null); - }; - - // 检查调用频率 - private checkFrequency (route: string, msg: any, roleId: string) { - let protect = gameData.serverConst.PROTECT_API.find(cur => { - if(cur.route == route) { - let paramOK = true; - for(let key in cur.param) { - if(msg[key] != cur.param[key]) { - paramOK = false; break; - } + // @ts-ignore + if(!isDevelopEnv(this.app.get('env'))) { + if(!this.checkPassEncrypt(routeRecord.route)) { + if(!this.checkSign(routeRecord.route, msg, session)) { + infologger.error('checkSign false', routeRecord.route, msg, session.uid); + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.SIGN_ERROR, { route: routeRecord.route })); } - if(paramOK) return true; - } - return false; - }); - if(!protect) { - return true; - } - let keyOfRouteWithUser = `${protect.id}_${roleId}`; - if(this.accessTime && this.accessTime.has(keyOfRouteWithUser)) { - console.log(this.accessTime.get(keyOfRouteWithUser) - Date.now()); - if(Date.now() - this.accessTime.get(keyOfRouteWithUser) < protect.interval) { - errlogger.info(`${keyOfRouteWithUser} 间隔时间小于${protect.interval}ms,为 ${Date.now() - this.accessTime.get(keyOfRouteWithUser)}`); - return false; } } - if(!this.accessTime) this.accessTime = new Map(); - this.accessTime.set(keyOfRouteWithUser, Date.now()); - return true; - } - - // 检查该接口是否关闭 - private checkFunction (route: string, msg: any) { - if(isApiClose()) { - let isClose = gameData.serverConst.CLOSE_APIS.find(cur => { - if(cur.route == route) { - if(cur.param == null) return true; - for(let key in cur.param) { - if(cur.param[key] == true && msg[key] != undefined) return true; - if(cur.param[key] && msg[key] == cur.param[key]) return true; - } - } - return false; - }); - return !isClose + + if(roleId) { + // @ts-ignore + if(blockType && blockType === BLOCK_TYPE.ROLE) { + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.ROLE_BLOCKED, { route: routeRecord.route })); + } } - return true; - } - - // 这个接口是否需要加密解密 - private checkPassEncrypt (route: string) { - return isSkipEncode(isDevelopEnv()) || route.startsWith('gm.') || route == 'connector.entryHandler.gmEnter' || route == 'gate.gateHandler.queryEntry'; - } - - // 解密接口 - private decryptMsg (msg: any, session: FrontendOrBackendSession) { - let msgEncrypt = new MsgEncrypt({ encodeK: msg?.k, encodeV: msg?.v }); - let { aesKey, aesIV } = msgEncrypt.getKv(); - msg = this.setMsg(msg, msgEncrypt.decryptMsg(msg?.data)); - if(!msg) return false; - - session.set('k', aesKey); - session.set('v', aesIV); - session.push('k', () => {}); - session.push('v', () => {}); - return msg - } - - // 解密接口 - private encryptMsg (resp: any, session: FrontendOrBackendSession) { - let msgEncrypt = new MsgEncrypt({ k: session.get('k'), v: session.get('v')}); - let data = msgEncrypt.encryptMsg(resp); - return data; + + if(await this.checkDuplicateAccess(msg)) { + infologger.error('checkDuplicateAccess false', routeRecord.route, msg); + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.DUPLICATE_ACCESS, { route: routeRecord.route })); + } + + if(routeRecord.route.indexOf('Handler.') != -1) { + if (!checkRouteParam(msg, routeRecord.route)) { + infologger.error('checkRouteParam false', routeRecord.route, msg); + return next(new Error('globalFilter'), resResult(STATUS.WRONG_PARMS, { route: routeRecord.route })); + } + } + + if(msg.body) { + msg = msg.body; + } + + if(!this.checkBlackList(roleId, serverId)) { + infologger.error('checkBlackList true', roleId, serverId); + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.IN_BLACK_LIST, { route: routeRecord.route })); + } + + if(await this.checkHasBlockWord(routeRecord.route, msg, roleId, serverId, guildCode)) { + infologger.error('checkHasBlockWord true', roleId, serverId); + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.HAS_BLOCK_WORD, { route: routeRecord.route })); + } + + if(routeRecord.route.indexOf('battle.') != -1) { + // @ts-ignore + if(!this.checkVersion(routeRecord.route, version)) { + // @ts-ignore + return next(new Error('globalFilter'), resResult(STATUS.VERSION_TOO_LOW, { route: routeRecord.route, version: version })); + } + } + + const beginTime = Date.now(); + this.accessTime.set(`${roleId}_${routeRecord.route}`, beginTime); + // @ts-ignore + next(); } - // 传入的msg的修改 - private setMsg (msg:any, targetObj: any) { - if(!msg || !targetObj || typeof targetObj != 'object') { - return false; - } - delete msg.k; - delete msg.v; - if(typeof msg.data == 'string') delete msg.data; - for(let key in targetObj) { - if(targetObj.hasOwnProperty(key)) { - msg[key] = targetObj[key]; - } + private checkVersion(route: string, version: string) { + if(!version) return true; + // @ts-ignore + const minVersion = gameData.serverConst.MIN_VERSION[route]; + if(!minVersion) return true; + return version >= minVersion; + } + + private decryptMsg(msg: any, session: FrontendOrBackendSession) { + if (!session) return msg; + const publicKey = session.get('publicKey'); + const encode = session.get('encode'); + // @ts-ignore + if(!encode || encode != MsgEncrypt.RSA) return msg; + if(!publicKey) return msg; + try { + // @ts-ignore + const decryptMsg = pinus.crypto.decrypt(Buffer.from(publicKey, 'base64'), Buffer.from(msg, 'base64')); + msg = JSON.parse(decryptMsg.toString()); + } catch (e) { + errlogger.error('decryptMsg error', e); + return null; } return msg; } - // 传出的resp的修改 - private setResp(resp: any, data: string) { - for(let key in resp) { - if(resp.hasOwnProperty(key)) { - delete resp[key]; - } - } - resp.data = data; - return resp; + private checkSign(route: string, msg: any, session: FrontendOrBackendSession) { + if (!session) return false; + const sign = msg['sign']; + const token = session.get('token'); + if (!sign || !token) return false; + const md5 = require('crypto').createHash('md5'); + const str = route + JSON.stringify(msg) + token; + const signVal = md5.update(str).digest('hex'); + return sign === signVal; } - - // 禁言的接口 - private checkBanRoute (route: string) { - return [ + + private checkPassEncrypt(route: string) { + // @ts-ignore + if(!gameData.serverConst.NOT_CHECK_SIGN_ROUTES) return false; + // @ts-ignore + return gameData.serverConst.NOT_CHECK_SIGN_ROUTES.indexOf(route) != -1; + } + + private checkBlackList(roleId: string, serverId: number) { + if(!roleId) return true; + const blackRoleMap = this.app.get('blackRoleMap') || new Map(); + const roleList = blackRoleMap.get(serverId); + if(!roleList) return true; + // @ts-ignore + if(roleList.indexOf(roleId) != -1) { + return false; + } + return true; + } + + private checkRoleFrom(route: string, session: FrontendOrBackendSession) { + const needRoutes = [ + 'role.roleHandler.rename', + 'role.roleHandler.setHead', + 'role.roleHandler.setSign', + ]; + if(needRoutes.indexOf(route) == -1) return true; + return session.get('roleId') === session.get('createRoleId'); + } + + private checkNoRepeatRoute(route: string, session: FrontendOrBackendSession) { + if(!session) return true; + const noRepeatRoutes = [ + 'role.roleHandler.createRole', + 'gate.gateHandler.login', + 'connector.entryHandler.enter', + ]; + if(noRepeatRoutes.indexOf(route) == -1) return true; + if(session.get('hasEnter')) { + return false; + } + session.set('hasEnter', true); + return true; + } + + private checkChat(route: string, session: FrontendOrBackendSession, msg: any) { + if(route.indexOf('chat.') == -1) return true; + // @ts-ignore + if(session.get('blockType') == BLOCK_TYPE.CHAT) { + return false; + } + + const needCheckRoutes = [ 'chat.chatHandler.sendPrivateMessage', 'chat.chatHandler.sendGroupMessage', 'battle.comBattleHandler.sendTeamMsg', 'battle.barrageHandler.sendBarrage', + ]; + if(needCheckRoutes.indexOf(route) == -1) return true; + // @ts-ignore + const sendLimit = gameData.serverConst.SEND_CHAT_LIMIT; + const roleId = session.get('roleId'); + getServerCreateTime(session.get('serverId')).then((now: number) => { + const lastTime = this.accessTime.get(`${roleId}_${route}`) || 0; + if(now - lastTime < sendLimit) { + return false; + } + }); + return true; + } + + private isNoCheckRoute(route: string) { + return [ + 'gate.gateHandler.login', + 'connector.entryHandler.enter', + 'role.roleHandler.initRole', + 'role.roleHandler.createRole', + 'chat.chatHandler.getInitData', + 'chat.chatHandler.getChatList', + 'chat.chatHandler.getPrivateChatList', + 'battle.barrageHandler.getBarrages', + 'activity.activityHandler.getActivityList', + 'activity.activityHandler.getServerTime', + 'role.roleHandler.getRoleInitInfo', + 'role.roleHandler.getRoleOtherInfo', + 'gate.gateHandler.getServerList', + 'gate.gateHandler.getServerList1', + 'gate.gateHandler.getServerTime', + 'gm.gmHandler.getServerList', + 'gm.gmHandler.getServerList1', + 'gm.gmHandler.getServerTime', + 'role.roleHandler.getOtherRoleInfo', + 'battle.normalBattleHandler.getChapterInfo', + 'battle.normalBattleHandler.getChapterStarReward', + 'battle.normalBattleHandler.getBoxReward', + 'battle.pvpHandler.getPvpInfo', + 'battle.pvpHandler.getRankList', + 'battle.ladderHandler.getLadderInfo', + 'battle.ladderHandler.getLadderRankList', + 'battle.ladderHandler.getSeasonReward', + 'role.roleHandler.getRechargeList', + 'role.roleHandler.getVipInfo', + 'role.roleHandler.getMonthCard', + 'activity.signInHandler.getSignInInfo', + 'activity.dailyGiftsHandler.getInfo', + 'activity.dailyMealHandler.getInfo', + 'activity.dailyRMBGiftsHandler.getInfo', + 'activity.growthFundHandler.getInfo', + 'activity.monthlyFundHandler.getInfo', + 'activity.sevenDaysHandler.getInfo', + 'activity.firstGiftHandler.getInfo', + 'activity.rechargeMoneyHandler.getInfo', + 'activity.rebateHandler.getInfo', + 'activity.thirtyDaysHandler.getInfo', + 'activity.timeLimitRankHandler.getRankList', + 'activity.timeLimitRankHandler.getMyRankInfo', + 'guild.guildHandler.getGuildList', + 'guild.guildHandler.getGuildDetail', + 'guild.guildHandler.getGuildMemberList', + 'guild.guildHandler.getApplyList', + 'guild.guildHandler.getGuildLog', + 'guild.guildHandler.searchGuild', + 'guild.guildTrainHandler.getTrainInfo', + 'guild.guildTrainHandler.getDonateLog', + 'guild.guildRefineHandler.getRefineLog', + 'guild.guildBossHandler.getGuildBossDetail', + 'guild.guildBossHandler.getRankList', + 'guild.gvgHandler.getGVGInfo', + 'guild.gvgBattleHandler.getSeasonReward', + 'guild.gvgBattleHandler.getRankList', + 'guild.gvgBattleHandler.getMyRankInfo', + 'guild.wishPoolHandler.getWishPoolInfo', + 'activity.popUpShopHandler.getPopUpShopInfo', + 'activity.yuanbaoShopHandler.getYuanbaoShopInfo', + 'activity.refreshShopHandler.getRefreshShopInfo', + 'activity.selfServiceShopActivityHandler.getSelfServiceShopInfo', + 'activity.forgeHandler.getForgeInfo', + 'activity.limitPackageHandler.getLimitPackageInfo', + 'battle.towerBattleHandler.getTowerInfo', + 'battle.towerBattleHandler.getTowerRankList', + 'battle.towerBattleHandler.getMyTowerRankInfo', + 'battle.expeditionBattleHandler.getExpeditionInfo', + 'battle.expeditionBattleHandler.getExpeditionRankList', + 'battle.dungeonBattleHandler.getDungeonInfo', + 'battle.friendBattleHandler.getFriendBattleInfo', + 'battle.friendBattleHandler.getFriendBattleRecord', + 'battle.rougeHandler.getRougeInfo', + 'battle.rougeHandler.getRougeRecord', + 'activity.weeklyFundHandler.getInfo', + 'activity.monthlyTicketHandler.getInfo', + 'activity.newHeroGachaHandler.getNewHeroGachaInfo', + 'activity.newHeroGKHandler.getNewHeroGKInfo', + 'activity.newHeroGiftsHandler.getNewHeroGiftsInfo', + 'activity.groupShopHandler.getGroupShopInfo', + 'activity.luckyHandler.getLuckyInfo', + 'activity.luckyTurntableHandler.getLuckyTurntableInfo', + 'activity.treasureHuntHandler.getTreasureHuntInfo', + 'activity.bindPhoneHandler.getPhoneState', + 'activity.midAutumnHandler.getMidAutumnInfo', + 'activity.dragonBoatHandler.getDragonBoatInfo', + 'activity.qixiHandler.getQixiInfo', + 'activity.chongyangHandler.getChongyangInfo', + 'activity.novemberHandler.getNovemberInfo', + 'activity.entertainHandler.getEntertainInfo', + 'activity.miniGameHandler.getMiniGameInfo', + 'activity.activityMonopolyHandler.getActivityMonopolyInfo', + 'activity.vipRechargeMoneyHandler.getVipRechargeMoneyInfo', + 'activity.refreshTaskHandler.getRefreshTaskInfo', + 'battle.barrageHandler.sendBarrage', 'guild.guildHandler.sendMail', 'guild.guildHandler.setGuildInfo', 'guild.gvgManageHandler.sendMail', @@ -220,59 +340,58 @@ class Filter { 'guild.gvgBattleHandler.setNotice', ].indexOf(route) != -1 } - - // 检查聊天屏蔽词 - private async checkHasBlockWord (route: string, msg: any, roleId: string, serverId: number, guildCode: string) { + + private async checkHasBlockWord (route: string, msg: any, roleId: string, serverId: number, guildCode: string) { let hasBlockWords = false; switch(route) { case 'chat.chatHandler.sendPrivateMessage': { let result = await checkPrivateChat(roleId, msg.targetRoleId, msg.type == MSG_TYPE.IMG? "表情": msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'chat.chatHandler.sendGroupMessage': { if(msg.channel == CHANNEL_PREFIX.GUILD) { let result = await checkGuildChat(roleId, guildCode, msg.type == MSG_TYPE.IMG? "表情": msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } else { let result = await checkOtherChat(roleId, msg.channel, msg.type == MSG_TYPE.IMG? "表情": msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } } case 'battle.comBattleHandler.sendTeamMsg': { let result = await checkOtherChat(roleId, CHANNEL_PREFIX.TEAM, msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'battle.barrageHandler.sendBarrage': { let result = await checkOtherChat(roleId, CHANNEL_PREFIX.WORLD, msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'guild.guildHandler.sendMail': { let result = await checkGuildChat(roleId, guildCode, msg.info); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'role.roleHandler.rename': case 'role.roleHandler.initRole': { let result = await checkRoleName(roleId, msg.roleName); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'guild.guildHandler.createGuild': case 'guild.guildHandler.setGuildInfo': { let result = await checkGuildName(guildCode, serverId, msg.name, msg.notice); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'guild.gvgManageHandler.createLeague': @@ -280,32 +399,31 @@ class Filter { case 'guild.gvgBattleHandler.setNotice': { let result = await checkGuildName(guildCode, serverId, msg.name, msg.notice); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } case 'guild.gvgManageHandler.sendMail': case 'guild.gvgManageHandler.recruit': { let result = await checkGuildChat(roleId, guildCode, msg.content); - if(!result) hasBlockWords = true; + if(!result) hasBlockWords = true; break; } } return hasBlockWords; } - // 检查是否维护中 private async checkMainten(serverId: number, sid: string, ip: string, uid: number, isNewUser: boolean) { if(!sid) return false; const mainten = getServerMainten(serverId); - if(!mainten) return false // 该服务器维护 + if(!mainten) return false if(mainten.startTime > nowSeconds() || mainten.endTime < nowSeconds()) return false; - + let isWhiteList = await checkWhiteList(this.app.get('env'), ip, uid); if(isWhiteList) return false; if(isNewUser) return false; - + return true } @@ -328,4 +446,4 @@ class Filter { await redis.expireAsync(`cs: ${cs}`, gameData.serverConst.ACCESS_CODE_EXPIRE_TIME/1000); return true; } -} \ No newline at end of file +} diff --git a/game-server/app/servers/connector/handler/entryHandler.ts b/game-server/app/servers/connector/handler/entryHandler.ts index 3a8d34d32..6589dd4e8 100644 --- a/game-server/app/servers/connector/handler/entryHandler.ts +++ b/game-server/app/servers/connector/handler/entryHandler.ts @@ -1,423 +1,424 @@ -import { STATUS } from './../../../consts/statusCode'; -import { RoleModel, RoleType } from './../../../db/Role'; -import { UserModel, UserType } from '../../../db/User'; -import { GMUserModel } from '../../../db/GMUser'; -import { Application, HandlerService, pinus, } from 'pinus'; -import { FrontendSession } from 'pinus'; -import { HeroModel } from './../../../db/Hero'; -import { compareVersion, genCode, generateStr, resResult } from '../../../pubUtils/util'; -import { COM_BTL_QUALITY, HERO_SELECT, DEBUG_MAGIC_WORD, REDIS_KEY, TASK_TYPE, ENTERY_ROLE_PICK, COUNTER, DEFAULT_LV, TA_USERSET_TYPE, LOG_TYPE, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE } from '../../../consts'; -// import { loginRefresh } from '../../../services/playerEventService'; -import { nowSeconds, getZeroPoint } from '../../../pubUtils/timeUtil'; -import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin, getOnlineRoleByUserCode } from '../../../services/redisService'; - -import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGroupShopChannel, leaveGuildAuctionChannel, leaveGuildChannel, leaveGVGAreaChannel, leaveGVGAreaTeamChannel, leaveGVGCityTeamChannel, leaveSysChannel, leaveWorldAuctionChannel, leaveWorldChannel } from '../../../services/chatService'; -import { reportOneOnline, savePlayTime } from '../../../services/authenticateService'; -import { checkTaskInEntry, } from '../../../services/task/taskService'; -import { pushData, kickUser, getModuleData, assignServer, leaveServer } from '../../../services/connectorService'; -// import { setComBtlOnUserLeave } from '../../../services/comBattleService'; -import Counter from '../../../db/Counter'; -import { getExpByLv } from '../../../pubUtils/data'; -import { reportCreateRoleEventToTa, reportTAEvent, reportTAUserSet } from '../../../services/sdkService'; -import { saveLoginAndOutLog } from '../../../pubUtils/logUtil'; -import { sendMessageToAllWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; -import { checkIsNewUser, getIpLocation } from '../../../services/roleService'; -import { leaveRaceActivityToRemote } from '../../../services/guildActivity/guildActivityService'; -import { leaveCity } from '../../../services/gvg/gvgBattleService'; -import { autoCreateServerWhenRoleInit } from '../../../services/serverService'; -import { getHiddenData } from '../../../services/memoryCache/hiddenData'; -import { ServerlistModel } from '../../../db/Serverlist'; -import { checkWhiteList } from '../../../pubUtils/sysUtil'; -import { getAp } from '../../../services/actionPointService'; -import { RegionModel } from '../../../db/Region'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new EntryHandler(app); -} - -export class EntryHandler { - constructor(private app: Application) { - } - - /** - * New client entry chat server. - * - * @param {Object} msg request message - * @param {Object} session current session object - */ - async enter(msg: { token: string, serverId: number, version: string }, session: FrontendSession) { - // console.log('****** entry before', Date.now()); - let self = this; - let serverId = msg.serverId; - let curRegion = await RegionModel.findRegionByEnv(pinus.app.get('env')); - const versionFlag = compareVersion(msg.version, curRegion?.minVersion); - if (!curRegion || versionFlag < 0) { - //版本号太低 - return resResult(STATUS.VERSION_ERR, { version: curRegion.minVersion }); - } - - let user = await UserModel.findUserByToken(msg.token); - if (!user) { - console.log('user token not found'); - return resResult(STATUS.TOKEN_ERR); - } - - let ip = this.getIp(session); - let isWhiteList = await checkWhiteList(pinus.app.get('env'), ip, user.uid); - let ipLocation = await getIpLocation(ip); - let role = await RoleModel.findByUidAndSetTime(user.uid, serverId, ip, ipLocation, null, true); - if (!role) { - return resResult(STATUS.ROLE_NOT_FOUND); - } - - let onlineRoleId = isWhiteList? role.roleId: await getOnlineRoleByUserCode(user.userCode); - if (!!onlineRoleId) { // 多地登陆踢下线 - let connect = await getRoleOnlineInfo(onlineRoleId); - if (connect.sid = self.app.getServerId()) { - await kickUser(self.app, onlineRoleId); - } else { - await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, onlineRoleId); - } - } - - let server = await ServerlistModel.findByServerId(serverId); - if(!server) return resResult(STATUS.SERVER_NOT_FOUND); - if(!isWhiteList) { // 白名单 - if(server.openTime > nowSeconds()) { - return resResult(STATUS.SERVER_IS_NOT_OPEN); - } - if(server.maintenance && server.maintenance.isOpen && server.maintenance.startTime <= nowSeconds() && server.maintenance.endTime >= nowSeconds()) { - let isNewUser = await checkIsNewUser(msg.version, server.maintenance.version, user.uid, server.latestServerUniqId); - console.log('#### isNewUser', isNewUser) - if(isNewUser && server.id == server.latestServerUniqId) { - user['isNewUser'] = true; - } else { - return resResult(STATUS.SERVER_MAINTENANCE, { curVersion: msg.version, minVersion: server.maintenance.version }) - } - } - } - - - let serverName = this.app.getServerId(); - await roleLogin(role.roleId, user.userCode, serverName, role.createTime, role.serverId, role.lv, role.topLineupCe); // 保存在线用户 - await this.addSession(user, role, msg.version, session); - - await reportCreateRoleEventToTa(role, ip); - saveLoginAndOutLog(LOG_TYPE.LOGIN, session); - addRoleToSysChannel(role.roleId, self.app.get('serverId'), role.serverId); - addRoleToWorldChannel(role.roleId, self.app.get('serverId'), role.serverId); - reportOneOnline(role.roleId, user.userCode, self.app.get('serverId'), true, user); - - // 任务 - checkTaskInEntry(serverId, role.roleId, self.app.get('serverId'), role); - if (role.hasGuild) { - addRoleToGuildChannel(role.roleId, self.app.get('serverId'), role.guildCode); - } - - let todayZeroPoint = getZeroPoint(); - if(role.needCount) autoCreateServerWhenRoleInit(serverId); - - // console.log('****** entry after', Date.now()); - return resResult(STATUS.SUCCESS, { roleId: role.roleId, todayZeroPoint }); - } - - async getData(msg: { }, session: FrontendSession) { - let ip = session.get('ip'); - let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId, '-_id', true, true); - - // 推送数据 - pushData(role.hasInit, role, session); - - let todayZeroPoint = getZeroPoint(); - return resResult(STATUS.SUCCESS, { todayZeroPoint }); - } - - private getIp(session: FrontendSession) { - return session.remoteAddress.ip.replace('::ffff:', ''); - } - - async addSession(user: UserType, role: RoleType, version: string, session: FrontendSession) { - const self = this; - let ip = this.getIp(session); - - console.log('####### addSession', user['isNewUser']||false) - - await session.abind(role.roleId); - session.set('userid', role.userInfo.uid); - session.set('roleId', role.roleId); - session.set('loginTime', nowSeconds()); - session.set('roleName', role.roleName); - session.set('eventStatus', role.eventStatus); - session.set('blockType', role.blockType); - session.set('sid', self.app.get('serverId')); - session.set('serverId', role.serverId); - session.set('guildCode', role.guildCode); - session.set('ip', ip); - session.set('vipStartTime', role.vipStartTime||0); - session.set('channel', user.channelInfo?.platformAppid||'pc'); - session.set('isNewUser', user['isNewUser']||false); - session.set('version', version); - session.set('quitTime', role.quitTime ? (role.quitTime * 1000) : Date.now()) - session.push('userid', () => { }); - session.push('sid', () => { }); - session.push('roleId', () => { }); - session.push('roleName', () => { }); - session.push('eventStatus', () => { }); - session.push('serverId', () => { }); - session.push('loginTime', () => { }); - session.push('guildCode', () => { }); - session.push('blockType', () => { }); - session.push('ip', () => { }); - session.push('vipStartTime', () => { }); - session.push('channel', () => { }); - session.push('version', () => { }); - session.push('isNewUser', () => { }); - session.push('quitTime', () => { }) - - assignServer(role.roleId, session); - - // console.log('#####', role.serverId, role.guildCode) - // console.log(role.guildCode) - // session.push('rid', function (err) { - // if (err) { - // console.error('set rid for session service failed! error is : %j', err.stack); - // } - // }); - session.on('closed', this.onUserLeave.bind(this)); - } - - - /** - * 每天5点时的刷新数据. - * - * @param {Object} msg request message - * @param {Object} session current session object - */ - async refresh(msg: {}, session: FrontendSession) { - let self = this; - let roleId = session.get('roleId'); - - let role = await RoleModel.findByRoleIdAndSetTime(roleId, '-_id', true); - if (!role) { - return resResult(STATUS.ROLE_NOT_FOUND); - } - - let { serverId } = role; - // 任务 - checkTaskInEntry(serverId, role.roleId, self.app.get('serverId'), role); - // 推送数据 - pushData(role.hasInit, role, session, 'refresh'); - - let todayZeroPoint = getZeroPoint(); - return resResult(STATUS.SUCCESS, { todayZeroPoint }); - } - - async getHiddenData(msg: { }, session: FrontendSession) { - let data = getHiddenData(); - return resResult(STATUS.SUCCESS, data); - } - - async comeBack(msg: { version: string }, session: FrontendSession) { - let roleId = session.get('roleId'); - let ip = session.get('ip'); - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let apJson = await getAp(roleId, ip, role.lv); - return resResult(STATUS.SUCCESS, { apJson }); - } - - /** - * User log out handler - * - * @param {Object} app current application - * @param {Object} session current session object - * - */ - async onUserLeave(session: FrontendSession, reason: string) { - if (!session || !session.uid) { - return; - } - - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let loginTime = session.get('loginTime'); - const guildCode = session.get('guildCode'); - const teamCode: string = session.get('teamCode'); - roleLeave(roleId).then(function (roleInfo) { - if (roleInfo.isOnline) { - savePlayTime(roleInfo.userCode); - } - }); - leaveRaceActivityToRemote(serverId, guildCode, roleId); - reportTAUserSet(TA_USERSET_TYPE.ADD, roleId, { total_play_time: nowSeconds() - loginTime }); - rmRoleFromQueue(roleId, sid); // 删除redis中寻宝的匹配记录 - let channelService = this.app.get('channelService'); - let channel = channelService.getChannel(roleId, true); - channel.leave(roleId, sid); - try { - await leaveSysChannel(roleId, sid, serverId); - await leaveWorldChannel(roleId, sid, serverId); - await leaveGuildChannel(roleId, sid, guildCode); - await leaveGuildAuctionChannel(roleId, sid, guildCode); - await leaveWorldAuctionChannel(roleId, sid, serverId); - await leaveGroupShopChannel(roleId, sid); - await leaveGVGAreaChannel(roleId, sid); - await leaveGVGAreaTeamChannel(roleId, sid); - await leaveGVGCityTeamChannel(roleId, sid); - await leaveCity(true, roleId, serverId, guildCode); - } catch(e) { - console.error(e.stack); - } - RoleModel.updateRoleInfo(roleId, { quitTime: nowSeconds() }); - // if(teamCode) { // 如果有寻宝中的队伍,那么等于战败 - // setComBtlOnUserLeave(roleId, teamCode) - // } - saveLoginAndOutLog(LOG_TYPE.LOGINOUT, session); - leaveServer(session); - } - - - /** - * New client entry chat server. - * - * @param {Object} msg request message - * @param {Object} session current session object - */ - async gmEnter(msg: { token: string }, session: FrontendSession) { - - let self = this; - - let user = await GMUserModel.getGmAccountByToken(msg.token); - if (!user) { - console.log('user token not found'); - return resResult(STATUS.TOKEN_ERR); - } - if(!user.isEnable) { - return resResult(STATUS.GM_NO_AUTHORITY_GET); - } - - // console.log(self.app.get('serverId')); - await session.abind(user.username); - session.set('uid', user.uid); - session.set('roleId', user.username); - session.set('roleName', user.name); - session.set('groupId', user.groupId); - session.set('eventStatus', 0); - session.set('sid', self.app.get('serverId')); - session.push('uid', () => { }); - session.push('sid', () => { }); - session.push('roleId', () => { }); - session.push('roleName', () => { }); - session.push('groupId', () => { }); - session.push('eventStatus', () => { }); - // session.push('rid', function (err) { - // if (err) { - // console.error('set rid for session service failed! error is : %j', err.stack); - // } - // }); - session.on('closed', this.onGmUserLeave.bind(this)); - - sendMessageToUserWithSuc(user.username, 'onGMENTER', {}, self.app.get('serverId')) - - // put user into channel - return resResult(STATUS.SUCCESS, { - env: this.app.get('env') - }); - } - - /** - * User log out handler - * - * @param {Object} app current application - * @param {Object} session current session object - * - */ - async onGmUserLeave(session: FrontendSession, reason: string) { - if (!session || !session.uid) { - return; - } - } - - /** - * ! 仅用于测试 - * @description 测试接口,用于查询和返回 token - * @param {{ tel: string, magicWord: string }} msg 要查询的手机号;需要验证的密码 - * @param {FrontendSession} session - * @returns - * @memberof EntryHandler - */ - async debugQueryToken(msg: { tel: string, magicWord: string }, session: FrontendSession) { - const { tel, magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const token = await UserModel.findTokenByTel(tel); - return resResult(STATUS.SUCCESS, { token }); - } - - /** - * ! 仅用于测试 - * @description 测试接口,用于查询和返回 token - * @param {{ seqId: string, magicWord: string }} msg 要查询的手机号;需要验证的密码 - * @param {FrontendSession} session - * @returns - * @memberof EntryHandler - */ - async debugQueryTokenById(msg: { uid: number, magicWord: string }, session: FrontendSession) { - const { uid, magicWord } = msg; - console.log('debugQueryTokenById msg:', msg); - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const user = await UserModel.findTokenByUid(uid); - console.log('debugQueryTokenById got user:', user); - return resResult(STATUS.SUCCESS, { user }); - } - - async debugGetRole(msg: { magicWord: string, type: string }, session: FrontendSession) { - const { magicWord, type = 'role' } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId, '-_id', true, true); - let module = await getModuleData(type, { role, session }); - return resResult(STATUS.SUCCESS, { role: module }); - } - - async debugQueryTokenByTel(msg: { tel: string, magicWord: string, serverId: number }, session: FrontendSession) { - const { tel, magicWord, serverId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let token = await UserModel.findTokenByTel(tel); - if(!token) { - // 用户注册登录 - token = generateStr(256); - let {user} = await UserModel.createOrUpdate(false, tel, token, 'pc', ' ', pinus.app.get('env'), '', ''); - const roleId = genCode(10); - const code = genCode(6); - const seqId = await Counter.getNewCounter(COUNTER.ROLE) || -1; - - await RoleModel.createRole(user.uid, serverId, { roleId, code, roleName: roleId, seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1) || { sum: 0 }).sum || 0 }, ''); - } - console.log('debugQueryTokenByTel got user:', token); - return resResult(STATUS.SUCCESS, { user: token }); - } - - async debugPushRefToOnlineUsers(msg: { magicWord: string, todayZeroPoint: number }, session: FrontendSession) { - const { magicWord, todayZeroPoint } = msg; - console.log('debugQueryTokenById msg:', msg); - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - await sendMessageToAllWithSuc(PUSH_ROUTE.REFRESH_TIME, { todayZeroPoint }); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { STATUS } from './../../../consts/statusCode'; +import { RoleModel, RoleType } from './../../../db/Role'; +import { UserModel, UserType } from '@db/User'; +import { GMUserModel } from '@db/GMUser'; +import { Application, HandlerService, pinus, } from 'pinus'; +import { FrontendSession } from 'pinus'; +import { HeroModel } from './../../../db/Hero'; +import { compareVersion, genCode, generateStr, resResult } from '@pubUtils/util'; +import { COM_BTL_QUALITY, HERO_SELECT, DEBUG_MAGIC_WORD, REDIS_KEY, TASK_TYPE, ENTERY_ROLE_PICK, COUNTER, DEFAULT_LV, TA_USERSET_TYPE, LOG_TYPE, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE } from '../../../consts'; +// import { loginRefresh } from '../../../services/playerEventService'; +import { nowSeconds, getZeroPoint } from '@pubUtils/timeUtil'; +import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin, getOnlineRoleByUserCode } from '../../../services/redisService'; + +import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGroupShopChannel, leaveGuildAuctionChannel, leaveGuildChannel, leaveGVGAreaChannel, leaveGVGAreaTeamChannel, leaveGVGCityTeamChannel, leaveSysChannel, leaveWorldAuctionChannel, leaveWorldChannel } from '../../../services/chatService'; +import { reportOneOnline, savePlayTime } from '../../../services/authenticateService'; +import { checkTaskInEntry, } from '../../../services/task/taskService'; +import { pushData, kickUser, getModuleData, assignServer, leaveServer } from '../../../services/connectorService'; +// import { setComBtlOnUserLeave } from '../../../services/comBattleService'; +import Counter from '@db/Counter'; +import { getExpByLv } from '@pubUtils/data'; +import { reportCreateRoleEventToTa, reportTAEvent, reportTAUserSet } from '../../../services/sdkService'; +import { saveLoginAndOutLog } from '@pubUtils/logUtil'; +import { sendMessageToAllWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; +import { checkIsNewUser, getIpLocation } from '../../../services/roleService'; +import { leaveRaceActivityToRemote } from '../../../services/guildActivity/guildActivityService'; +import { leaveCity } from '../../../services/gvg/gvgBattleService'; +import { autoCreateServerWhenRoleInit } from '../../../services/serverService'; +import { getHiddenData } from '../../../services/memoryCache/hiddenData'; +import { ServerlistModel } from '@db/Serverlist'; +import { checkWhiteList } from '@pubUtils/sysUtil'; +import { getAp } from '../../../services/actionPointService'; +import { RegionModel } from '@db/Region'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new EntryHandler(app); +} + +export class EntryHandler { + constructor(private app: Application) { + } + + /** + * New client entry chat server. + * + * @param {Object} msg request message + * @param {Object} session current session object + */ + async enter(msg: { token: string, serverId: number, version: string }, session: FrontendSession) { + // console.log('****** entry before', Date.now()); + let self = this; + let serverId = msg.serverId; + let curRegion = await RegionModel.findRegionByEnv(pinus.app.get('env')); + const versionFlag = compareVersion(msg.version, curRegion?.minVersion); + if (!curRegion || versionFlag < 0) { + //版本号太低 + return resResult(STATUS.VERSION_ERR, { version: curRegion.minVersion }); + } + + let user = await UserModel.findUserByToken(msg.token); + if (!user) { + console.log('user token not found'); + return resResult(STATUS.TOKEN_ERR); + } + + let ip = this.getIp(session); + let isWhiteList = await checkWhiteList(pinus.app.get('env'), ip, user.uid); + let ipLocation = await getIpLocation(ip); + let role = await RoleModel.findByUidAndSetTime(user.uid, serverId, ip, ipLocation, null, true); + if (!role) { + return resResult(STATUS.ROLE_NOT_FOUND); + } + + let onlineRoleId = isWhiteList? role.roleId: await getOnlineRoleByUserCode(user.userCode); + if (!!onlineRoleId) { // 多地登陆踢下线 + let connect = await getRoleOnlineInfo(onlineRoleId); + if (connect.sid = self.app.getServerId()) { + await kickUser(self.app, onlineRoleId); + } else { + await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, onlineRoleId); + } + } + + let server = await ServerlistModel.findByServerId(serverId); + if(!server) return resResult(STATUS.SERVER_NOT_FOUND); + if(!isWhiteList) { // 白名单 + if(server.openTime > nowSeconds()) { + return resResult(STATUS.SERVER_IS_NOT_OPEN); + } + if(server.maintenance && server.maintenance.isOpen && server.maintenance.startTime <= nowSeconds() && server.maintenance.endTime >= nowSeconds()) { + let isNewUser = await checkIsNewUser(msg.version, server.maintenance.version, user.uid, server.latestServerUniqId); + console.log('#### isNewUser', isNewUser) + if(isNewUser && server.id == server.latestServerUniqId) { + user['isNewUser'] = true; + } else { + return resResult(STATUS.SERVER_MAINTENANCE, { curVersion: msg.version, minVersion: server.maintenance.version }) + } + } + } + + + let serverName = this.app.getServerId(); + await roleLogin(role.roleId, user.userCode, serverName, role.createTime, role.serverId, role.lv, role.topLineupCe); // 保存在线用户 + await this.addSession(user, role, msg.version, session); + + await reportCreateRoleEventToTa(role, ip); + saveLoginAndOutLog(LOG_TYPE.LOGIN, session); + addRoleToSysChannel(role.roleId, self.app.get('serverId'), role.serverId); + addRoleToWorldChannel(role.roleId, self.app.get('serverId'), role.serverId); + reportOneOnline(role.roleId, user.userCode, self.app.get('serverId'), true, user); + + // 任务 + checkTaskInEntry(serverId, role.roleId, self.app.get('serverId'), role); + if (role.hasGuild) { + addRoleToGuildChannel(role.roleId, self.app.get('serverId'), role.guildCode); + } + + let todayZeroPoint = getZeroPoint(); + if(role.needCount) autoCreateServerWhenRoleInit(serverId); + + // console.log('****** entry after', Date.now()); + return resResult(STATUS.SUCCESS, { roleId: role.roleId, todayZeroPoint }); + } + + async getData(msg: { }, session: FrontendSession) { + let ip = session.get('ip'); + let roleId = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId, '-_id', true, true); + + // 推送数据 + pushData(role.hasInit, role, session); + + let todayZeroPoint = getZeroPoint(); + return resResult(STATUS.SUCCESS, { todayZeroPoint }); + } + + private getIp(session: FrontendSession) { + return session.remoteAddress.ip.replace('::ffff:', ''); + } + + async addSession(user: UserType, role: RoleType, version: string, session: FrontendSession) { + const self = this; + let ip = this.getIp(session); + + console.log('####### addSession', user['isNewUser']||false) + + await session.abind(role.roleId); + session.set('userid', role.userInfo.uid); + session.set('roleId', role.roleId); + session.set('loginTime', nowSeconds()); + session.set('roleName', role.roleName); + session.set('eventStatus', role.eventStatus); + session.set('blockType', role.blockType); + session.set('sid', self.app.get('serverId')); + session.set('serverId', role.serverId); + session.set('guildCode', role.guildCode); + session.set('ip', ip); + session.set('vipStartTime', role.vipStartTime||0); + session.set('channel', user.channelInfo?.platformAppid||'pc'); + session.set('isNewUser', user['isNewUser']||false); + session.set('version', version); + session.set('quitTime', role.quitTime ? (role.quitTime * 1000) : Date.now()) + session.push('userid', () => { }); + session.push('sid', () => { }); + session.push('roleId', () => { }); + session.push('roleName', () => { }); + session.push('eventStatus', () => { }); + session.push('serverId', () => { }); + session.push('loginTime', () => { }); + session.push('guildCode', () => { }); + session.push('blockType', () => { }); + session.push('ip', () => { }); + session.push('vipStartTime', () => { }); + session.push('channel', () => { }); + session.push('version', () => { }); + session.push('isNewUser', () => { }); + session.push('quitTime', () => { }) + + assignServer(role.roleId, session); + + // console.log('#####', role.serverId, role.guildCode) + // console.log(role.guildCode) + // session.push('rid', function (err) { + // if (err) { + // console.error('set rid for session service failed! error is : %j', err.stack); + // } + // }); + session.on('closed', this.onUserLeave.bind(this)); + } + + + /** + * 每天5点时的刷新数据. + * + * @param {Object} msg request message + * @param {Object} session current session object + */ + async refresh(msg: {}, session: FrontendSession) { + let self = this; + let roleId = session.get('roleId'); + + let role = await RoleModel.findByRoleIdAndSetTime(roleId, '-_id', true); + if (!role) { + return resResult(STATUS.ROLE_NOT_FOUND); + } + + let { serverId } = role; + // 任务 + checkTaskInEntry(serverId, role.roleId, self.app.get('serverId'), role); + // 推送数据 + pushData(role.hasInit, role, session, 'refresh'); + + let todayZeroPoint = getZeroPoint(); + return resResult(STATUS.SUCCESS, { todayZeroPoint }); + } + + async getHiddenData(msg: { }, session: FrontendSession) { + let data = getHiddenData(); + return resResult(STATUS.SUCCESS, data); + } + + async comeBack(msg: { version: string }, session: FrontendSession) { + let roleId = session.get('roleId'); + let ip = session.get('ip'); + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let apJson = await getAp(roleId, ip, role.lv); + return resResult(STATUS.SUCCESS, { apJson }); + } + + /** + * User log out handler + * + * @param {Object} app current application + * @param {Object} session current session object + * + */ + async onUserLeave(session: FrontendSession, reason: string) { + if (!session || !session.uid) { + return; + } + + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let loginTime = session.get('loginTime'); + const guildCode = session.get('guildCode'); + const teamCode: string = session.get('teamCode'); + roleLeave(roleId).then(function (roleInfo) { + if (roleInfo.isOnline) { + savePlayTime(roleInfo.userCode); + } + }); + leaveRaceActivityToRemote(serverId, guildCode, roleId); + reportTAUserSet(TA_USERSET_TYPE.ADD, roleId, { total_play_time: nowSeconds() - loginTime }); + rmRoleFromQueue(roleId, sid); // 删除redis中寻宝的匹配记录 + let channelService = this.app.get('channelService'); + let channel = channelService.getChannel(roleId, true); + channel.leave(roleId, sid); + try { + await leaveSysChannel(roleId, sid, serverId); + await leaveWorldChannel(roleId, sid, serverId); + await leaveGuildChannel(roleId, sid, guildCode); + await leaveGuildAuctionChannel(roleId, sid, guildCode); + await leaveWorldAuctionChannel(roleId, sid, serverId); + await leaveGroupShopChannel(roleId, sid); + await leaveGVGAreaChannel(roleId, sid); + await leaveGVGAreaTeamChannel(roleId, sid); + await leaveGVGCityTeamChannel(roleId, sid); + await leaveCity(true, roleId, serverId, guildCode); + } catch(e) { + console.error(e.stack); + } + RoleModel.updateRoleInfo(roleId, { quitTime: nowSeconds() }); + // if(teamCode) { // 如果有寻宝中的队伍,那么等于战败 + // setComBtlOnUserLeave(roleId, teamCode) + // } + saveLoginAndOutLog(LOG_TYPE.LOGINOUT, session); + leaveServer(session); + } + + + /** + * New client entry chat server. + * + * @param {Object} msg request message + * @param {Object} session current session object + */ + async gmEnter(msg: { token: string }, session: FrontendSession) { + + let self = this; + + let user = await GMUserModel.getGmAccountByToken(msg.token); + if (!user) { + console.log('user token not found'); + return resResult(STATUS.TOKEN_ERR); + } + if(!user.isEnable) { + return resResult(STATUS.GM_NO_AUTHORITY_GET); + } + + // console.log(self.app.get('serverId')); + await session.abind(user.username); + session.set('uid', user.uid); + session.set('roleId', user.username); + session.set('roleName', user.name); + session.set('groupId', user.groupId); + session.set('eventStatus', 0); + session.set('sid', self.app.get('serverId')); + session.push('uid', () => { }); + session.push('sid', () => { }); + session.push('roleId', () => { }); + session.push('roleName', () => { }); + session.push('groupId', () => { }); + session.push('eventStatus', () => { }); + // session.push('rid', function (err) { + // if (err) { + // console.error('set rid for session service failed! error is : %j', err.stack); + // } + // }); + session.on('closed', this.onGmUserLeave.bind(this)); + + sendMessageToUserWithSuc(user.username, 'onGMENTER', {}, self.app.get('serverId')) + + // put user into channel + return resResult(STATUS.SUCCESS, { + env: this.app.get('env') + }); + } + + /** + * User log out handler + * + * @param {Object} app current application + * @param {Object} session current session object + * + */ + async onGmUserLeave(session: FrontendSession, reason: string) { + if (!session || !session.uid) { + return; + } + } + + /** + * ! 仅用于测试 + * @description 测试接口,用于查询和返回 token + * @param {{ tel: string, magicWord: string }} msg 要查询的手机号;需要验证的密码 + * @param {FrontendSession} session + * @returns + * @memberof EntryHandler + */ + async debugQueryToken(msg: { tel: string, magicWord: string }, session: FrontendSession) { + const { tel, magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const token = await UserModel.findTokenByTel(tel); + return resResult(STATUS.SUCCESS, { token }); + } + + /** + * ! 仅用于测试 + * @description 测试接口,用于查询和返回 token + * @param {{ seqId: string, magicWord: string }} msg 要查询的手机号;需要验证的密码 + * @param {FrontendSession} session + * @returns + * @memberof EntryHandler + */ + async debugQueryTokenById(msg: { uid: number, magicWord: string }, session: FrontendSession) { + const { uid, magicWord } = msg; + console.log('debugQueryTokenById msg:', msg); + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const user = await UserModel.findTokenByUid(uid); + console.log('debugQueryTokenById got user:', user); + return resResult(STATUS.SUCCESS, { user }); + } + + async debugGetRole(msg: { magicWord: string, type: string }, session: FrontendSession) { + const { magicWord, type = 'role' } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId, '-_id', true, true); + let module = await getModuleData(type, { role, session }); + return resResult(STATUS.SUCCESS, { role: module }); + } + + async debugQueryTokenByTel(msg: { tel: string, magicWord: string, serverId: number }, session: FrontendSession) { + const { tel, magicWord, serverId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let token = await UserModel.findTokenByTel(tel); + if(!token) { + // 用户注册登录 + token = generateStr(256); + let {user} = await UserModel.createOrUpdate(false, tel, token, 'pc', ' ', pinus.app.get('env'), '', ''); + const roleId = genCode(10); + const code = genCode(6); + const seqId = await Counter.getNewCounter(COUNTER.ROLE) || -1; + + await RoleModel.createRole(user.uid, serverId, { roleId, code, roleName: roleId, seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1) || { sum: 0 }).sum || 0 }, ''); + } + console.log('debugQueryTokenByTel got user:', token); + return resResult(STATUS.SUCCESS, { user: token }); + } + + async debugPushRefToOnlineUsers(msg: { magicWord: string, todayZeroPoint: number }, session: FrontendSession) { + const { magicWord, todayZeroPoint } = msg; + console.log('debugQueryTokenById msg:', msg); + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + await sendMessageToAllWithSuc(PUSH_ROUTE.REFRESH_TIME, { todayZeroPoint }); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/connector/remote/connectorRemote.ts b/game-server/app/servers/connector/remote/connectorRemote.ts index de78255e7..d26ee41ae 100644 --- a/game-server/app/servers/connector/remote/connectorRemote.ts +++ b/game-server/app/servers/connector/remote/connectorRemote.ts @@ -1,240 +1,241 @@ -import { Application, HandlerService, } from 'pinus'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { UserGuildType } from '../../../db/UserGuild'; -import { incServerNum, kickUser } from '../../../services/connectorService'; -import { PVPConfigModel, PVPConfigType } from '../../../db/PvpConfig'; -import { setDicAuctionTime, setDicGuildActivity } from '../../../services/guildActivity/guildActivityService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { taflush } from '../../../services/sdkService'; -import { errlogger } from '../../../util/logger'; -import { setWeek } from '../../../pubUtils/timeUtil'; -import { savePvpSeasonMemory } from '../../../services/log/memoryLogService'; -import { setApiIsClose } from '../../../services/chatService'; -import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; -import { setKvToMemory } from '../../../services/pushService'; -import { setServerGroup } from '../../../services/serverService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ConnectorRemote(app); -} - -export class ConnectorRemote { - - constructor(private app: Application) { - this.app = app; - } - - public async remoteLogin(uid: string, message?: any) { - try { - await kickUser(this.app, uid, message); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setOtherUserGuildSession(params: { roleId: string, userGuild: UserGuildType}[]) { - try { - let sessionService = this.app.get('sessionService'); - for(let {roleId, userGuild} of params) { - let sessions = sessionService.getByUid(roleId); - if(!!sessions) { - sessions.forEach(session => { - if(userGuild && userGuild.status == 1) { - sessionService.aimportAll(session.id, { guildCode: userGuild?.guildCode, guildAuth: userGuild?.auth }); - } else { - sessionService.aimportAll(session.id, { guildCode: '', guildAuth: 0 }); - } - }) - } - } - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setOtherUserSession(params: { roleId: string, roleName?: string, blockType?: number, vipStartTime?: number}[]) { - try { - let sessionService = this.app.get('sessionService'); - for(let {roleId, roleName, blockType, vipStartTime} of params) { - let sessions = sessionService.getByUid(roleId); - if(!!sessions) { - sessions.forEach(session => { - if(roleName) sessionService.aimportAll(session.id, { roleName }); - if(blockType) sessionService.aimportAll(session.id, { blockType }); - if(vipStartTime) sessionService.aimportAll(session.id, { vipStartTime }); - }); - } - } - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSettleSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的拍卖行时间 - */ - async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { - try { - setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - async setDay(week: number) { - try { - setWeek(week); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的军团活动开始时间&持续时间 - * @param {number} aid 活动 - * @param {number} startSeconds 从现在开始几秒后开启活动 - * @param {number} endSeconds 从开始之后几秒后结束活动 - */ - public async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { - try { - setDicGuildActivity(now, aid, startSeconds, endSeconds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async incServerNum(sid: string, inc: number) { - try { - incServerNum(sid, inc); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public savePvpSeasonMemory() { - try { - return savePvpSeasonMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - return setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} +import { Application, HandlerService, } from 'pinus'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { UserGuildType } from '@db/UserGuild'; +import { incServerNum, kickUser } from '../../../services/connectorService'; +import { PVPConfigModel, PVPConfigType } from '@db/PvpConfig'; +import { setDicAuctionTime, setDicGuildActivity } from '../../../services/guildActivity/guildActivityService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { taflush } from '../../../services/sdkService'; +import { errlogger } from '../../../util/logger'; +import { setWeek } from '@pubUtils/timeUtil'; +import { savePvpSeasonMemory } from '../../../services/log/memoryLogService'; +import { setApiIsClose } from '../../../services/chatService'; +import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; +import { setKvToMemory } from '../../../services/pushService'; +import { setServerGroup } from '../../../services/serverService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ConnectorRemote(app); +} + +export class ConnectorRemote { + + constructor(private app: Application) { + this.app = app; + } + + public async remoteLogin(uid: string, message?: any) { + try { + await kickUser(this.app, uid, message); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setOtherUserGuildSession(params: { roleId: string, userGuild: UserGuildType}[]) { + try { + let sessionService = this.app.get('sessionService'); + for(let {roleId, userGuild} of params) { + let sessions = sessionService.getByUid(roleId); + if(!!sessions) { + sessions.forEach(session => { + if(userGuild && userGuild.status == 1) { + sessionService.aimportAll(session.id, { guildCode: userGuild?.guildCode, guildAuth: userGuild?.auth }); + } else { + sessionService.aimportAll(session.id, { guildCode: '', guildAuth: 0 }); + } + }) + } + } + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setOtherUserSession(params: { roleId: string, roleName?: string, blockType?: number, vipStartTime?: number}[]) { + try { + let sessionService = this.app.get('sessionService'); + for(let {roleId, roleName, blockType, vipStartTime} of params) { + let sessions = sessionService.getByUid(roleId); + if(!!sessions) { + sessions.forEach(session => { + if(roleName) sessionService.aimportAll(session.id, { roleName }); + if(blockType) sessionService.aimportAll(session.id, { blockType }); + if(vipStartTime) sessionService.aimportAll(session.id, { vipStartTime }); + }); + } + } + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSettleSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的拍卖行时间 + */ + async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { + try { + setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + async setDay(week: number) { + try { + setWeek(week); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的军团活动开始时间&持续时间 + * @param {number} aid 活动 + * @param {number} startSeconds 从现在开始几秒后开启活动 + * @param {number} endSeconds 从开始之后几秒后结束活动 + */ + public async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { + try { + setDicGuildActivity(now, aid, startSeconds, endSeconds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async incServerNum(sid: string, inc: number) { + try { + incServerNum(sid, inc); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public savePvpSeasonMemory() { + try { + return savePvpSeasonMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + return setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/gate/handler/gateHandler.ts b/game-server/app/servers/gate/handler/gateHandler.ts index 088073bee..7d86854d2 100644 --- a/game-server/app/servers/gate/handler/gateHandler.ts +++ b/game-server/app/servers/gate/handler/gateHandler.ts @@ -1,38 +1,39 @@ -import { STATUS } from './../../../consts/statusCode'; -import { dispatch } from '../../../pubUtils/dispatcher'; -import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { redisClient } from '../../../services/redisService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GateHandler(app); -} - -export class GateHandler { - constructor(private app: Application) { - } - - /** - * Gate handler that dispatch user to connectors. - * - * @param {Object} msg message from client - * @param {Object} session - * - */ - async queryEntry(msg: { userCode: string }, session: BackendSession) { - let { userCode } = msg; - if (!userCode) { - return resResult(STATUS.WRONG_PARMS); - } - // get all connectors - let connectors = this.app.getServersByType('connector'); - // console.log(connectors); - if (!connectors || connectors.length === 0) { - return resResult(STATUS.CONNECTOR_ERR); - } - // select connector - let res = await dispatch(redisClient(), userCode, connectors, 'connector'); - return resResult(STATUS.SUCCESS, { host: res.clientHost, port: res.clientPort }); - } -} \ No newline at end of file +import { STATUS } from './../../../consts/statusCode'; +import { dispatch } from '@pubUtils/dispatcher'; +import { Application, BackendSession, HandlerService, pinus, } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { redisClient } from '../../../services/redisService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GateHandler(app); +} + +export class GateHandler { + constructor(private app: Application) { + } + + /** + * Gate handler that dispatch user to connectors. + * + * @param {Object} msg message from client + * @param {Object} session + * + */ + async queryEntry(msg: { userCode: string }, session: BackendSession) { + let { userCode } = msg; + if (!userCode) { + return resResult(STATUS.WRONG_PARMS); + } + // get all connectors + let connectors = this.app.getServersByType('connector'); + // console.log(connectors); + if (!connectors || connectors.length === 0) { + return resResult(STATUS.CONNECTOR_ERR); + } + // select connector + let res = await dispatch(redisClient(), userCode, connectors, 'connector'); + return resResult(STATUS.SUCCESS, { host: res.clientHost, port: res.clientPort }); + } +} + diff --git a/game-server/app/servers/gate/remote/gateRemote.ts b/game-server/app/servers/gate/remote/gateRemote.ts index 04999cc11..433f72e1e 100644 --- a/game-server/app/servers/gate/remote/gateRemote.ts +++ b/game-server/app/servers/gate/remote/gateRemote.ts @@ -1,16 +1,16 @@ -import { Application, ChannelService, FrontendSession, RemoterClass, HandlerService, } from 'pinus'; -export default function (app: Application) { - new HandlerService(app, {}); - return new GateRemote(app); -} - -export class GateRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - -} \ No newline at end of file +import { Application, ChannelService, FrontendSession, RemoterClass, HandlerService, } from 'pinus'; +export default function (app: Application) { + new HandlerService(app, {}); + return new GateRemote(app); +} + +export class GateRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + +} diff --git a/game-server/app/servers/gm/filter/tokenFilter.ts b/game-server/app/servers/gm/filter/tokenFilter.ts index 5255958d7..c4ea7ecc2 100644 --- a/game-server/app/servers/gm/filter/tokenFilter.ts +++ b/game-server/app/servers/gm/filter/tokenFilter.ts @@ -1,48 +1,49 @@ -import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback } from "pinus"; -import { GM_API_TYPE, STATUS } from "../../../consts"; -import { GMGroupModel } from "../../../db/GMGroup"; -import { GMRecordModel } from "../../../db/GMRecord"; -import { gameData } from "../../../pubUtils/data"; -import { resResult } from "../../../pubUtils/util"; - -export function tokenFilter(app: Application) { - return new Filter(app); -} - -var Filter = function(this: any, app: Application) { - this.app = app; -}; - -Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { - const uid = session.get('uid'); - const groupId = session.get('groupId'); - - let route = routeRecord.route; - // console.log('********uid', uid, route); - let dicApi = gameData.apiByUrl.get(route); - if(!dicApi) { - return next(new Error(), resResult(STATUS.GM_MISS_API)); - } - let group = await GMGroupModel.getGroupById(groupId); - - if(!group) { - return next(new Error(), resResult(STATUS.GM_NO_AUTHORITY_GET)); - } - - if(!group.apis.includes(0) && !group.apis.includes(dicApi.id)) { - return next(new Error(), resResult(STATUS.GM_NO_AUTHORITY_GET)); - } - - next(null); -}; - -Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { - const uid = session.get('uid'); - let route = routeRecord.route; - - let dicApi = gameData.apiByUrl.get(route); - if(dicApi && dicApi.type != GM_API_TYPE.find) { - GMRecordModel.createRecord(uid, this.app.get('env'), route, JSON.stringify(msg||{}), JSON.stringify(resp||{})); - } - next(err); -}; \ No newline at end of file +import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback } from "pinus"; +import { GM_API_TYPE, STATUS } from "@consts"; +import { GMGroupModel } from "@db/GMGroup"; +import { GMRecordModel } from "@db/GMRecord"; +import { gameData } from "@pubUtils/data"; +import { resResult } from "@pubUtils/util"; + +export function tokenFilter(app: Application) { + return new Filter(app); +} + +var Filter = function(this: any, app: Application) { + this.app = app; +}; + +Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { + const uid = session.get('uid'); + const groupId = session.get('groupId'); + + let route = routeRecord.route; + // console.log('********uid', uid, route); + let dicApi = gameData.apiByUrl.get(route); + if(!dicApi) { + return next(new Error(), resResult(STATUS.GM_MISS_API)); + } + let group = await GMGroupModel.getGroupById(groupId); + + if(!group) { + return next(new Error(), resResult(STATUS.GM_NO_AUTHORITY_GET)); + } + + if(!group.apis.includes(0) && !group.apis.includes(dicApi.id)) { + return next(new Error(), resResult(STATUS.GM_NO_AUTHORITY_GET)); + } + + next(null); +}; + +Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { + const uid = session.get('uid'); + let route = routeRecord.route; + + let dicApi = gameData.apiByUrl.get(route); + if(dicApi && dicApi.type != GM_API_TYPE.find) { + GMRecordModel.createRecord(uid, this.app.get('env'), route, JSON.stringify(msg||{}), JSON.stringify(resp||{})); + } + next(err); +}; + diff --git a/game-server/app/servers/gm/handler/gmHandler.ts b/game-server/app/servers/gm/handler/gmHandler.ts index 329fd2775..66fc92967 100644 --- a/game-server/app/servers/gm/handler/gmHandler.ts +++ b/game-server/app/servers/gm/handler/gmHandler.ts @@ -1,357 +1,358 @@ -import { Application, BackendSession, pinus } from 'pinus'; -import { getRandSingleEelm, isTimestamp, resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { GMMailModel, GMMailType } from '../../../db/GMMail'; -import { ACTIVITY_TYPE, GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, SURVEY_SELECT } from '../../../consts'; -import { ActivityModel } from '../../../db/Activity'; -import { ActivityGroupModel } from '../../../db/ActivityGroup'; -import { ActivityGroupTypeModel } from '../../../db/ActivityGroupType'; -import { getPastTime, getTimeFunM, nowSeconds } from '../../../pubUtils/timeUtil'; -import moment = require('moment'); -import { sendUngotDividend } from '../../../services/auctionService'; -import { taflush } from '../../../services/sdkService'; -import { ActivityInRemote } from '../../../domain/activityField/activityField'; -import { pushCurrentTime } from '../../../services/auctionService'; -import { SurveyModel, SurveyUpdate } from '../../../db/Survery'; -import { compaireMailGoods, getSurvey } from '../../../services/gmService'; -import { sendMessageToAllWithSuc } from '../../../services/pushService'; -import { sendMailByContent, sendMailsByGmMail } from '../../../services/mailService'; -import { saveMemory } from '../../../services/log/memoryLogService'; -import { getGVGConfigFromRemote } from '../../../services/gvg/gvgService'; -import { ServerGroupModel } from '../../../db/ServerGroup'; -import { isNumber } from 'underscore'; -import { group } from 'console'; -import { GVGConfigModel } from '../../../db/GVGConfig'; -import { ServerlistModel } from '../../../db/Serverlist'; -import { getPvpTimeFromRemote } from '../../../services/pvpService'; - -let timer: NodeJS.Timer; -export default function (app: Application) { - return new GmHandler(app); -} - -export class GmHandler { - constructor(private app: Application) { - } - - async sendSingleMail(msg: { id: string, isPass: boolean }, session: BackendSession) { - const uid: number = session.get('uid') - let { id, isPass } = msg; - let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, true); - if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); - return await this.sendMail(gmmail, isPass, uid); - } - - async sendSingleMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { - const uid: number = session.get('uid') - let { id, isPass } = msg; - let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, false); - if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); - return await this.sendMail(gmmail, isPass, uid); - } - - async sendServerMail(msg: { id: string, isPass: boolean }, session: BackendSession) { - const uid: number = session.get('uid') - let { id, isPass } = msg; - let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, true); - if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); - return await this.sendMail(gmmail, isPass, uid); - } - - async sendServerMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { - const uid: number = session.get('uid') - let { id, isPass } = msg; - let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, false); - if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); - return await this.sendMail(gmmail, isPass, uid); - } - - //对接gm后台,下发邮件 - async sendMail(gmmail: GMMailType, isPass: boolean, uid: number) { - let id = gmmail._id; - let { receivers, mailType, status, hasGoods, goods } = gmmail; - if(status != GM_MAIL_STATUS.CREATE) { - return resResult(STATUS.GM_MAIL_HAS_SENT); - } - - if(isPass) { - let gmmailArr: GMMailType[] = []; - if(mailType == GM_MAIL_TYPE.SINGLE && hasGoods && (!goods || goods.length == 0)) { - for(let receiver of receivers) { - let index = gmmailArr.findIndex(gmmail => compaireMailGoods(gmmail, receiver)); - if(index == -1) { - gmmailArr.push({...gmmail, receivers: [receiver], goods: receiver.rewards, hasGoods: receiver?receiver.rewards.length > 0: false }); - } else { - gmmailArr[index].receivers.push(receiver); - } - } - } else { - gmmailArr.push(gmmail); - } - - - await sendMailsByGmMail(gmmailArr); - } - await GMMailModel.updateMailById(id, { status: isPass? GM_MAIL_STATUS.PASS: GM_MAIL_STATUS.NOT_PASS, viewAt: new Date(), viewBy: uid }, uid); - return resResult(STATUS.SUCCESS); - } - - async reloadResource(msg: {}, session: BackendSession) { - try { - let activityServers = this.app.getServersByType('activity'); - for (let { id } of activityServers) { - await this.app.rpc.activity.activityRemote.reloadResources.toServer(id); - } - let battleServers = this.app.getServersByType('battle'); - for (let { id } of battleServers) { - await this.app.rpc.battle.battleRemote.reloadResources.toServer(id); - } - let comBattleServers = this.app.getServersByType('comBattle'); - for (let { id } of comBattleServers) { - await this.app.rpc.comBattle.comBattleRemote.reloadResources.toServer(id); - } - let chatServers = this.app.getServersByType('chat'); - for (let { id } of chatServers) { - await this.app.rpc.chat.chatRemote.reloadResources.toServer(id); - } - let connectServers = this.app.getServersByType('connector'); - for (let { id } of connectServers) { - await this.app.rpc.connector.connectorRemote.reloadResources.toServer(id); - } - let guildServers = this.app.getServersByType('guild'); - for (let { id } of guildServers) { - await this.app.rpc.guild.guildRemote.reloadResources.toServer(id); - } - let roleServers = this.app.getServersByType('role'); - for (let { id } of roleServers) { - await this.app.rpc.role.roleRemote.reloadResources.toServer(id); - } - let systimerServers = this.app.getServersByType('systimer'); - for (let { id } of systimerServers) { - await this.app.rpc.systimer.systimerRemote.reloadResources.toServer(id); - } - let orderServers = this.app.getServersByType('order'); - for (let { id } of orderServers) { - await this.app.rpc.order.orderRemote.reloadResources.toServer(id); - } - return resResult(STATUS.SUCCESS, { - isOK: true - }); - } catch (e) { - return resResult(STATUS.SUCCESS, { - isOK: false, - err: e.stack - }); - } - } - - async updateActivity(msg: { aids: number[] }, session: BackendSession) { - let { aids }= msg; - - let activities = await ActivityModel.findActivityByIds(aids); - let activityServers = pinus.app.getServersByType('activity'); - for(let server of activityServers) { - pinus.app.rpc.activity.activityRemote.updateActivities.toServer(server.id, activities.map(activity => new ActivityInRemote(activity))); - } - let timeLimitRanks = activities.filter(cur => cur.type == ACTIVITY_TYPE.TIME_LIMIT_RANK); - if(timeLimitRanks.length > 0) { - pinus.app.rpc.systimer.systimerRemote.updateTimeLimitRank.broadcast(timeLimitRanks); - } - let groupShops = activities.filter(cur => cur.type == ACTIVITY_TYPE.GROUP_SHOP); - if(groupShops.length > 0) { - pinus.app.rpc.systimer.systimerRemote.initSumSchedule.broadcast(); - } - let signIns = activities.filter(cur => cur.type == ACTIVITY_TYPE.COMMON_SIGN_IN); - if(signIns.length > 0) { - pinus.app.rpc.systimer.systimerRemote.initVipSignInMailSchedule.broadcast(); - } - - return resResult(STATUS.SUCCESS, { - activity: activities - }); - } - - async deleteActivity(msg: { activityId: number}, session: BackendSession) { - const { activityId } = msg; - let activityServers = pinus.app.getServersByType('activity'); - for(let server of activityServers) { - pinus.app.rpc.activity.activityRemote.deleteActivities.toServer(server.id, [activityId]); - } - - return resResult(STATUS.SUCCESS); - } - - async updateActivityGroup(msg: { groupId: number, serverIds: number[], activityIds: number[] }, session: BackendSession) { - const uid = session.get('uid'); - let { groupId, serverIds, activityIds } = msg; - pinus.app.rpc.activity.activityRemote.saveActivitiesToGroup.broadcast(groupId, activityIds); - pinus.app.rpc.activity.activityRemote.saveGroupToServer.broadcast([groupId], serverIds); - return resResult(STATUS.SUCCESS); - } - - /** - * 开启军团活动到拍卖行debug - * @param msg - * @param session - */ - async setGuildActivityDebug(msg: { aid: number, day: number, startActivity: number, endActivity: number, startGuildAuction: number, endGuildAuction: number, startWorldAuction: number, endWorldAuction: number, startNextDay: number }, session: BackendSession) { - let { aid, day, startActivity = 0, endActivity = 0, startGuildAuction = 0, endGuildAuction = 0, startWorldAuction = 0, endWorldAuction = 0, startNextDay = 0 } = msg; - if(timer) { - clearTimeout(timer); - } - const uid = session.get('uid'); - if(aid == undefined || day == undefined ) { - return resResult(STATUS.WRONG_PARMS); - } - if(aid == 0) { - day = new Date().getDay(); - } - - // 设置字典 - let now = new Date(); - - let startTimes = await pinus.app.rpc.guild.guildActivityRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); - await pinus.app.rpc.systimer.systimerRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); - await pinus.app.rpc.connector.connectorRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); - await pinus.app.rpc.guild.guildActivityRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); - await pinus.app.rpc.connector.connectorRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); - await pinus.app.rpc.systimer.systimerRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); - await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(day); - await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(day); - await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(day); - await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(aid); - await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); - - // 开启定时器 - await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast(); - // 向客户端发送时间 - let time = getTimeFunM().getTimeWithWeek(day, 20, 0, 0) - startActivity * 1000; - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); - await pushCurrentTime(time); - timer = setTimeout(async () => { - let time = getTimeFunM().getAfterDayWithHour(0); - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); - await pushCurrentTime(time); - let guilds = pinus.app.getServersByType('guild'); - let guild = getRandSingleEelm(guilds); - await pinus.app.rpc.guild.guildActivityRemote.sendUngotDividend.toServer(guild.id); - }, startActivity * 1000 + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000) - return resResult(STATUS.SUCCESS, { - startActivity: startTimes[0], - endActivity: startTimes[0] + endActivity * 1000, - startGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000, - endGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000, - startWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000, - endWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000, - startNextDay: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000, - }); - } - - async cancelGuildActivityDebug(msg: { }, session: BackendSession) { - // 设置字典 - let now = new Date(); - if(timer) { - clearTimeout(timer); - } - await pinus.app.rpc.guild.guildRemote.reloadResources.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.reloadResources.broadcast(); - await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(null); - await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(null); - await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(null); - - // 开启定时器 - await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast(); - await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); - - // 向客户端发送时间 - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(now.getTime()); - await pushCurrentTime(now.getTime()); - return resResult(STATUS.SUCCESS); - } - - async taflus() { - taflush(); - pinus.app.rpc.activity.activityRemote.taflush.broadcast(); - pinus.app.rpc.battle.battleRemote.taflush.broadcast(); - pinus.app.rpc.chat.chatRemote.taflush.broadcast(); - pinus.app.rpc.connector.connectorRemote.taflush.broadcast(); - pinus.app.rpc.guild.guildRemote.taflush.broadcast(); - pinus.app.rpc.order.orderRemote.taflush.broadcast(); - pinus.app.rpc.role.roleRemote.taflush.broadcast(); - pinus.app.rpc.systimer.systimerRemote.taflush.broadcast(); - return resResult(STATUS.SUCCESS); - } - - async updateSurvey(msg: { code: string, surveyId: string, beginTim: number, endTime: number, isEnable: boolean, surveyLink: string, surveyName: string, roleIndex: number, goods: string, mailContent: string }, session: BackendSession) { - let update: SurveyUpdate = msg; - if(msg.goods) { - let reward = JSON.parse(msg.goods); - update.reward = reward; - } - let origin = await SurveyModel.findByCode(msg.code); - let result = await SurveyModel.updateSurvey(msg.code, update, SURVEY_SELECT.FIND); - if(!result) return resResult(STATUS.WRONG_PARMS); - - if(origin && origin.isEnable != result.isEnable) { - await sendMessageToAllWithSuc(PUSH_ROUTE.UPDATE_SURVEY, { survey: result }); - } - - return resResult(STATUS.SUCCESS); - } - - async deleteSurvey(msg: { code: string }, session: BackendSession) { - let { code } = msg; - - await SurveyModel.deleteSurvey(code); - await sendMessageToAllWithSuc(PUSH_ROUTE.DELETE_SURVEY, { code }); - - return resResult(STATUS.SUCCESS); - } - - async saveMemoryLog(msg: { memoryLogType: MEMORY_LOG_TYPE }, session: BackendSession) { - const { memoryLogType } = msg; - await saveMemory(memoryLogType); - return resResult(STATUS.SUCCESS); - } - - async updateGVGServerGroup(msg: { serverId: number[], groupId: number }, session: BackendSession) { - const { serverId: serverIds, groupId } = msg; - if(!isNumber(groupId)) return resResult(STATUS.WRONG_PARMS); - for(let serverId of serverIds) { - if(!isNumber(serverId)) return resResult(STATUS.WRONG_PARMS); - } - let { scheduleTime } = await getGVGConfigFromRemote(); - let { seasonNum, seasonEndTime } = await getPvpTimeFromRemote(); - for(let serverId of serverIds) { - await ServerGroupModel.updateByServerId(serverId, groupId, scheduleTime, seasonNum == 0? getPastTime(): seasonEndTime); - } - - try { - await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); - await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); - await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); - await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); - await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); - } catch(e) { - console.log('remote未初始完'); - } - return resResult(STATUS.SUCCESS); - } - - async updateGVGConfig(msg: { configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number }, session: BackendSession) { - const { configId, teamTime, prepareTime, battleTime, scheduleTime } = msg; - if(!isNumber(configId) || !isTimestamp(teamTime) || !isTimestamp(prepareTime) || !isTimestamp(battleTime) || !isTimestamp(scheduleTime)) { - return resResult(STATUS.WRONG_PARMS); - } - if(teamTime > prepareTime || prepareTime > battleTime || battleTime > scheduleTime) { - return resResult(STATUS.GM_GVG_TIME_ERR); - } - const config = await GVGConfigModel.updateConfig(configId, teamTime, prepareTime, battleTime, scheduleTime); - await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); - await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast(); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, pinus } from 'pinus'; +import { getRandSingleEelm, isTimestamp, resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { GMMailModel, GMMailType } from '@db/GMMail'; +import { ACTIVITY_TYPE, GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, SURVEY_SELECT } from '../../../consts'; +import { ActivityModel } from '@db/Activity'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { ActivityGroupTypeModel } from '@db/ActivityGroupType'; +import { getPastTime, getTimeFunM, nowSeconds } from '@pubUtils/timeUtil'; +import moment = require('moment'); +import { sendUngotDividend } from '../../../services/auctionService'; +import { taflush } from '../../../services/sdkService'; +import { ActivityInRemote } from '@domain/activityField/activityField'; +import { pushCurrentTime } from '../../../services/auctionService'; +import { SurveyModel, SurveyUpdate } from '@db/Survery'; +import { compaireMailGoods, getSurvey } from '../../../services/gmService'; +import { sendMessageToAllWithSuc } from '../../../services/pushService'; +import { sendMailByContent, sendMailsByGmMail } from '../../../services/mailService'; +import { saveMemory } from '../../../services/log/memoryLogService'; +import { getGVGConfigFromRemote } from '../../../services/gvg/gvgService'; +import { ServerGroupModel } from '@db/ServerGroup'; +import { isNumber } from 'underscore'; +import { group } from 'console'; +import { GVGConfigModel } from '@db/GVGConfig'; +import { ServerlistModel } from '@db/Serverlist'; +import { getPvpTimeFromRemote } from '../../../services/pvpService'; + +let timer: NodeJS.Timer; +export default function (app: Application) { + return new GmHandler(app); +} + +export class GmHandler { + constructor(private app: Application) { + } + + async sendSingleMail(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, true); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendSingleMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, false); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendServerMail(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, true); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendServerMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, false); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + //对接gm后台,下发邮件 + async sendMail(gmmail: GMMailType, isPass: boolean, uid: number) { + let id = gmmail._id; + let { receivers, mailType, status, hasGoods, goods } = gmmail; + if(status != GM_MAIL_STATUS.CREATE) { + return resResult(STATUS.GM_MAIL_HAS_SENT); + } + + if(isPass) { + let gmmailArr: GMMailType[] = []; + if(mailType == GM_MAIL_TYPE.SINGLE && hasGoods && (!goods || goods.length == 0)) { + for(let receiver of receivers) { + let index = gmmailArr.findIndex(gmmail => compaireMailGoods(gmmail, receiver)); + if(index == -1) { + gmmailArr.push({...gmmail, receivers: [receiver], goods: receiver.rewards, hasGoods: receiver?receiver.rewards.length > 0: false }); + } else { + gmmailArr[index].receivers.push(receiver); + } + } + } else { + gmmailArr.push(gmmail); + } + + + await sendMailsByGmMail(gmmailArr); + } + await GMMailModel.updateMailById(id, { status: isPass? GM_MAIL_STATUS.PASS: GM_MAIL_STATUS.NOT_PASS, viewAt: new Date(), viewBy: uid }, uid); + return resResult(STATUS.SUCCESS); + } + + async reloadResource(msg: {}, session: BackendSession) { + try { + let activityServers = this.app.getServersByType('activity'); + for (let { id } of activityServers) { + await this.app.rpc.activity.activityRemote.reloadResources.toServer(id); + } + let battleServers = this.app.getServersByType('battle'); + for (let { id } of battleServers) { + await this.app.rpc.battle.battleRemote.reloadResources.toServer(id); + } + let comBattleServers = this.app.getServersByType('comBattle'); + for (let { id } of comBattleServers) { + await this.app.rpc.comBattle.comBattleRemote.reloadResources.toServer(id); + } + let chatServers = this.app.getServersByType('chat'); + for (let { id } of chatServers) { + await this.app.rpc.chat.chatRemote.reloadResources.toServer(id); + } + let connectServers = this.app.getServersByType('connector'); + for (let { id } of connectServers) { + await this.app.rpc.connector.connectorRemote.reloadResources.toServer(id); + } + let guildServers = this.app.getServersByType('guild'); + for (let { id } of guildServers) { + await this.app.rpc.guild.guildRemote.reloadResources.toServer(id); + } + let roleServers = this.app.getServersByType('role'); + for (let { id } of roleServers) { + await this.app.rpc.role.roleRemote.reloadResources.toServer(id); + } + let systimerServers = this.app.getServersByType('systimer'); + for (let { id } of systimerServers) { + await this.app.rpc.systimer.systimerRemote.reloadResources.toServer(id); + } + let orderServers = this.app.getServersByType('order'); + for (let { id } of orderServers) { + await this.app.rpc.order.orderRemote.reloadResources.toServer(id); + } + return resResult(STATUS.SUCCESS, { + isOK: true + }); + } catch (e) { + return resResult(STATUS.SUCCESS, { + isOK: false, + err: e.stack + }); + } + } + + async updateActivity(msg: { aids: number[] }, session: BackendSession) { + let { aids }= msg; + + let activities = await ActivityModel.findActivityByIds(aids); + let activityServers = pinus.app.getServersByType('activity'); + for(let server of activityServers) { + pinus.app.rpc.activity.activityRemote.updateActivities.toServer(server.id, activities.map(activity => new ActivityInRemote(activity))); + } + let timeLimitRanks = activities.filter(cur => cur.type == ACTIVITY_TYPE.TIME_LIMIT_RANK); + if(timeLimitRanks.length > 0) { + pinus.app.rpc.systimer.systimerRemote.updateTimeLimitRank.broadcast(timeLimitRanks); + } + let groupShops = activities.filter(cur => cur.type == ACTIVITY_TYPE.GROUP_SHOP); + if(groupShops.length > 0) { + pinus.app.rpc.systimer.systimerRemote.initSumSchedule.broadcast(); + } + let signIns = activities.filter(cur => cur.type == ACTIVITY_TYPE.COMMON_SIGN_IN); + if(signIns.length > 0) { + pinus.app.rpc.systimer.systimerRemote.initVipSignInMailSchedule.broadcast(); + } + + return resResult(STATUS.SUCCESS, { + activity: activities + }); + } + + async deleteActivity(msg: { activityId: number}, session: BackendSession) { + const { activityId } = msg; + let activityServers = pinus.app.getServersByType('activity'); + for(let server of activityServers) { + pinus.app.rpc.activity.activityRemote.deleteActivities.toServer(server.id, [activityId]); + } + + return resResult(STATUS.SUCCESS); + } + + async updateActivityGroup(msg: { groupId: number, serverIds: number[], activityIds: number[] }, session: BackendSession) { + const uid = session.get('uid'); + let { groupId, serverIds, activityIds } = msg; + pinus.app.rpc.activity.activityRemote.saveActivitiesToGroup.broadcast(groupId, activityIds); + pinus.app.rpc.activity.activityRemote.saveGroupToServer.broadcast([groupId], serverIds); + return resResult(STATUS.SUCCESS); + } + + /** + * 开启军团活动到拍卖行debug + * @param msg + * @param session + */ + async setGuildActivityDebug(msg: { aid: number, day: number, startActivity: number, endActivity: number, startGuildAuction: number, endGuildAuction: number, startWorldAuction: number, endWorldAuction: number, startNextDay: number }, session: BackendSession) { + let { aid, day, startActivity = 0, endActivity = 0, startGuildAuction = 0, endGuildAuction = 0, startWorldAuction = 0, endWorldAuction = 0, startNextDay = 0 } = msg; + if(timer) { + clearTimeout(timer); + } + const uid = session.get('uid'); + if(aid == undefined || day == undefined ) { + return resResult(STATUS.WRONG_PARMS); + } + if(aid == 0) { + day = new Date().getDay(); + } + + // 设置字典 + let now = new Date(); + + let startTimes = await pinus.app.rpc.guild.guildActivityRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); + await pinus.app.rpc.systimer.systimerRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); + await pinus.app.rpc.connector.connectorRemote.setDicGuildActivity.broadcast(now.getTime(), aid, startActivity, endActivity); + await pinus.app.rpc.guild.guildActivityRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); + await pinus.app.rpc.connector.connectorRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); + await pinus.app.rpc.systimer.systimerRemote.setDicAuctionTime.broadcast(startTimes[0], endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction); + await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(day); + await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(day); + await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(day); + await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(aid); + await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); + + // 开启定时器 + await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast(); + // 向客户端发送时间 + let time = getTimeFunM().getTimeWithWeek(day, 20, 0, 0) - startActivity * 1000; + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); + await pushCurrentTime(time); + timer = setTimeout(async () => { + let time = getTimeFunM().getAfterDayWithHour(0); + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); + await pushCurrentTime(time); + let guilds = pinus.app.getServersByType('guild'); + let guild = getRandSingleEelm(guilds); + await pinus.app.rpc.guild.guildActivityRemote.sendUngotDividend.toServer(guild.id); + }, startActivity * 1000 + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000) + return resResult(STATUS.SUCCESS, { + startActivity: startTimes[0], + endActivity: startTimes[0] + endActivity * 1000, + startGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000, + endGuildAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000, + startWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000, + endWorldAuction: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000, + startNextDay: startTimes[0] + endActivity * 1000 + startGuildAuction * 1000 + endGuildAuction * 1000 + startWorldAuction * 1000 + endWorldAuction * 1000 + startNextDay * 1000, + }); + } + + async cancelGuildActivityDebug(msg: { }, session: BackendSession) { + // 设置字典 + let now = new Date(); + if(timer) { + clearTimeout(timer); + } + await pinus.app.rpc.guild.guildRemote.reloadResources.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.reloadResources.broadcast(); + await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(null); + await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(null); + await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(null); + + // 开启定时器 + await pinus.app.rpc.systimer.systimerRemote.setAuctionSchedule.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setGuildActivitySchedule.broadcast(); + await pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); + + // 向客户端发送时间 + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(now.getTime()); + await pushCurrentTime(now.getTime()); + return resResult(STATUS.SUCCESS); + } + + async taflus() { + taflush(); + pinus.app.rpc.activity.activityRemote.taflush.broadcast(); + pinus.app.rpc.battle.battleRemote.taflush.broadcast(); + pinus.app.rpc.chat.chatRemote.taflush.broadcast(); + pinus.app.rpc.connector.connectorRemote.taflush.broadcast(); + pinus.app.rpc.guild.guildRemote.taflush.broadcast(); + pinus.app.rpc.order.orderRemote.taflush.broadcast(); + pinus.app.rpc.role.roleRemote.taflush.broadcast(); + pinus.app.rpc.systimer.systimerRemote.taflush.broadcast(); + return resResult(STATUS.SUCCESS); + } + + async updateSurvey(msg: { code: string, surveyId: string, beginTim: number, endTime: number, isEnable: boolean, surveyLink: string, surveyName: string, roleIndex: number, goods: string, mailContent: string }, session: BackendSession) { + let update: SurveyUpdate = msg; + if(msg.goods) { + let reward = JSON.parse(msg.goods); + update.reward = reward; + } + let origin = await SurveyModel.findByCode(msg.code); + let result = await SurveyModel.updateSurvey(msg.code, update, SURVEY_SELECT.FIND); + if(!result) return resResult(STATUS.WRONG_PARMS); + + if(origin && origin.isEnable != result.isEnable) { + await sendMessageToAllWithSuc(PUSH_ROUTE.UPDATE_SURVEY, { survey: result }); + } + + return resResult(STATUS.SUCCESS); + } + + async deleteSurvey(msg: { code: string }, session: BackendSession) { + let { code } = msg; + + await SurveyModel.deleteSurvey(code); + await sendMessageToAllWithSuc(PUSH_ROUTE.DELETE_SURVEY, { code }); + + return resResult(STATUS.SUCCESS); + } + + async saveMemoryLog(msg: { memoryLogType: MEMORY_LOG_TYPE }, session: BackendSession) { + const { memoryLogType } = msg; + await saveMemory(memoryLogType); + return resResult(STATUS.SUCCESS); + } + + async updateGVGServerGroup(msg: { serverId: number[], groupId: number }, session: BackendSession) { + const { serverId: serverIds, groupId } = msg; + if(!isNumber(groupId)) return resResult(STATUS.WRONG_PARMS); + for(let serverId of serverIds) { + if(!isNumber(serverId)) return resResult(STATUS.WRONG_PARMS); + } + let { scheduleTime } = await getGVGConfigFromRemote(); + let { seasonNum, seasonEndTime } = await getPvpTimeFromRemote(); + for(let serverId of serverIds) { + await ServerGroupModel.updateByServerId(serverId, groupId, scheduleTime, seasonNum == 0? getPastTime(): seasonEndTime); + } + + try { + await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); + await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); + await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); + await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); + await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); + } catch(e) { + console.log('remote未初始完'); + } + return resResult(STATUS.SUCCESS); + } + + async updateGVGConfig(msg: { configId: number, teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number }, session: BackendSession) { + const { configId, teamTime, prepareTime, battleTime, scheduleTime } = msg; + if(!isNumber(configId) || !isTimestamp(teamTime) || !isTimestamp(prepareTime) || !isTimestamp(battleTime) || !isTimestamp(scheduleTime)) { + return resResult(STATUS.WRONG_PARMS); + } + if(teamTime > prepareTime || prepareTime > battleTime || battleTime > scheduleTime) { + return resResult(STATUS.GM_GVG_TIME_ERR); + } + const config = await GVGConfigModel.updateConfig(configId, teamTime, prepareTime, battleTime, scheduleTime); + await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); + await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast(); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/gm/handler/gmOrderHandler.ts b/game-server/app/servers/gm/handler/gmOrderHandler.ts index fbc504102..310ecc4a2 100644 --- a/game-server/app/servers/gm/handler/gmOrderHandler.ts +++ b/game-server/app/servers/gm/handler/gmOrderHandler.ts @@ -1,182 +1,183 @@ -import { Application, BackendSession, pinus } from 'pinus'; -import { genCode, getRandSingleEelm, resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { ORDER_STATE, PAY_TYPE } from '../../../consts'; -import _ = require('underscore'); -import { dicRMB } from '../../../pubUtils/dictionary/DicRMB'; -import { getActivityById } from '../../../services/activity/activityService'; -import { UserOrderModel } from '../../../db/UserOrder'; -import { settleOrder, settleOrderAli, settleOrderFromHandler, settleOrderWx } from '../../../services/orderService'; -import { getActivityProducts, getParamStr } from '../../../services/gmService'; -import { ActivityGroupModel } from '../../../db/ActivityGroup'; -import { Receiver } from '../../../db/GMMail'; -import { getRoleOnlineInfo } from '../../../services/redisService'; -import { RoleModel } from '../../../db/Role'; - -export interface Cascader { - value: number|string; - label: number|string; - children?: Cascader[]; -} - -export default function (app: Application) { - return new GmOrderHandler(app); -} - -export class GmOrderHandler { - constructor(private app: Application) { - } - - async getActivitiesCanBuy(msg: { serverId: number }, session: BackendSession) { - const { serverId } = msg; - - let groups = await ActivityGroupModel.findByServerId(serverId); - let result: Cascader[] = []; - for (let groupData of groups) { - let activities: Cascader[] = []; - for (let activityId of groupData.activities) { - let activityData = await getActivityById(activityId); - if(!activityData) continue; - let products = getActivityProducts(activityData); - if(products) { - let children = products.filter(cur => !!cur); - if(children.length > 0) { - activities.push({ - value: activityData.activityId, - label: activityData.name, - children - }); - } - } - } - if(activities.length > 0) { - result.push({ - value: groupData.groupId, - label: groupData.groupName, - children: activities - }); - } - } - - return resResult(STATUS.SUCCESS, result); - } - - /** - * @description 虚拟充值 - * @param {BackendSession} session - * @memberof orderHandler - */ - async applyOrder(msg: { serverId: number, activityId: (number|string)[], receiver: Receiver[] }, session: BackendSession) { - const { activityId: activityIds, receiver } = msg; - let activityId = activityIds[1]; - let productID = activityIds[2]; - - let payType = PAY_TYPE.TEST - //如果有特殊情况,activityId可为0 - if (!productID || !_.isString(productID)) { - return resResult(STATUS.WRONG_PARMS); - } - - //商品价格信息 - let productInfo = dicRMB.get(productID) - if (!productInfo) { - console.log('productID', productID) - return resResult(STATUS.NO_PRODUCT_ID); - } - - let price = productInfo.price;//价格 - let productType = productInfo.type;//类型 - let message = productInfo.message;//商品信息 - let localOrderID = genCode(32);//本地订单号 - let orderID = '';//平台订单号 - let sdkOrderInfo = null;//客户端需要的平台订单信息 - - let activityData = await getActivityById(activityId); - if (!activityData) return resResult(STATUS.ACTIVITY_MISSING); - - let results = []; - for(let { roleId, serverId } of receiver) { - let role = await RoleModel.findByRoleId(roleId); - if(!role && role.serverId != serverId) { - results.push(resResult(STATUS.ROLE_NOT_FOUND)); - continue; - } - let paramStr = await getParamStr(activityData, productID, role); - let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false, 0); - - //订单成功 - if(!orderInfo) { - results.push(resResult(STATUS.NO_ORDER)); - continue; - } - let onlineUser = await getRoleOnlineInfo(roleId); - let result = await settleOrder(orderInfo, serverId, onlineUser?.sid); - orderInfo = await UserOrderModel.success(roleId, localOrderID, JSON.stringify(result)); - console.log(`测试支付完成!!!!!!!!!!!!! serverId:${serverId}, productID:${productID}, productType:${productType}, roleId:${roleId}, localOrderID:${localOrderID}, payType:${payType}`) - results.push(resResult(STATUS.SUCCESS)); - } - - let findResultErrCode = results.find(cur => cur.code != 0); - if(!findResultErrCode) { - return resResult(STATUS.SUCCESS); - } else { - return findResultErrCode; - } - } - - - /** - * @description 补单 - * @param {BackendSession} session - * @memberof orderHandler - */ - async reCallOrder(msg: { localOrderID: string }, session: BackendSession) { - - let sid = session.get('sid'); - const { localOrderID } = msg; - - if (!localOrderID || !_.isString(localOrderID)) { - return resResult(STATUS.WRONG_PARMS); - } - let orderInfo = await UserOrderModel.findOrder(localOrderID); - if (!orderInfo) { - return resResult(STATUS.NO_ORDER); - } - - if(orderInfo.state == ORDER_STATE.RESULT_SUCCESS) { - return resResult(STATUS.DUPLICATE_ORDER); - } - //商品价格信息 - let productInfo = dicRMB.get(orderInfo.productID) - if (!productInfo) { - console.log(orderInfo.productID) - return resResult(STATUS.NO_PRODUCT_ID); - } - - let order = await UserOrderModel.findOrder(localOrderID); - - let result = await settleOrder(order, order.serverId, sid); - await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result)); - - orderInfo = await UserOrderModel.findOrder(localOrderID); - - //订单成功 - console.log('结算完成', localOrderID) - let res: any = {}; - try { - res = orderInfo.rewardResult? JSON.parse(orderInfo.rewardResult): {}; - } catch(e) { - console.log('order rewardResult', e); - } - if(res.code && res.code != 0) { - return resResult(STATUS.APPLY_ORDER_ERROR); - } - - return resResult(STATUS.SUCCESS, { - ...res, - price: orderInfo.price, - state: orderInfo.state, - localOrderID: orderInfo.localOrderID - }); - } -} \ No newline at end of file +import { Application, BackendSession, pinus } from 'pinus'; +import { genCode, getRandSingleEelm, resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { ORDER_STATE, PAY_TYPE } from '../../../consts'; +import _ = require('underscore'); +import { dicRMB } from '@pubUtils/dictionary/DicRMB'; +import { getActivityById } from '../../../services/activity/activityService'; +import { UserOrderModel } from '@db/UserOrder'; +import { settleOrder, settleOrderAli, settleOrderFromHandler, settleOrderWx } from '../../../services/orderService'; +import { getActivityProducts, getParamStr } from '../../../services/gmService'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { Receiver } from '@db/GMMail'; +import { getRoleOnlineInfo } from '../../../services/redisService'; +import { RoleModel } from '@db/Role'; + +export interface Cascader { + value: number|string; + label: number|string; + children?: Cascader[]; +} + +export default function (app: Application) { + return new GmOrderHandler(app); +} + +export class GmOrderHandler { + constructor(private app: Application) { + } + + async getActivitiesCanBuy(msg: { serverId: number }, session: BackendSession) { + const { serverId } = msg; + + let groups = await ActivityGroupModel.findByServerId(serverId); + let result: Cascader[] = []; + for (let groupData of groups) { + let activities: Cascader[] = []; + for (let activityId of groupData.activities) { + let activityData = await getActivityById(activityId); + if(!activityData) continue; + let products = getActivityProducts(activityData); + if(products) { + let children = products.filter(cur => !!cur); + if(children.length > 0) { + activities.push({ + value: activityData.activityId, + label: activityData.name, + children + }); + } + } + } + if(activities.length > 0) { + result.push({ + value: groupData.groupId, + label: groupData.groupName, + children: activities + }); + } + } + + return resResult(STATUS.SUCCESS, result); + } + + /** + * @description 虚拟充值 + * @param {BackendSession} session + * @memberof orderHandler + */ + async applyOrder(msg: { serverId: number, activityId: (number|string)[], receiver: Receiver[] }, session: BackendSession) { + const { activityId: activityIds, receiver } = msg; + let activityId = activityIds[1]; + let productID = activityIds[2]; + + let payType = PAY_TYPE.TEST + //如果有特殊情况,activityId可为0 + if (!productID || !_.isString(productID)) { + return resResult(STATUS.WRONG_PARMS); + } + + //商品价格信息 + let productInfo = dicRMB.get(productID) + if (!productInfo) { + console.log('productID', productID) + return resResult(STATUS.NO_PRODUCT_ID); + } + + let price = productInfo.price;//价格 + let productType = productInfo.type;//类型 + let message = productInfo.message;//商品信息 + let localOrderID = genCode(32);//本地订单号 + let orderID = '';//平台订单号 + let sdkOrderInfo = null;//客户端需要的平台订单信息 + + let activityData = await getActivityById(activityId); + if (!activityData) return resResult(STATUS.ACTIVITY_MISSING); + + let results = []; + for(let { roleId, serverId } of receiver) { + let role = await RoleModel.findByRoleId(roleId); + if(!role && role.serverId != serverId) { + results.push(resResult(STATUS.ROLE_NOT_FOUND)); + continue; + } + let paramStr = await getParamStr(activityData, productID, role); + let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false, 0); + + //订单成功 + if(!orderInfo) { + results.push(resResult(STATUS.NO_ORDER)); + continue; + } + let onlineUser = await getRoleOnlineInfo(roleId); + let result = await settleOrder(orderInfo, serverId, onlineUser?.sid); + orderInfo = await UserOrderModel.success(roleId, localOrderID, JSON.stringify(result)); + console.log(`测试支付完成!!!!!!!!!!!!! serverId:${serverId}, productID:${productID}, productType:${productType}, roleId:${roleId}, localOrderID:${localOrderID}, payType:${payType}`) + results.push(resResult(STATUS.SUCCESS)); + } + + let findResultErrCode = results.find(cur => cur.code != 0); + if(!findResultErrCode) { + return resResult(STATUS.SUCCESS); + } else { + return findResultErrCode; + } + } + + + /** + * @description 补单 + * @param {BackendSession} session + * @memberof orderHandler + */ + async reCallOrder(msg: { localOrderID: string }, session: BackendSession) { + + let sid = session.get('sid'); + const { localOrderID } = msg; + + if (!localOrderID || !_.isString(localOrderID)) { + return resResult(STATUS.WRONG_PARMS); + } + let orderInfo = await UserOrderModel.findOrder(localOrderID); + if (!orderInfo) { + return resResult(STATUS.NO_ORDER); + } + + if(orderInfo.state == ORDER_STATE.RESULT_SUCCESS) { + return resResult(STATUS.DUPLICATE_ORDER); + } + //商品价格信息 + let productInfo = dicRMB.get(orderInfo.productID) + if (!productInfo) { + console.log(orderInfo.productID) + return resResult(STATUS.NO_PRODUCT_ID); + } + + let order = await UserOrderModel.findOrder(localOrderID); + + let result = await settleOrder(order, order.serverId, sid); + await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result)); + + orderInfo = await UserOrderModel.findOrder(localOrderID); + + //订单成功 + console.log('结算完成', localOrderID) + let res: any = {}; + try { + res = orderInfo.rewardResult? JSON.parse(orderInfo.rewardResult): {}; + } catch(e) { + console.log('order rewardResult', e); + } + if(res.code && res.code != 0) { + return resResult(STATUS.APPLY_ORDER_ERROR); + } + + return resResult(STATUS.SUCCESS, { + ...res, + price: orderInfo.price, + state: orderInfo.state, + localOrderID: orderInfo.localOrderID + }); + } +} + diff --git a/game-server/app/servers/gm/handler/gmRoleHandler.ts b/game-server/app/servers/gm/handler/gmRoleHandler.ts index b7c0fcbef..eb1f97aba 100644 --- a/game-server/app/servers/gm/handler/gmRoleHandler.ts +++ b/game-server/app/servers/gm/handler/gmRoleHandler.ts @@ -1,437 +1,438 @@ -import { Application, BackendSession, pinus } from 'pinus'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { getRoleOnlineInfo, redisClient, updateUserInfo } from '../../../services/redisService'; -import { addItems } from '../../../services/role/rewardService'; -import { RewardInter } from '../../../pubUtils/interface'; -import { gameData, getExpByLv, getHeroExpByLv, getHeroLvByExp, getLvByExp, getEquipByJobClassAndEPlace } from '../../../pubUtils/data'; -import { RoleModel, RoleType, WarStar } from '../../../db/Role'; -import { BLOCK_TYPE, DEFAULT_HEROES, GUILD_AUTH, GUILD_DISMISS_WAY, GUILD_JOB, GUILD_MASTER_CHANGE_WAY, GUILD_STATUS, GUILD_STRUCTURE, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, REDIS_KEY, TA_EVENT, WAR_TYPE } from '../../../consts'; -import { GuildFormParam, SetHeroParam } from '../../../domain/backEndField/params'; -import { GuildModel, GuildUpdateParam } from '../../../db/Guild'; -import { Rank } from '../../../services/rankService'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { UserGuildApplyModel } from '../../../db/UserGuildApply'; -import { reportTAEvent } from '../../../services/sdkService'; -import { sendMailByContent } from '../../../services/mailService'; -import { GuildLeader } from '../../../domain/rank'; -import { HeroModel } from '../../../db/Hero'; -import { SkinModel } from '../../../db/Skin'; -import { PvpDefenseModel } from '../../../db/PvpDefense'; -import { createHeroes } from '../../../services/role/createHero'; -import { calculateCeWithHero, calculateCeWithRole } from '../../../services/playerCeService'; -import { pushChangeGuildLeader, pushGuildDismiss, pushGuildInfoUpdate } from '../../../services/guildService'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; -import { RScriptRecordModel } from '../../../db/RScriptRecord'; -import { DicWar } from '../../../pubUtils/dictionary/DicWar'; -import { SchoolModel } from '../../../db/School'; -import { JewelModel } from '../../../db/Jewel'; -import { RoleCeModel } from '../../../db/RoleCe'; -import { setTrainLv } from '../../../services/gmService'; -import { ArtifactModel } from '../../../db/Artifact'; -import { roleLeave } from '../../../services/redisService'; -import { KeyName } from '../../../domain/rank'; -import { LadderMatchModel } from '../../../db/LadderMatch'; - -let timer: NodeJS.Timer; -export default function (app: Application) { - return new GmRoleHandler(app); -} - -export class GmRoleHandler { - constructor(private app: Application) { - } - - async addItems(msg: { roleId: string, roleName: string, serverId: number, values: { reward: RewardInter[], heroes: number[], lv: number, expInc: number, fixedIpLocation: string }}, session: BackendSession) { - let { roleId, roleName, serverId, values } = msg; - - let { reward, heroes, lv, expInc = 0, fixedIpLocation } = values; - let connect = await getRoleOnlineInfo(roleId); - let sid = connect.isOnline?connect.sid: null; - - if(reward &&reward.length > 0) { - await addItems(roleId, roleName, sid, values.reward, ITEM_CHANGE_REASON.DEBUG); - } - if(heroes && heroes.length > 0) { - await createHeroes(roleId, roleName, sid, serverId, heroes.map(hid => { return { hid, count: 1 }})) - } - if(lv && lv > 0) { - let exp = getExpByLv(lv - 1)?.sum||0; - exp += expInc; - let newLv = getLvByExp(exp); - let role = await RoleModel.updateRoleInfo(roleId, { lv: newLv, exp }) - let r = new Rank(REDIS_KEY.USER_LV, { serverId: serverId }); - await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_EXP_CHANGE, { - isLvUp: false, lv: newLv, exp - }, sid); - } - if(fixedIpLocation != undefined) { - await RoleModel.updateRoleInfo(roleId, { fixedIpLocation }) - } - return resResult(STATUS.SUCCESS); - } - - async handleBlock(msg: { roleId: string, blockType: BLOCK_TYPE, blockReason: string }, session: BackendSession) { - let { roleId, blockType, blockReason } = msg; - if(roleId == undefined || blockType == undefined || blockReason == undefined) return resResult(STATUS.WRONG_PARMS); - let role = await RoleModel.updateRoleInfo(roleId, { blockType, blockReason }); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - let { isOnline, sid } = await getRoleOnlineInfo(roleId); - if(isOnline) { - await this.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, blockType }]); - if(blockType == BLOCK_TYPE.BLOCK) { // 踢走 - await this.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId, STATUS.BLOCKED); - await roleLeave(roleId); - } - } - return resResult(STATUS.SUCCESS); - } - - - async setHero(msg: { roleId: string, hid: number, param: SetHeroParam }, session: BackendSession) { - let { roleId, hid } = msg; - let param = new SetHeroParam(msg.param); - if(!param.checkParams()) return resResult(STATUS.WRONG_PARMS); - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - let { sid } = await getRoleOnlineInfo(roleId); - - if(param.lv && param.lv > 0) { - let exp = getHeroExpByLv(param.lv - 1)||0; - exp += (param.expInc||0); - let newLv = getHeroLvByExp(exp); - param.lv = newLv; - param['exp'] = exp; - } - await calculateCeWithHero(HERO_SYSTEM_TYPE.INIT, roleId, hero.serverId, sid, hid, {...hero, ...param}); - // if(param.job > 0) { - // await calculateCe(HERO_SYSTEM_TYPE.STAGEUP, roleId, hero.serverId, sid, param, {}, { hid }); - - // hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAGEUP, sid, roleId, hero, { job: param.job, jobStage: 0 }); - // } - - // if (hero.star != param.star) { - // await calAllHeroCe(HERO_SYSTEM_TYPE.STAR, sid, roleId, {}, [hid, 1]); // 升星可能影响到百家学院全局加成 - // } - return resResult(STATUS.SUCCESS); - } - - /** - * 升级英雄装备至限制内的最高级 - * - * @param {{ roleId: string, hid: number }} msg - * @param {BackendSession} session - * @return {*} - * @memberof GmRoleHandler - */ - async upgradeHeroEPlace(msg: { roleId: string, hid: number }, session: BackendSession) { - let { roleId, hid } = msg; - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - /* - * 通过 - * dic_zyz_equipQuality.json - * dic_zyz_equipStar.json - * dic_zyz_equipStrength.json - * dic_zyz_artifactQuality.json - * 配置文件得出: - * maxLevel: 100 - * maxQuality: 5 (金) - * maxStar: 12 - * - * 限制: - * 装备等级不能超过hero等级 - * maxQuality限制等级最大值: 金 最大lv 100 - * - * 装备信息: - * dic_zyz_equip.json - */ - const MAX_STAR = 12; - const MAX_QUALITY = 5; - // EPLACE_ID 分别代表4个部位 - const EPLACE_IDS = [1, 2, 3, 4]; - // 装备升级、升星、升品(注意升级限制) - // 装备未满 - 补全 - 并升至满级 - let doNotGetEPlaceIds = new Set(EPLACE_IDS); - hero.ePlace.forEach((ePlaceItem) => { - doNotGetEPlaceIds.delete(ePlaceItem.id); - // 该装备已拥有 - 升级、品、星 - // 升级 - 最大等级100 - ePlaceItem.lv = hero.lv; // 英雄等级肯定小于MAX_LV - // 升品 - 金 - ePlaceItem.quality = MAX_QUALITY; - ePlaceItem.qualityStage = 0; - // 生星 - 最高12 - ePlaceItem.star = MAX_STAR; - ePlaceItem.starStage = 0; - }); - // 装备补全 - let dicHero = gameData.hero.get(hero.skinId); - doNotGetEPlaceIds.forEach((ePlaceId) => { - let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, ePlaceId); - if (dicEquip) { - hero.ePlace.push({ - lv: hero.lv, - quality: MAX_QUALITY, - qualityStage: 0, - star: MAX_STAR, - starStage: 0, - jewel: 0, - id: ePlaceId, - equipId: dicEquip.id, - stones: [ - { - id: 1, - stone: 0 - }, - { - id: 2, - stone: 0 - }, - { - id: 3, - stone: 0 - } - ] - }) - } - }) - - // 更新装备信息 - await HeroModel.updateHeroInfo(roleId, hid, { ePlace: hero.ePlace }); - // 获取战力重算需要的数据 - let role = await RoleModel.findByRoleId(roleId); - let schools = await SchoolModel.findByRoleId(roleId); - let jewels = await JewelModel.findbyRole(roleId); - let heroes = await HeroModel.findByRole(roleId); - let skins = await SkinModel.findbyRole(roleId); - let artifacts = await ArtifactModel.findbyRole(roleId); - // 所有战力重算 - await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); - // 获取更新装备的英雄 - hero = await HeroModel.findByHidAndRole(hid, roleId); - - // 返回强化,升星,升品后的hero数据 - return resResult(STATUS.SUCCESS, { curHero: hero }); - } - - async deleteHero(msg: { roleId: string, hid: number }, session: BackendSession) { - let { roleId, hid } = msg; - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - await HeroModel.deleteHero(roleId, hid); - await SkinModel.deleteByHero(roleId, hid); - let role = await RoleModel.findByRoleId(roleId); - await PvpDefenseModel.deleteHero(roleId, hid); - await RoleCeModel.deleteHero(roleId, hid); - await RoleModel.updateRoleInfo(roleId, { topLineup: role.topLineup.filter(cur => cur.hid != hid), topLineupCe: role.topLineupCe - hero.ce, ce: role.ce - hero.ce }); - await JewelModel.updateMany({ hid }, { $set: { hid: 0}}); - - return resResult(STATUS.SUCCESS); - } - - - async updateGuild(msg: GuildFormParam, session: BackendSession ) { - const uid = session.get('uid'); - let params = new GuildFormParam(msg); - if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); - - let guild = await GuildModel.findByCode(params.code, null, '+members'); - let structure = guild.structure||[]; - - let updateParams: GuildUpdateParam = { code: params.code }; - if(params.name && guild.name != params.name) updateParams.name = params.name; - if(params.fund != undefined && guild.fund != params.fund) updateParams.fund = params.fund; - if(params.notice && guild.notice != params.notice) updateParams.notice = params.notice; - if(params.lv && guild.lv != params.lv) updateParams.lv = params.lv; - for(let id = GUILD_STRUCTURE.START; id < GUILD_STRUCTURE.END; id ++) { - let curStructure = structure.find(cur => cur.id == id); - let lv = params.lv; - switch(id) { - case GUILD_STRUCTURE.ARMY_CENTER: - lv = params.lv; break; - case GUILD_STRUCTURE.EQUIP_PRODUCE: - lv = params.equipProduce; break; - case GUILD_STRUCTURE.BOSS: - lv = params.boss; break; - case GUILD_STRUCTURE.TRAIN: - lv = params.train; break; - case GUILD_STRUCTURE.DONATE: - lv = params.donate; break; - case GUILD_STRUCTURE.WISH_POOL: - lv = params.wishPool; break; - case GUILD_STRUCTURE.STORE: - lv = params.store; break; - } - if(curStructure) { - curStructure.lv = lv; - } else { - structure.push({ id, lv }); - } - } - updateParams.structure = structure; - await pushGuildInfoUpdate(params.code, updateParams); - // 设置玩家名 - if(updateParams.name != undefined || updateParams.lv != undefined) { - let arr = []; - if(updateParams.name != undefined) { - arr.push({ field: 'name', value: updateParams.name }); - for(let roleId of guild.members) { - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: updateParams.name }]); - } - } - if(updateParams.lv != undefined) arr.push({ field: 'lv', value: updateParams.lv }); - await updateUserInfo(REDIS_KEY.GUILD_INFO, params.code, arr); - } - if (updateParams.lv != undefined) { - let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId: guild.serverId }); - await r.setRankWithGuildInfo2(guild.code, updateParams.lv, guild.activeWeekly, guild.lvUpdateTime, guild); - } - - guild = await GuildModel.updateInfo(params.code, updateParams); - - if(params.trainLv) { - await setTrainLv(params.code, params.trainLv); - } - - return resResult(STATUS.SUCCESS); - } - async dismissGuild(msg: { code: string }, session: BackendSession) { - - const { code } = msg; - - let guild = await GuildModel.findByCode(code, null, '+serverId'); - if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); - if(guild.status == GUILD_STATUS.DISMISSED) return resResult(STATUS.GUILD_DELETE_ERROR); - - let serverId = guild.serverId; - guild = await GuildModel.dismiss(code, serverId); - if (!guild) return resResult(STATUS.GUILD_DELETE_ERROR); - - await UserGuildModel.dismiss(code); - const { members } = guild; - await RoleModel.dissmissGuild(members); - await UserGuildApplyModel.deleteApplyByGuild(code); - - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast(members.map(roleId => { return { roleId, userGuild: null } })); // 更新session - - // 删除channel - await pushGuildDismiss(code); - let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - await r.removeFromRank({ guildCode: code }); - let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await r2.removeFromRank({ guildCode: code }); - let leader = guild.leader; - reportTAEvent(leader.roleId, TA_EVENT.GUILD_DISMISS, { name: guild.name, way: GUILD_DISMISS_WAY.BACKEND }); - - return resResult(STATUS.SUCCESS, { code, status: guild.status }); - } - - async setGuildLeader(msg: { code: string, roleId: string }, session: BackendSession) { - - const { code, roleId } = msg; - let guild = await GuildModel.findByCode(code, null, '+serverId'); - if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); - if(guild.status == GUILD_STATUS.DISMISSED) return resResult(STATUS.GUILD_DELETE_ERROR); - - let role = await RoleModel.findByRoleId(roleId); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let userGuild = await UserGuildModel.getMyGuild(roleId); - if(!userGuild || userGuild.guildCode != code) return resResult(STATUS.GUILD_KICK_ERROR); - if(userGuild.auth == GUILD_AUTH.LEADER) return resResult(STATUS.GUILD_USER_IS_LEADER); - - let leader = guild.leader; - // 交换 - let oldLeaderUserGuild = await UserGuildModel.updateInfo(leader.roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}, 'auth'); // 团长撤 - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: leader.roleId, userGuild: oldLeaderUserGuild }]); // 更新session - - let newLeaderUserGuild = await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.LEADER, job: GUILD_JOB.DAJIANGJUN }, {}, 'auth'); // 最高功勋人升 - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: roleId, userGuild: newLeaderUserGuild }]); // 更新session - - let managerCntInc = userGuild.auth == GUILD_AUTH.MANAGER ? -1 : 0; // 管理人数 - - guild = await GuildModel.updateInfo(code, { leader: role._id }, { managerCnt: managerCntInc }, 'managerCnt name'); // 如果有转让团长设置leader - - // 添加动态 - await pushChangeGuildLeader(code, guild.managerCnt, role, leader.roleId); - await sendMailByContent(MAIL_TYPE.GUILD_BE_IMPEACH, leader.roleId, { params: [guild.name] }); - await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, roleId, { params: [guild.name] }); - - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(role) }]); - reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY.BACKEND, change_id_after: roleId }) - - return resResult(STATUS.SUCCESS, { code }); - } - - async skipEpilogue(msg: { roleId: string, roleName: string }, session: BackendSession) { - - const { roleId, roleName } = msg; - let role = await RoleModel.findByRoleId(roleId); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - if(role.hasInit) return resResult(STATUS.ROLE_HAS_INIT); - - let checkName = await RoleModel.checkName(roleName, role.serverId); - if (checkName) return resResult(STATUS.NAME_HAS_USED); - - let warStars: WarStar[] = []; - let insertParams: DicWar[] = []; - let exp = 0; - for(let i = 101; i <= 103; i++) { - let dicWar = gameData.war.get(i); - insertParams.push(dicWar); - warStars.push({ id: dicWar.war_id, warType: dicWar.warType, star: 0, stars: [] }); - exp += dicWar.kingExp; - } - let lv = getLvByExp(exp); - - await RScriptRecordModel.deleteByWarType(roleId, WAR_TYPE.NORMAL); - await RScriptRecordModel.insertScripts(roleId, insertParams); - - let onlineUser = await getRoleOnlineInfo(roleId); - await createHeroes(roleId, roleName, onlineUser?.sid, role.serverId, DEFAULT_HEROES.map(hid => ({hid, count: 1})), { roleName, hasInit: true, title: role.title, teraphs: role.teraphs, lv, exp, warStar: warStars }); - - return resResult(STATUS.SUCCESS); - } - - async reCalCe(msg: { roleId: string }, session: BackendSession) { - const { roleId } = msg; - let role = await RoleModel.findByRoleId(roleId); - let schools = await SchoolModel.findByRoleId(roleId); - let jewels = await JewelModel.findbyRole(roleId); - let heroes = await HeroModel.findByRole(roleId); - let skins = await SkinModel.findbyRole(roleId); - let artifacts = await ArtifactModel.findbyRole(roleId); - - await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); - return resResult(STATUS.SUCCESS); - } - - - async clearRank(msg: { roleId: string }, session: BackendSession) { - let { roleId } = msg; - let role = await RoleModel.findByRoleId(roleId); - if(!role) return resResult(STATUS.WRONG_PARMS); - if(role.blockType != 2) return resResult(STATUS.GM_CANNOT_CLEAR_RANK) - let { serverId } = role; - - await redisClient().zremAsync(new KeyName(REDIS_KEY.TOWER_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.LADDER, { serverId }).getName(), roleId); - await LadderMatchModel.updateByRoleId(roleId, { rank: 0 }); - await redisClient().zremAsync(new KeyName(REDIS_KEY.TOP_LINEUP_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.TOP_HERO_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.HERO_NUM_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.SUM_CE_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.USER_LV, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.MAIN_RANK, { serverId }).getName(), roleId); - await redisClient().zremAsync(new KeyName(REDIS_KEY.MAIN_ELITE_RANK, { serverId }).getName(), roleId); - - let keys = await redisClient().keysAsync(REDIS_KEY.PVP_RANK); - for(let key of keys) await redisClient().zremAsync(key, roleId); - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, pinus } from 'pinus'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { getRoleOnlineInfo, redisClient, updateUserInfo } from '../../../services/redisService'; +import { addItems } from '../../../services/role/rewardService'; +import { RewardInter } from '@pubUtils/interface'; +import { gameData, getExpByLv, getHeroExpByLv, getHeroLvByExp, getLvByExp, getEquipByJobClassAndEPlace } from '@pubUtils/data'; +import { RoleModel, RoleType, WarStar } from '@db/Role'; +import { BLOCK_TYPE, DEFAULT_HEROES, GUILD_AUTH, GUILD_DISMISS_WAY, GUILD_JOB, GUILD_MASTER_CHANGE_WAY, GUILD_STATUS, GUILD_STRUCTURE, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, MEMORY_LOG_TYPE, PUSH_ROUTE, REDIS_KEY, TA_EVENT, WAR_TYPE } from '../../../consts'; +import { GuildFormParam, SetHeroParam } from '@domain/backEndField/params'; +import { GuildModel, GuildUpdateParam } from '@db/Guild'; +import { Rank } from '../../../services/rankService'; +import { UserGuildModel } from '@db/UserGuild'; +import { UserGuildApplyModel } from '@db/UserGuildApply'; +import { reportTAEvent } from '../../../services/sdkService'; +import { sendMailByContent } from '../../../services/mailService'; +import { GuildLeader } from '@domain/rank'; +import { HeroModel } from '@db/Hero'; +import { SkinModel } from '@db/Skin'; +import { PvpDefenseModel } from '@db/PvpDefense'; +import { createHeroes } from '../../../services/role/createHero'; +import { calculateCeWithHero, calculateCeWithRole } from '../../../services/playerCeService'; +import { pushChangeGuildLeader, pushGuildDismiss, pushGuildInfoUpdate } from '../../../services/guildService'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; +import { RScriptRecordModel } from '@db/RScriptRecord'; +import { DicWar } from '@pubUtils/dictionary/DicWar'; +import { SchoolModel } from '@db/School'; +import { JewelModel } from '@db/Jewel'; +import { RoleCeModel } from '@db/RoleCe'; +import { setTrainLv } from '../../../services/gmService'; +import { ArtifactModel } from '@db/Artifact'; +import { roleLeave } from '../../../services/redisService'; +import { KeyName } from '@domain/rank'; +import { LadderMatchModel } from '@db/LadderMatch'; + +let timer: NodeJS.Timer; +export default function (app: Application) { + return new GmRoleHandler(app); +} + +export class GmRoleHandler { + constructor(private app: Application) { + } + + async addItems(msg: { roleId: string, roleName: string, serverId: number, values: { reward: RewardInter[], heroes: number[], lv: number, expInc: number, fixedIpLocation: string }}, session: BackendSession) { + let { roleId, roleName, serverId, values } = msg; + + let { reward, heroes, lv, expInc = 0, fixedIpLocation } = values; + let connect = await getRoleOnlineInfo(roleId); + let sid = connect.isOnline?connect.sid: null; + + if(reward &&reward.length > 0) { + await addItems(roleId, roleName, sid, values.reward, ITEM_CHANGE_REASON.DEBUG); + } + if(heroes && heroes.length > 0) { + await createHeroes(roleId, roleName, sid, serverId, heroes.map(hid => { return { hid, count: 1 }})) + } + if(lv && lv > 0) { + let exp = getExpByLv(lv - 1)?.sum||0; + exp += expInc; + let newLv = getLvByExp(exp); + let role = await RoleModel.updateRoleInfo(roleId, { lv: newLv, exp }) + let r = new Rank(REDIS_KEY.USER_LV, { serverId: serverId }); + await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_EXP_CHANGE, { + isLvUp: false, lv: newLv, exp + }, sid); + } + if(fixedIpLocation != undefined) { + await RoleModel.updateRoleInfo(roleId, { fixedIpLocation }) + } + return resResult(STATUS.SUCCESS); + } + + async handleBlock(msg: { roleId: string, blockType: BLOCK_TYPE, blockReason: string }, session: BackendSession) { + let { roleId, blockType, blockReason } = msg; + if(roleId == undefined || blockType == undefined || blockReason == undefined) return resResult(STATUS.WRONG_PARMS); + let role = await RoleModel.updateRoleInfo(roleId, { blockType, blockReason }); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + let { isOnline, sid } = await getRoleOnlineInfo(roleId); + if(isOnline) { + await this.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, blockType }]); + if(blockType == BLOCK_TYPE.BLOCK) { // 踢走 + await this.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId, STATUS.BLOCKED); + await roleLeave(roleId); + } + } + return resResult(STATUS.SUCCESS); + } + + + async setHero(msg: { roleId: string, hid: number, param: SetHeroParam }, session: BackendSession) { + let { roleId, hid } = msg; + let param = new SetHeroParam(msg.param); + if(!param.checkParams()) return resResult(STATUS.WRONG_PARMS); + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + let { sid } = await getRoleOnlineInfo(roleId); + + if(param.lv && param.lv > 0) { + let exp = getHeroExpByLv(param.lv - 1)||0; + exp += (param.expInc||0); + let newLv = getHeroLvByExp(exp); + param.lv = newLv; + param['exp'] = exp; + } + await calculateCeWithHero(HERO_SYSTEM_TYPE.INIT, roleId, hero.serverId, sid, hid, {...hero, ...param}); + // if(param.job > 0) { + // await calculateCe(HERO_SYSTEM_TYPE.STAGEUP, roleId, hero.serverId, sid, param, {}, { hid }); + + // hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAGEUP, sid, roleId, hero, { job: param.job, jobStage: 0 }); + // } + + // if (hero.star != param.star) { + // await calAllHeroCe(HERO_SYSTEM_TYPE.STAR, sid, roleId, {}, [hid, 1]); // 升星可能影响到百家学院全局加成 + // } + return resResult(STATUS.SUCCESS); + } + + /** + * 升级英雄装备至限制内的最高级 + * + * @param {{ roleId: string, hid: number }} msg + * @param {BackendSession} session + * @return {*} + * @memberof GmRoleHandler + */ + async upgradeHeroEPlace(msg: { roleId: string, hid: number }, session: BackendSession) { + let { roleId, hid } = msg; + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + /* + * 通过 + * dic_zyz_equipQuality.json + * dic_zyz_equipStar.json + * dic_zyz_equipStrength.json + * dic_zyz_artifactQuality.json + * 配置文件得出: + * maxLevel: 100 + * maxQuality: 5 (金) + * maxStar: 12 + * + * 限制: + * 装备等级不能超过hero等级 + * maxQuality限制等级最大值: 金 最大lv 100 + * + * 装备信息: + * dic_zyz_equip.json + */ + const MAX_STAR = 12; + const MAX_QUALITY = 5; + // EPLACE_ID 分别代表4个部位 + const EPLACE_IDS = [1, 2, 3, 4]; + // 装备升级、升星、升品(注意升级限制) + // 装备未满 - 补全 - 并升至满级 + let doNotGetEPlaceIds = new Set(EPLACE_IDS); + hero.ePlace.forEach((ePlaceItem) => { + doNotGetEPlaceIds.delete(ePlaceItem.id); + // 该装备已拥有 - 升级、品、星 + // 升级 - 最大等级100 + ePlaceItem.lv = hero.lv; // 英雄等级肯定小于MAX_LV + // 升品 - 金 + ePlaceItem.quality = MAX_QUALITY; + ePlaceItem.qualityStage = 0; + // 生星 - 最高12 + ePlaceItem.star = MAX_STAR; + ePlaceItem.starStage = 0; + }); + // 装备补全 + let dicHero = gameData.hero.get(hero.skinId); + doNotGetEPlaceIds.forEach((ePlaceId) => { + let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, ePlaceId); + if (dicEquip) { + hero.ePlace.push({ + lv: hero.lv, + quality: MAX_QUALITY, + qualityStage: 0, + star: MAX_STAR, + starStage: 0, + jewel: 0, + id: ePlaceId, + equipId: dicEquip.id, + stones: [ + { + id: 1, + stone: 0 + }, + { + id: 2, + stone: 0 + }, + { + id: 3, + stone: 0 + } + ] + }) + } + }) + + // 更新装备信息 + await HeroModel.updateHeroInfo(roleId, hid, { ePlace: hero.ePlace }); + // 获取战力重算需要的数据 + let role = await RoleModel.findByRoleId(roleId); + let schools = await SchoolModel.findByRoleId(roleId); + let jewels = await JewelModel.findbyRole(roleId); + let heroes = await HeroModel.findByRole(roleId); + let skins = await SkinModel.findbyRole(roleId); + let artifacts = await ArtifactModel.findbyRole(roleId); + // 所有战力重算 + await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); + // 获取更新装备的英雄 + hero = await HeroModel.findByHidAndRole(hid, roleId); + + // 返回强化,升星,升品后的hero数据 + return resResult(STATUS.SUCCESS, { curHero: hero }); + } + + async deleteHero(msg: { roleId: string, hid: number }, session: BackendSession) { + let { roleId, hid } = msg; + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + await HeroModel.deleteHero(roleId, hid); + await SkinModel.deleteByHero(roleId, hid); + let role = await RoleModel.findByRoleId(roleId); + await PvpDefenseModel.deleteHero(roleId, hid); + await RoleCeModel.deleteHero(roleId, hid); + await RoleModel.updateRoleInfo(roleId, { topLineup: role.topLineup.filter(cur => cur.hid != hid), topLineupCe: role.topLineupCe - hero.ce, ce: role.ce - hero.ce }); + await JewelModel.updateMany({ hid }, { $set: { hid: 0}}); + + return resResult(STATUS.SUCCESS); + } + + + async updateGuild(msg: GuildFormParam, session: BackendSession ) { + const uid = session.get('uid'); + let params = new GuildFormParam(msg); + if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); + + let guild = await GuildModel.findByCode(params.code, null, '+members'); + let structure = guild.structure||[]; + + let updateParams: GuildUpdateParam = { code: params.code }; + if(params.name && guild.name != params.name) updateParams.name = params.name; + if(params.fund != undefined && guild.fund != params.fund) updateParams.fund = params.fund; + if(params.notice && guild.notice != params.notice) updateParams.notice = params.notice; + if(params.lv && guild.lv != params.lv) updateParams.lv = params.lv; + for(let id = GUILD_STRUCTURE.START; id < GUILD_STRUCTURE.END; id ++) { + let curStructure = structure.find(cur => cur.id == id); + let lv = params.lv; + switch(id) { + case GUILD_STRUCTURE.ARMY_CENTER: + lv = params.lv; break; + case GUILD_STRUCTURE.EQUIP_PRODUCE: + lv = params.equipProduce; break; + case GUILD_STRUCTURE.BOSS: + lv = params.boss; break; + case GUILD_STRUCTURE.TRAIN: + lv = params.train; break; + case GUILD_STRUCTURE.DONATE: + lv = params.donate; break; + case GUILD_STRUCTURE.WISH_POOL: + lv = params.wishPool; break; + case GUILD_STRUCTURE.STORE: + lv = params.store; break; + } + if(curStructure) { + curStructure.lv = lv; + } else { + structure.push({ id, lv }); + } + } + updateParams.structure = structure; + await pushGuildInfoUpdate(params.code, updateParams); + // 设置玩家名 + if(updateParams.name != undefined || updateParams.lv != undefined) { + let arr = []; + if(updateParams.name != undefined) { + arr.push({ field: 'name', value: updateParams.name }); + for(let roleId of guild.members) { + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: updateParams.name }]); + } + } + if(updateParams.lv != undefined) arr.push({ field: 'lv', value: updateParams.lv }); + await updateUserInfo(REDIS_KEY.GUILD_INFO, params.code, arr); + } + if (updateParams.lv != undefined) { + let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId: guild.serverId }); + await r.setRankWithGuildInfo2(guild.code, updateParams.lv, guild.activeWeekly, guild.lvUpdateTime, guild); + } + + guild = await GuildModel.updateInfo(params.code, updateParams); + + if(params.trainLv) { + await setTrainLv(params.code, params.trainLv); + } + + return resResult(STATUS.SUCCESS); + } + async dismissGuild(msg: { code: string }, session: BackendSession) { + + const { code } = msg; + + let guild = await GuildModel.findByCode(code, null, '+serverId'); + if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); + if(guild.status == GUILD_STATUS.DISMISSED) return resResult(STATUS.GUILD_DELETE_ERROR); + + let serverId = guild.serverId; + guild = await GuildModel.dismiss(code, serverId); + if (!guild) return resResult(STATUS.GUILD_DELETE_ERROR); + + await UserGuildModel.dismiss(code); + const { members } = guild; + await RoleModel.dissmissGuild(members); + await UserGuildApplyModel.deleteApplyByGuild(code); + + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast(members.map(roleId => { return { roleId, userGuild: null } })); // 更新session + + // 删除channel + await pushGuildDismiss(code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await r.removeFromRank({ guildCode: code }); + let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await r2.removeFromRank({ guildCode: code }); + let leader = guild.leader; + reportTAEvent(leader.roleId, TA_EVENT.GUILD_DISMISS, { name: guild.name, way: GUILD_DISMISS_WAY.BACKEND }); + + return resResult(STATUS.SUCCESS, { code, status: guild.status }); + } + + async setGuildLeader(msg: { code: string, roleId: string }, session: BackendSession) { + + const { code, roleId } = msg; + let guild = await GuildModel.findByCode(code, null, '+serverId'); + if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); + if(guild.status == GUILD_STATUS.DISMISSED) return resResult(STATUS.GUILD_DELETE_ERROR); + + let role = await RoleModel.findByRoleId(roleId); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let userGuild = await UserGuildModel.getMyGuild(roleId); + if(!userGuild || userGuild.guildCode != code) return resResult(STATUS.GUILD_KICK_ERROR); + if(userGuild.auth == GUILD_AUTH.LEADER) return resResult(STATUS.GUILD_USER_IS_LEADER); + + let leader = guild.leader; + // 交换 + let oldLeaderUserGuild = await UserGuildModel.updateInfo(leader.roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}, 'auth'); // 团长撤 + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: leader.roleId, userGuild: oldLeaderUserGuild }]); // 更新session + + let newLeaderUserGuild = await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.LEADER, job: GUILD_JOB.DAJIANGJUN }, {}, 'auth'); // 最高功勋人升 + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: roleId, userGuild: newLeaderUserGuild }]); // 更新session + + let managerCntInc = userGuild.auth == GUILD_AUTH.MANAGER ? -1 : 0; // 管理人数 + + guild = await GuildModel.updateInfo(code, { leader: role._id }, { managerCnt: managerCntInc }, 'managerCnt name'); // 如果有转让团长设置leader + + // 添加动态 + await pushChangeGuildLeader(code, guild.managerCnt, role, leader.roleId); + await sendMailByContent(MAIL_TYPE.GUILD_BE_IMPEACH, leader.roleId, { params: [guild.name] }); + await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, roleId, { params: [guild.name] }); + + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(role) }]); + reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY.BACKEND, change_id_after: roleId }) + + return resResult(STATUS.SUCCESS, { code }); + } + + async skipEpilogue(msg: { roleId: string, roleName: string }, session: BackendSession) { + + const { roleId, roleName } = msg; + let role = await RoleModel.findByRoleId(roleId); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + if(role.hasInit) return resResult(STATUS.ROLE_HAS_INIT); + + let checkName = await RoleModel.checkName(roleName, role.serverId); + if (checkName) return resResult(STATUS.NAME_HAS_USED); + + let warStars: WarStar[] = []; + let insertParams: DicWar[] = []; + let exp = 0; + for(let i = 101; i <= 103; i++) { + let dicWar = gameData.war.get(i); + insertParams.push(dicWar); + warStars.push({ id: dicWar.war_id, warType: dicWar.warType, star: 0, stars: [] }); + exp += dicWar.kingExp; + } + let lv = getLvByExp(exp); + + await RScriptRecordModel.deleteByWarType(roleId, WAR_TYPE.NORMAL); + await RScriptRecordModel.insertScripts(roleId, insertParams); + + let onlineUser = await getRoleOnlineInfo(roleId); + await createHeroes(roleId, roleName, onlineUser?.sid, role.serverId, DEFAULT_HEROES.map(hid => ({hid, count: 1})), { roleName, hasInit: true, title: role.title, teraphs: role.teraphs, lv, exp, warStar: warStars }); + + return resResult(STATUS.SUCCESS); + } + + async reCalCe(msg: { roleId: string }, session: BackendSession) { + const { roleId } = msg; + let role = await RoleModel.findByRoleId(roleId); + let schools = await SchoolModel.findByRoleId(roleId); + let jewels = await JewelModel.findbyRole(roleId); + let heroes = await HeroModel.findByRole(roleId); + let skins = await SkinModel.findbyRole(roleId); + let artifacts = await ArtifactModel.findbyRole(roleId); + + await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); + return resResult(STATUS.SUCCESS); + } + + + async clearRank(msg: { roleId: string }, session: BackendSession) { + let { roleId } = msg; + let role = await RoleModel.findByRoleId(roleId); + if(!role) return resResult(STATUS.WRONG_PARMS); + if(role.blockType != 2) return resResult(STATUS.GM_CANNOT_CLEAR_RANK) + let { serverId } = role; + + await redisClient().zremAsync(new KeyName(REDIS_KEY.TOWER_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.LADDER, { serverId }).getName(), roleId); + await LadderMatchModel.updateByRoleId(roleId, { rank: 0 }); + await redisClient().zremAsync(new KeyName(REDIS_KEY.TOP_LINEUP_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.TOP_HERO_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.HERO_NUM_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.SUM_CE_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.USER_LV, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.MAIN_RANK, { serverId }).getName(), roleId); + await redisClient().zremAsync(new KeyName(REDIS_KEY.MAIN_ELITE_RANK, { serverId }).getName(), roleId); + + let keys = await redisClient().keysAsync(REDIS_KEY.PVP_RANK); + for(let key of keys) await redisClient().zremAsync(key, roleId); + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/gm/handler/gmServerHandler.ts b/game-server/app/servers/gm/handler/gmServerHandler.ts index b78a5f7cc..263e17cb9 100644 --- a/game-server/app/servers/gm/handler/gmServerHandler.ts +++ b/game-server/app/servers/gm/handler/gmServerHandler.ts @@ -1,271 +1,272 @@ -import { Application, BackendSession, pinus } from 'pinus'; -import { genCode, getRandSingleEelm, isTimestamp, resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { UpdateHiddenDataParam, CreatePvpConfigParam, CreateServerParam, UpdateRegionParams, CreateServersParam } from '../../../domain/backEndField/params'; -import { RegionModel, RegionType } from '../../../db/Region'; -import { getDicServerName } from '../../../pubUtils/data'; -import { Maintenance, ServerlistModel, ServerlistUpdate } from '../../../db/Serverlist'; -import { nowSeconds, getFutureTime, getPastTime } from '../../../pubUtils/timeUtil'; -import { calHiddenData } from '../../../services/gmService'; -import { isNumber } from 'util'; -import { MarqueeModel } from '../../../db/Marquee'; -import { setApiIsCloseToRemote } from '../../../services/chatService'; -import { PVPConfigModel } from '../../../db/PvpConfig'; -import { HiddenDataByIdModel, HiddenDataByIdModelTypeParam } from '../../../db/HiddenDataById'; -import { isDevelopEnv } from '../../../services/utilService'; -import { redisClient } from "../../../services/redisService"; -import { REDIS_KEY } from "../../../consts"; -import { createNewServer } from '../../../services/serverService'; - -export default function (app: Application) { - return new GmHandler(app); -} - -export class GmHandler { - constructor(private app: Application) { - } - - // 保存大区配置 - async saveRegionConf(msg: UpdateRegionParams, session: BackendSession) { - let params = new UpdateRegionParams(msg); - let uid = session.get('uid'); - if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); - let region: RegionType; - if(params.id == 'new') { - let update = params.getUpdateParam(); - region = await RegionModel.createNewRegion(update, uid); - } else { - let oldRegion = await RegionModel.findRegionById(params.id); - if(!oldRegion) return resResult(STATUS.WRONG_PARMS); - let update = params.getUpdateParam(oldRegion); - region = await RegionModel.updateRegion(params.id, update, uid); - } - - return resResult(STATUS.SUCCESS); - } - - // 手动开服 - async createNewServer(msg: CreateServersParam, session: BackendSession) { - if(isNumber(msg.openTime)) return resResult(STATUS.WRONG_PARMS, '请刷新后使用新后台页面'); - let params = new CreateServersParam(msg); - let uid = session.get('uid'); - if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); - - console.log('*******', params); - let curRegion = await RegionModel.findRegionByEnv(params.env); - console.log('******* curRegion', curRegion); - if(!curRegion) return resResult(STATUS.WRONG_PARMS); - msg.openTime.sort() - let { latestServer = 0, env } = curRegion; - for(let openTime of msg.openTime) { - let dic = getDicServerName(env, latestServer + 1); - if(!dic) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - await createNewServer(curRegion, latestServer + 1, new CreateServerParam({...params, openTime}), uid); - latestServer++; - } - return resResult(STATUS.SUCCESS); - } - - // 开始维护 - async startMaintenance(msg: { id: number, startTime: number, endTime: number, hasNotify: boolean, version: string }, session: BackendSession) { - const { id, startTime, endTime, hasNotify, version } = msg; - if(!id || !isNumber(startTime) || !isNumber(endTime)) return resResult(STATUS.WRONG_PARMS); - if(endTime < nowSeconds()) return resResult(STATUS.WRONG_PARMS, '结束时间不能比现在早'); - const uid = session.get('uid'); - let server = await ServerlistModel.findByServerId(id); - if(server && server.maintenance) { - await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(server.maintenance.batchCode, [server.id]); - } - - let newMaintenance: Maintenance = { batchCode: genCode(10), startTime, endTime, hasNotify, isOpen: true, version } - server = await ServerlistModel.updateByServerId(id, { maintenance: newMaintenance }); - await pinus.app.rpc.systimer.systimerRemote.initMaintenance.broadcast([server]); - - return resResult(STATUS.SUCCESS,); - } - - // 大区一起维护 - async startRegionMaintenance(msg: { startTime: number, endTime: number, hasNotify: boolean, version: string }, session: BackendSession) { - const { startTime, endTime, hasNotify, version } = msg; - if(!isNumber(startTime) || !isNumber(endTime)) return resResult(STATUS.WRONG_PARMS); - if(endTime < nowSeconds()) return resResult(STATUS.WRONG_PARMS, '结束时间不能比现在早'); - const uid = session.get('uid'); - let newMaintenance: Maintenance = { batchCode: genCode(10), startTime, endTime, hasNotify, isOpen: true, version } - let servers = await ServerlistModel.findByEnv(this.app.get('env')); - let serverIdsOfBatchCode = new Map(); - let serverIds: number[] = []; - for(let server of servers) { - if(server.maintenance) { - let { batchCode } = server.maintenance; - if(!serverIdsOfBatchCode.has(batchCode)) { - serverIdsOfBatchCode.set(batchCode, []); - } - serverIdsOfBatchCode.get(batchCode).push(server.id); - } - serverIds.push(server.id); - } - for(let [ batchCode, serverIds ] of serverIdsOfBatchCode) { - await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(batchCode, serverIds); - } - - await ServerlistModel.updateByServerIds(serverIds, { maintenance: newMaintenance }); - servers = await ServerlistModel.findByEnv(this.app.get('env')); - await pinus.app.rpc.systimer.systimerRemote.initMaintenance.broadcast(servers.map(server => ({...server, maintenance: newMaintenance }))); - - return resResult(STATUS.SUCCESS,); - } - - // 提前结束维护 - async stopMaintenance(msg: { id: number }, session: BackendSession) { - const { id } = msg; - const uid = session.get('uid'); - let server = await ServerlistModel.findByServerId(id); - let maintenance = server.maintenance; - if(maintenance) { - // 更新serverlist上的status - await ServerlistModel.updateByServerId(server.id, { 'maintenance.isOpen': false } as ServerlistUpdate); - - // console.log('&&&', server, server.id) - await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(maintenance.batchCode, [server.id]); - } - - return resResult(STATUS.SUCCESS,); - } - - // 大区一起结束维护 - async stopRegionMaintenance(msg: {}, session: BackendSession) { - const { } = msg; - const uid = session.get('uid'); - let servers = await ServerlistModel.findByEnv(this.app.get('env')); - let serverIdsOfBatchCode = new Map(); - let serverIds: number[] = []; - for(let server of servers) { - if(server.maintenance) { - let { batchCode } = server.maintenance; - if(!serverIdsOfBatchCode.has(batchCode)) { - serverIdsOfBatchCode.set(batchCode, []); - } - serverIdsOfBatchCode.get(batchCode).push(server.id); - serverIds.push(server.id); - } - } - - for(let [ batchCode, serverIds ] of serverIdsOfBatchCode) { - await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(batchCode, serverIds); - } - // 更新serverlist上的status - await ServerlistModel.updateByServerIds(serverIds, { 'maintenance.isOpen': false } as ServerlistUpdate); - - return resResult(STATUS.SUCCESS,); - } - - async sendMarquee(msg: { code: string }, session: BackendSession) { - const { code } = msg; - let marquee = await MarqueeModel.findByCode(code); - if(!marquee) return resResult(STATUS.DB_DATA_NOT_FOUND); - - await MarqueeModel.updateData(code, { isEnable: true }); - let result = await this.app.rpc.systimer.systimerRemote.setMarquee.broadcast(marquee); - if (!result) return resResult(STATUS.GM_MARQUEE_ERR); - return resResult(STATUS.SUCCESS); - } - - async cancelMarquee(msg: { code: string }, session: BackendSession) { - const { code } = msg; - await MarqueeModel.updateData(code, { isEnable: false }); - let result = await this.app.rpc.systimer.systimerRemote.cancelMarquee.broadcast(code); - if (!result) return resResult(STATUS.GM_MARQUEE_CANCEL_ERR); - return resResult(STATUS.SUCCESS); - } - - async setApiIsClose(msg: { isCloseApi: boolean }, session: BackendSession) { - const { isCloseApi } = msg; - let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); - if(!region) return resResult(STATUS.SERVER_NOT_FOUND); - - region = await RegionModel.updateRegion(region.id, { isCloseApi }); - setApiIsCloseToRemote(region.isCloseApi); - return resResult(STATUS.SUCCESS); - } - - async savePvpConfig(msg: CreatePvpConfigParam, session: BackendSession) { - let params = new CreatePvpConfigParam(msg); - if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); - if(params.seasonStartTime >= params.seasonEndTime) return resResult(STATUS.WRONG_PARMS, null, '开始时间不可晚于结束时间'); - if(params.seasonEndTime >= params.seasonRewardTime) return resResult(STATUS.WRONG_PARMS, null, '结束时间不可晚于奖励时间'); - - if(await PVPConfigModel.checkTime(params.seasonNum, params.seasonStartTime, params.seasonRewardTime)) { - return resResult(STATUS.WRONG_PARMS, null, '不可与其他赛季时间重叠'); - } - - let uid = session.get('uid'); - await PVPConfigModel.createPVPConfig(params.seasonNum, params.getUpdateParam(), uid); - pinus.app.rpc.systimer.systimerRemote.setPvpSeasonSchedule.broadcast(true); - - return resResult(STATUS.SUCCESS); - } - - async initHiddenData(msg: {pubArr: number[], hideArr: number[], type: number}, session: BackendSession) { - let { pubArr = [], hideArr = [], type } = msg; - let uid = session.get('uid'); - let datas = await HiddenDataByIdModel.findExistData(type); - let existIds = datas.map(cur => cur.id); - let insertParam: HiddenDataByIdModelTypeParam[] = []; - for(let id of pubArr) { - if(existIds.indexOf(id) == -1) { - insertParam.push({ type, id, publishTime: getPastTime(), createdBy: uid, updatedBy: uid }); - } - } - for(let id of hideArr) { - if(existIds.indexOf(id) == -1) { - insertParam.push({ type, id, publishTime: getFutureTime(), createdBy: uid, updatedBy: uid }); - } - } - await HiddenDataByIdModel.createDatas(insertParam); - await calHiddenData(uid); - await pinus.app.rpc.systimer.systimerRemote.gmSetHiddenDataSchedule.broadcast(); - - return resResult(STATUS.SUCCESS); - } - - async saveHiddenData(msg: UpdateHiddenDataParam, session: BackendSession) { - let params = new UpdateHiddenDataParam(msg); - if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); - let uid = session.get('uid'); - let heroes: number[] = [], goods: number[] = []; - for(let {type, id} of params.arr) { - if(type == 1) heroes.push(id); - if(type == 2) goods.push(id); - } - if(!isDevelopEnv()) { - if(!await HiddenDataByIdModel.checkById(1, heroes, params.publishTime) || !await HiddenDataByIdModel.checkById(2, goods, params.publishTime)) { - return resResult(STATUS.GM_OLD_REF_TIME_ERR); - } - } - for(let {type, id} of params.arr) { - await HiddenDataByIdModel.updateData(type, id, params.publishTime, uid); - } - await calHiddenData(uid); - await pinus.app.rpc.systimer.systimerRemote.gmSetHiddenDataSchedule.broadcast(); - return resResult(STATUS.SUCCESS); - } - - async setServerOpenTime(msg: { serverId: number, serverOpenTime: number }, session: BackendSession) { - let { serverId, serverOpenTime } = msg; - if(!isTimestamp(serverOpenTime)) return resResult(STATUS.WRONG_PARMS); - let server = await ServerlistModel.findByServerId(serverId); - if(!server) return resResult(STATUS.WRONG_PARMS); - - let region = await RegionModel.findRegionById(server.regionId); - if(!region) return resResult(STATUS.WRONG_PARMS); - - server = await ServerlistModel.updateByServerId(serverId, { openTime: serverOpenTime }); - if(server.id == region.latestServerUniqId) { - region = await RegionModel.updateRegion(server.regionId, { latestServerOpenTime: server.openTime }) - } - - await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${server.id}`, `${server.openTime}`); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, pinus } from 'pinus'; +import { genCode, getRandSingleEelm, isTimestamp, resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { UpdateHiddenDataParam, CreatePvpConfigParam, CreateServerParam, UpdateRegionParams, CreateServersParam } from '@domain/backEndField/params'; +import { RegionModel, RegionType } from '@db/Region'; +import { getDicServerName } from '@pubUtils/data'; +import { Maintenance, ServerlistModel, ServerlistUpdate } from '@db/Serverlist'; +import { nowSeconds, getFutureTime, getPastTime } from '@pubUtils/timeUtil'; +import { calHiddenData } from '../../../services/gmService'; +import { isNumber } from 'util'; +import { MarqueeModel } from '@db/Marquee'; +import { setApiIsCloseToRemote } from '../../../services/chatService'; +import { PVPConfigModel } from '@db/PvpConfig'; +import { HiddenDataByIdModel, HiddenDataByIdModelTypeParam } from '@db/HiddenDataById'; +import { isDevelopEnv } from '../../../services/utilService'; +import { redisClient } from "../../../services/redisService"; +import { REDIS_KEY } from "../../../consts"; +import { createNewServer } from '../../../services/serverService'; + +export default function (app: Application) { + return new GmHandler(app); +} + +export class GmHandler { + constructor(private app: Application) { + } + + // 保存大区配置 + async saveRegionConf(msg: UpdateRegionParams, session: BackendSession) { + let params = new UpdateRegionParams(msg); + let uid = session.get('uid'); + if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); + let region: RegionType; + if(params.id == 'new') { + let update = params.getUpdateParam(); + region = await RegionModel.createNewRegion(update, uid); + } else { + let oldRegion = await RegionModel.findRegionById(params.id); + if(!oldRegion) return resResult(STATUS.WRONG_PARMS); + let update = params.getUpdateParam(oldRegion); + region = await RegionModel.updateRegion(params.id, update, uid); + } + + return resResult(STATUS.SUCCESS); + } + + // 手动开服 + async createNewServer(msg: CreateServersParam, session: BackendSession) { + if(isNumber(msg.openTime)) return resResult(STATUS.WRONG_PARMS, '请刷新后使用新后台页面'); + let params = new CreateServersParam(msg); + let uid = session.get('uid'); + if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); + + console.log('*******', params); + let curRegion = await RegionModel.findRegionByEnv(params.env); + console.log('******* curRegion', curRegion); + if(!curRegion) return resResult(STATUS.WRONG_PARMS); + msg.openTime.sort() + let { latestServer = 0, env } = curRegion; + for(let openTime of msg.openTime) { + let dic = getDicServerName(env, latestServer + 1); + if(!dic) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + await createNewServer(curRegion, latestServer + 1, new CreateServerParam({...params, openTime}), uid); + latestServer++; + } + return resResult(STATUS.SUCCESS); + } + + // 开始维护 + async startMaintenance(msg: { id: number, startTime: number, endTime: number, hasNotify: boolean, version: string }, session: BackendSession) { + const { id, startTime, endTime, hasNotify, version } = msg; + if(!id || !isNumber(startTime) || !isNumber(endTime)) return resResult(STATUS.WRONG_PARMS); + if(endTime < nowSeconds()) return resResult(STATUS.WRONG_PARMS, '结束时间不能比现在早'); + const uid = session.get('uid'); + let server = await ServerlistModel.findByServerId(id); + if(server && server.maintenance) { + await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(server.maintenance.batchCode, [server.id]); + } + + let newMaintenance: Maintenance = { batchCode: genCode(10), startTime, endTime, hasNotify, isOpen: true, version } + server = await ServerlistModel.updateByServerId(id, { maintenance: newMaintenance }); + await pinus.app.rpc.systimer.systimerRemote.initMaintenance.broadcast([server]); + + return resResult(STATUS.SUCCESS,); + } + + // 大区一起维护 + async startRegionMaintenance(msg: { startTime: number, endTime: number, hasNotify: boolean, version: string }, session: BackendSession) { + const { startTime, endTime, hasNotify, version } = msg; + if(!isNumber(startTime) || !isNumber(endTime)) return resResult(STATUS.WRONG_PARMS); + if(endTime < nowSeconds()) return resResult(STATUS.WRONG_PARMS, '结束时间不能比现在早'); + const uid = session.get('uid'); + let newMaintenance: Maintenance = { batchCode: genCode(10), startTime, endTime, hasNotify, isOpen: true, version } + let servers = await ServerlistModel.findByEnv(this.app.get('env')); + let serverIdsOfBatchCode = new Map(); + let serverIds: number[] = []; + for(let server of servers) { + if(server.maintenance) { + let { batchCode } = server.maintenance; + if(!serverIdsOfBatchCode.has(batchCode)) { + serverIdsOfBatchCode.set(batchCode, []); + } + serverIdsOfBatchCode.get(batchCode).push(server.id); + } + serverIds.push(server.id); + } + for(let [ batchCode, serverIds ] of serverIdsOfBatchCode) { + await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(batchCode, serverIds); + } + + await ServerlistModel.updateByServerIds(serverIds, { maintenance: newMaintenance }); + servers = await ServerlistModel.findByEnv(this.app.get('env')); + await pinus.app.rpc.systimer.systimerRemote.initMaintenance.broadcast(servers.map(server => ({...server, maintenance: newMaintenance }))); + + return resResult(STATUS.SUCCESS,); + } + + // 提前结束维护 + async stopMaintenance(msg: { id: number }, session: BackendSession) { + const { id } = msg; + const uid = session.get('uid'); + let server = await ServerlistModel.findByServerId(id); + let maintenance = server.maintenance; + if(maintenance) { + // 更新serverlist上的status + await ServerlistModel.updateByServerId(server.id, { 'maintenance.isOpen': false } as ServerlistUpdate); + + // console.log('&&&', server, server.id) + await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(maintenance.batchCode, [server.id]); + } + + return resResult(STATUS.SUCCESS,); + } + + // 大区一起结束维护 + async stopRegionMaintenance(msg: {}, session: BackendSession) { + const { } = msg; + const uid = session.get('uid'); + let servers = await ServerlistModel.findByEnv(this.app.get('env')); + let serverIdsOfBatchCode = new Map(); + let serverIds: number[] = []; + for(let server of servers) { + if(server.maintenance) { + let { batchCode } = server.maintenance; + if(!serverIdsOfBatchCode.has(batchCode)) { + serverIdsOfBatchCode.set(batchCode, []); + } + serverIdsOfBatchCode.get(batchCode).push(server.id); + serverIds.push(server.id); + } + } + + for(let [ batchCode, serverIds ] of serverIdsOfBatchCode) { + await pinus.app.rpc.systimer.systimerRemote.stopMaintenance.broadcast(batchCode, serverIds); + } + // 更新serverlist上的status + await ServerlistModel.updateByServerIds(serverIds, { 'maintenance.isOpen': false } as ServerlistUpdate); + + return resResult(STATUS.SUCCESS,); + } + + async sendMarquee(msg: { code: string }, session: BackendSession) { + const { code } = msg; + let marquee = await MarqueeModel.findByCode(code); + if(!marquee) return resResult(STATUS.DB_DATA_NOT_FOUND); + + await MarqueeModel.updateData(code, { isEnable: true }); + let result = await this.app.rpc.systimer.systimerRemote.setMarquee.broadcast(marquee); + if (!result) return resResult(STATUS.GM_MARQUEE_ERR); + return resResult(STATUS.SUCCESS); + } + + async cancelMarquee(msg: { code: string }, session: BackendSession) { + const { code } = msg; + await MarqueeModel.updateData(code, { isEnable: false }); + let result = await this.app.rpc.systimer.systimerRemote.cancelMarquee.broadcast(code); + if (!result) return resResult(STATUS.GM_MARQUEE_CANCEL_ERR); + return resResult(STATUS.SUCCESS); + } + + async setApiIsClose(msg: { isCloseApi: boolean }, session: BackendSession) { + const { isCloseApi } = msg; + let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); + if(!region) return resResult(STATUS.SERVER_NOT_FOUND); + + region = await RegionModel.updateRegion(region.id, { isCloseApi }); + setApiIsCloseToRemote(region.isCloseApi); + return resResult(STATUS.SUCCESS); + } + + async savePvpConfig(msg: CreatePvpConfigParam, session: BackendSession) { + let params = new CreatePvpConfigParam(msg); + if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); + if(params.seasonStartTime >= params.seasonEndTime) return resResult(STATUS.WRONG_PARMS, null, '开始时间不可晚于结束时间'); + if(params.seasonEndTime >= params.seasonRewardTime) return resResult(STATUS.WRONG_PARMS, null, '结束时间不可晚于奖励时间'); + + if(await PVPConfigModel.checkTime(params.seasonNum, params.seasonStartTime, params.seasonRewardTime)) { + return resResult(STATUS.WRONG_PARMS, null, '不可与其他赛季时间重叠'); + } + + let uid = session.get('uid'); + await PVPConfigModel.createPVPConfig(params.seasonNum, params.getUpdateParam(), uid); + pinus.app.rpc.systimer.systimerRemote.setPvpSeasonSchedule.broadcast(true); + + return resResult(STATUS.SUCCESS); + } + + async initHiddenData(msg: {pubArr: number[], hideArr: number[], type: number}, session: BackendSession) { + let { pubArr = [], hideArr = [], type } = msg; + let uid = session.get('uid'); + let datas = await HiddenDataByIdModel.findExistData(type); + let existIds = datas.map(cur => cur.id); + let insertParam: HiddenDataByIdModelTypeParam[] = []; + for(let id of pubArr) { + if(existIds.indexOf(id) == -1) { + insertParam.push({ type, id, publishTime: getPastTime(), createdBy: uid, updatedBy: uid }); + } + } + for(let id of hideArr) { + if(existIds.indexOf(id) == -1) { + insertParam.push({ type, id, publishTime: getFutureTime(), createdBy: uid, updatedBy: uid }); + } + } + await HiddenDataByIdModel.createDatas(insertParam); + await calHiddenData(uid); + await pinus.app.rpc.systimer.systimerRemote.gmSetHiddenDataSchedule.broadcast(); + + return resResult(STATUS.SUCCESS); + } + + async saveHiddenData(msg: UpdateHiddenDataParam, session: BackendSession) { + let params = new UpdateHiddenDataParam(msg); + if(!params.checkParams()) return resResult(STATUS.WRONG_PARMS); + let uid = session.get('uid'); + let heroes: number[] = [], goods: number[] = []; + for(let {type, id} of params.arr) { + if(type == 1) heroes.push(id); + if(type == 2) goods.push(id); + } + if(!isDevelopEnv()) { + if(!await HiddenDataByIdModel.checkById(1, heroes, params.publishTime) || !await HiddenDataByIdModel.checkById(2, goods, params.publishTime)) { + return resResult(STATUS.GM_OLD_REF_TIME_ERR); + } + } + for(let {type, id} of params.arr) { + await HiddenDataByIdModel.updateData(type, id, params.publishTime, uid); + } + await calHiddenData(uid); + await pinus.app.rpc.systimer.systimerRemote.gmSetHiddenDataSchedule.broadcast(); + return resResult(STATUS.SUCCESS); + } + + async setServerOpenTime(msg: { serverId: number, serverOpenTime: number }, session: BackendSession) { + let { serverId, serverOpenTime } = msg; + if(!isTimestamp(serverOpenTime)) return resResult(STATUS.WRONG_PARMS); + let server = await ServerlistModel.findByServerId(serverId); + if(!server) return resResult(STATUS.WRONG_PARMS); + + let region = await RegionModel.findRegionById(server.regionId); + if(!region) return resResult(STATUS.WRONG_PARMS); + + server = await ServerlistModel.updateByServerId(serverId, { openTime: serverOpenTime }); + if(server.id == region.latestServerUniqId) { + region = await RegionModel.updateRegion(server.regionId, { latestServerOpenTime: server.openTime }) + } + + await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${server.id}`, `${server.openTime}`); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/gm/remote/gmRemote.ts b/game-server/app/servers/gm/remote/gmRemote.ts index 7f7a80f5b..77f780a37 100644 --- a/game-server/app/servers/gm/remote/gmRemote.ts +++ b/game-server/app/servers/gm/remote/gmRemote.ts @@ -1,85 +1,86 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { setServerGroup } from '../../../services/serverService'; -import { errlogger } from '../../../util/logger'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GMRemote(app); -} - -// rpc 定义挪到单独的定义文件(user.rpc.define.ts)。解决ts-node 有可能找不到定义的问题。 -// 你也可以用其它方法解决,或者没有遇到过这个问题的话,定义还是可以放在这里。 - -// UserRpc的命名空间自动合并 -// declare global { -// interface UserRpc { -// chat: { -// GMRemote: RemoterClass; -// }; -// } -// } -export class GMRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - await setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { setServerGroup } from '../../../services/serverService'; +import { errlogger } from '../../../util/logger'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import { gameData, reloadResources } from '@pubUtils/data'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GMRemote(app); +} + +// rpc 定义挪到单独的定义文件(user.rpc.define.ts)。解决ts-node 有可能找不到定义的问题。 +// 你也可以用其它方法解决,或者没有遇到过这个问题的话,定义还是可以放在这里。 + +// UserRpc的命名空间自动合并 +// declare global { +// interface UserRpc { +// chat: { +// GMRemote: RemoterClass; +// }; +// } +// } +export class GMRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + await setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/guild/filter/guildAuthFilter.ts b/game-server/app/servers/guild/filter/guildAuthFilter.ts index 3c57266fd..4dcf42cde 100644 --- a/game-server/app/servers/guild/filter/guildAuthFilter.ts +++ b/game-server/app/servers/guild/filter/guildAuthFilter.ts @@ -1,68 +1,69 @@ -import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback } from "pinus"; -import { resResult } from "../../../pubUtils/util"; -import { GUILD_AUTH_CHECK_TYPE, GUILD_OPERATE, GUILD_ROUTE_TO_OPERATE, STATUS } from "../../../consts"; -import { UserGuildModel, UserGuildType } from "../../../db/UserGuild"; -import { checkAuth, setUserGuildSession } from "../../../services/guildService"; - -export function guildAuthFilter(app: Application) { - return new Filter(app); -} - -var Filter = function(this: any, app: Application) { - this.app = app; -}; - -Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { - const roleId: string = session.get('roleId'); - let guildCode: string = session.get('guildCode'); - let guildAuth: number = session.get('guildAuth'); - // console.log('********guildAuth', guildAuth); - - const { code, roleId: hisRoleId } = msg; - - let route = routeRecord.route; - if(GUILD_ROUTE_TO_OPERATE.has(route)) { - let myUserGuild: UserGuildType; - let hisUserGuild: UserGuildType; - - if(!guildAuth) { - myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); - if(myUserGuild) { - guildCode = myUserGuild.guildCode; - guildAuth = myUserGuild.auth; - } - setUserGuildSession(session, myUserGuild); - } - - let arr = GUILD_ROUTE_TO_OPERATE.get(route); - for(let { operate, type } of arr) { - if( type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF) { - myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); - const checkResult = await checkAuth(operate, code||guildCode, guildAuth); - if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); - } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF_IF_EXIST) { - if(!!guildCode) { - myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); - const checkResult = await checkAuth(operate, code||guildCode, guildAuth); - if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); - } - } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_OTHERS) { - hisUserGuild = await UserGuildModel.getMyGuild(hisRoleId, 'auth guildCode job'); - const checkResult = await checkAuth(operate, code||guildCode, hisUserGuild?.auth); - if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); - } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF_WITH_SESSION) { - const checkResult = await checkAuth(operate, code||guildCode, guildAuth); - if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); - } - } - - msg.myUserGuild = myUserGuild; - msg.hisUserGuild = hisUserGuild; - } - - next(null); -}; - -Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { - next(err); -}; \ No newline at end of file +import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback } from "pinus"; +import { resResult } from "@pubUtils/util"; +import { GUILD_AUTH_CHECK_TYPE, GUILD_OPERATE, GUILD_ROUTE_TO_OPERATE, STATUS } from "@consts"; +import { UserGuildModel, UserGuildType } from "@db/UserGuild"; +import { checkAuth, setUserGuildSession } from "@pubUtils/guildService"; + +export function guildAuthFilter(app: Application) { + return new Filter(app); +} + +var Filter = function(this: any, app: Application) { + this.app = app; +}; + +Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) { + const roleId: string = session.get('roleId'); + let guildCode: string = session.get('guildCode'); + let guildAuth: number = session.get('guildAuth'); + // console.log('********guildAuth', guildAuth); + + const { code, roleId: hisRoleId } = msg; + + let route = routeRecord.route; + if(GUILD_ROUTE_TO_OPERATE.has(route)) { + let myUserGuild: UserGuildType; + let hisUserGuild: UserGuildType; + + if(!guildAuth) { + myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); + if(myUserGuild) { + guildCode = myUserGuild.guildCode; + guildAuth = myUserGuild.auth; + } + setUserGuildSession(session, myUserGuild); + } + + let arr = GUILD_ROUTE_TO_OPERATE.get(route); + for(let { operate, type } of arr) { + if( type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF) { + myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); + const checkResult = await checkAuth(operate, code||guildCode, guildAuth); + if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); + } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF_IF_EXIST) { + if(!!guildCode) { + myUserGuild = await UserGuildModel.getMyGuild(roleId, '+refTimeDaily'); + const checkResult = await checkAuth(operate, code||guildCode, guildAuth); + if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); + } + } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_OTHERS) { + hisUserGuild = await UserGuildModel.getMyGuild(hisRoleId, 'auth guildCode job'); + const checkResult = await checkAuth(operate, code||guildCode, hisUserGuild?.auth); + if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); + } else if (type == GUILD_AUTH_CHECK_TYPE.CHECK_SELF_WITH_SESSION) { + const checkResult = await checkAuth(operate, code||guildCode, guildAuth); + if (!checkResult) return next(new Error(), resResult(STATUS.GUILD_AUTH_NOT_ENOUGH)); + } + } + + msg.myUserGuild = myUserGuild; + msg.hisUserGuild = hisUserGuild; + } + + next(null); +}; + +Filter.prototype.after = function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) { + next(err); +}; + diff --git a/game-server/app/servers/guild/handler/auctionHandler.ts b/game-server/app/servers/guild/handler/auctionHandler.ts index c5f5081c4..4851db2da 100644 --- a/game-server/app/servers/guild/handler/auctionHandler.ts +++ b/game-server/app/servers/guild/handler/auctionHandler.ts @@ -1,399 +1,400 @@ -import { DividendModel, DividendType } from './../../../db/Dividend'; -import { Application, BackendSession, ChannelService, HandlerService, pinus, } from "pinus"; -import { AUCTION_STAGE, DEBUG_MAGIC_WORD, STATUS, CURRENCY_BY_TYPE, CURRENCY_TYPE, DATA_NAME, LOT_STATUS, CHANNEL_PREFIX, MAIL_TYPE, ITEM_CHANGE_REASON, TA_EVENT, ROLE_RECEIVE_STATUS, PUSH_ROUTE, AUCTION_BID_EXTEND_TIME } from "../../../consts"; -import { LotModel, LotParam } from "../../../db/Lot"; -import { ItemReward } from "../../../domain/dbGeneral"; -import { genCode, resResult } from "../../../pubUtils/util"; -import { auctionStage, calculateDividend, genAuction, sendUngotDividend, startGuildAuction, startWorldAuction, stopAuction, todayGuildBegin, getBasePrice, debugAuctionLots, officialAuctionLots, auctionBidStatus, getMaxPrice, guildBidStatus, getAuction, pushAuctionOver, pushAuctionUpdate, processDividendFormat, processSingleDividendFormat, tomorrowGuildBegin, processLotsFormat, processSingleLotFormat, getAuctionRewardByPoolId, getLotStatus, extendLotTime } from "../../../services/auctionService"; -import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { getSimpleRoleInfo } from '../../../services/roleService'; -import { getRoleOnlineInfo } from '../../../services/redisService'; -import { lockData } from '../../../services/redLockService'; -import { GuildModel } from '../../../db/Guild'; -import { RoleModel, RoleType } from '../../../db/Role'; -import { openGuildRefine } from '../../../services/guildRefineService'; -import { unlockTrain } from '../../../services/guildTrainService'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { UserGuildApplyModel } from '../../../db/UserGuildApply'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { gameData } from '../../../pubUtils/data'; -import { sendMailByContent } from '../../../services/mailService'; -import { reportTAEvent } from '../../../services/sdkService'; -import { sendMessageToGuildWithSuc, sendMessageToServerWithSuc } from '../../../services/pushService'; -import { LOTS_KEEP_TO_WORLD_CNT } from '../../../consts'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new AuctionHandler(app); -} - -export class AuctionHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - async getAuction(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - - const guildCode = session.get('guildCode'); - let result = await getAuction(guildCode, session, magicWord); - - return resResult(STATUS.SUCCESS, result); - } - - async leaveAuction(msg: {}, session: BackendSession) { - return resResult(STATUS.SUCCESS); - } - - - async offer(msg: { code: string, max: boolean, auctionStage: number, magicWord: string }, session: BackendSession) { - const { code, max, auctionStage, magicWord } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const ip = session.get('ip'); - let res: any = await lockData(serverId, DATA_NAME.AUCTION_LOT, '');// 加锁 - - try { - if (!!res.err) { - return resResult(STATUS.REDLOCK_ERR); - } - - const lot = await LotModel.findLot(code); - if (!lot) { - res.releaseCallback(); - return resResult(STATUS.GUILD_LOT_NOT_FOUND); - } - if (lot.status === LOT_STATUS.SOLD || lot.status === LOT_STATUS.MAX) { - res.releaseCallback(); - return resResult(STATUS.GUILD_LOT_HAS_SOLD); - } - - if (auctionStage === AUCTION_STAGE.GUILD && lot.guildCode !== guildCode) { - res.releaseCallback(); - return resResult(STATUS.AUCTION_GUILD_MEMBER_ONLY); - } - - let { curBuyer, curPrice, prePrice, maxPrice, gid, count, bidRoles, watchingRoles, seq, begin, auctionStage: lotAuctionStage } = lot; - if (auctionStage != lotAuctionStage) { - res.releaseCallback(); - return resResult(STATUS.AUCITON_STAGE_ERR); - } - - if (curBuyer === roleId && !max) { - res.releaseCallback(); - return resResult(STATUS.LOT_OFFER_SERIAL); - } - let newPrice = Math.floor(curPrice * dicParam.GUILD_AUCTION.AUCTION_PRICE_RISE); - let maxFlag = max; - if (maxFlag) { - curPrice = maxPrice; - } - if (curPrice >= maxPrice) { - curPrice = maxPrice; - newPrice = maxPrice; - maxFlag = true; - } - if(newPrice > maxPrice) { - newPrice = maxPrice; - } - - const costRes = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: curPrice }], ITEM_CHANGE_REASON.AUCTION_OFFER); - if (!costRes) { - res.releaseCallback(); - return resResult(STATUS.ROLE_COIN_NOT_ENOUGH); - } - - bidRoles.push({ roleId, price: newPrice, time: new Date() }); - let lotStatus = await getLotStatus(auctionStage, max, maxFlag) - let update: LotParam = { code, curBuyer: roleId, curPrice: newPrice, auctionStage, prePrice: curPrice, bidRoles, status: lotStatus, watchingRoles: Array.from(new Set([...watchingRoles, roleId])), seq: 0 }; - if(lotStatus == LOT_STATUS.BIDDING) update.end = new Date(Date.now() + AUCTION_BID_EXTEND_TIME * 1000); - const newLot = await LotModel.updateLot(update); - if(!newLot) { - // 如果拍卖行状态不对,那回退handleCost - if (curBuyer && prePrice > 0) { - await sendMailByContent(MAIL_TYPE.AUCTION_OVER, roleId, { goods: [getGoldObject(curPrice)] }); - } - res.releaseCallback(); - return resResult(STATUS.GUILD_LOT_HAS_SOLD); - } else { - if (curBuyer && prePrice > 0) { - await sendMailByContent(MAIL_TYPE.AUCTION_OVER, curBuyer, { goods: [getGoldObject(prePrice)] }); - } - - if (maxFlag) { - newPrice = maxPrice; - await sendMailByContent(MAIL_TYPE.AUTION_REWARD, roleId, { goods: [{ id: gid, count }] }); - let dicGoods = gameData.goods.get(gid); - reportTAEvent(roleId, TA_EVENT.AUCTION_ITEM_GET, { item_name: dicGoods?.name, item_count: count, deel_price: newPrice }, ip); - } - } - await extendLotTime(newLot); - if(seq <= LOTS_KEEP_TO_WORLD_CNT && seq > 0) await LotModel.updateOne({ begin, gid, count, status: LOT_STATUS.DEFAULT, serverId, seq: { $gt: LOTS_KEEP_TO_WORLD_CNT } }, { $set: { seq }}); - await pushAuctionOver(newLot); // 推送竞价超过标志 - res.releaseCallback(); - - const incPrice = curPrice - prePrice > 0? prePrice: 0; - let newDividend: DividendType = null; - if (auctionStage === AUCTION_STAGE.GUILD) { - const dividend = await DividendModel.updateLot(code, gid, curPrice, incPrice, max); - newDividend = await calculateDividend(dividend); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_UPDATE, { dividends: processDividendFormat([newDividend]) }) - } - let newLotResult = processSingleLotFormat(newLot); - return resResult(STATUS.SUCCESS, { lot: newLotResult, dividend: processSingleDividendFormat(newDividend) }); - } catch (e) { - console.log('offer got err:', e); - res.releaseCallback(); - return resResult(STATUS.INTERNAL_ERR); - } - } - - async watchLot(msg: { code: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const { code } = msg; - const lot = await LotModel.watchLot(code, roleId); - if (!lot) return resResult(STATUS.WRONG_PARMS); - return resResult(STATUS.SUCCESS, { lot: processSingleLotFormat(lot) }); - } - - async unWatchLot(msg: { code: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const { code } = msg; - const lot = await LotModel.unWatchLot(code, roleId); - if (!lot) return resResult(STATUS.WRONG_PARMS); - return resResult(STATUS.SUCCESS, { lot: processSingleLotFormat(lot) }); - } - - async checkDividend(msg: {}, session: BackendSession) { - const begin = await todayGuildBegin(); - const tomorrowBegin = await tomorrowGuildBegin(); - const guildCode = session.get('guildCode'); - if(guildCode) { - const dividends = await DividendModel.findGuildDividendsByBegin(guildCode, [begin, tomorrowBegin]); - return resResult(STATUS.SUCCESS, { dividends: processDividendFormat(dividends) }); - } else { - let roleId = session.get('roleId'); - - const dividends = await DividendModel.findDividendByRoleAndBegin(roleId, [begin, tomorrowBegin]); - return resResult(STATUS.SUCCESS, { dividends: processDividendFormat(dividends) }); - } - } - - async getDividend(msg: { code: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const { code } = msg; - const dividendData = await DividendModel.findReadyDividend(code); - if (!dividendData) return resResult(STATUS.DIVIDEND_NOT_READY); - const { dividends } = dividendData; - const dividend = dividends.find(item => { return item.roleId === roleId }); - if (!dividend || dividend.status == ROLE_RECEIVE_STATUS.YES) return resResult(STATUS.DIVIDEND_GUILD_PLAYER_ONLY); - let goods = await addItems(roleId, roleName, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: dividend.total }], ITEM_CHANGE_REASON.AUCTION_DIVIDEND); - await DividendModel.updateReceiveStatus(dividendData.code, roleId); - dividend.status = ROLE_RECEIVE_STATUS.YES; - return resResult(STATUS.SUCCESS, { dividend, goods }); - } - - async myWatching(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const begin = await todayGuildBegin(); - const lots = await LotModel.watchingLotsByBegin(serverId, roleId, begin); - const stage = await auctionStage(); - let newLots = await processLotsFormat(lots); - return resResult(STATUS.SUCCESS, { lots: stage === AUCTION_STAGE.END ? [] : newLots }); - } - - async offerRecs(msg: { count: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const lotsData = await LotModel.recentBidLots(serverId, roleId, msg.count); - const bidRecs = lotsData.map(lot => { - const bidRec = lot.bidRoles.find(role => { return role.roleId === roleId }); - const { gid } = lot; - return { ...bidRec, gid, status: auctionBidStatus(roleId, lot) }; - }).sort((a,b) => b.time.getTime() - a.time.getTime()); - return resResult(STATUS.SUCCESS, { bidRecs }); - } - - async guildLotRecs(msg: { count: number }, session: BackendSession) { - const guildCode = session.get('guildCode'); - const dividends = await DividendModel.findDividendsByGuild(guildCode, msg.count); - let lotsData = []; - dividends.forEach(dividend => { - const lots = dividend.lots.map(lot => { - return { ...lot, sourceType: dividend.sourceType, dividendStatus: dividend.status }; - }) - lotsData = [...lotsData, ...lots]; - }); - const lotRecs = lotsData.map(lot => { - const { gid, count, price: lotPrice } = lot; - // const price = lotPrice === 0 ? getBasePrice(gid, count) : lotPrice; - const sold = guildBidStatus(lot); - return { ...lot, price: lotPrice, sold }; - }).sort((a,b) => b.time.getTime() - a.time.getTime());; - - return resResult(STATUS.SUCCESS, { lotRecs }); - } - - // ! 测试接口 - async debugSetDividendStatus(msg: { magicWord: string, sourceType: number, status: number }, session: BackendSession) { - const { magicWord, sourceType, status } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - const guildCode: string = session.get('guildCode'); - if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND) - const dividend = await DividendModel.updateDividendStatus(guildCode, sourceType, status); - return resResult(STATUS.SUCCESS, { dividend }); - } - - // ! 测试接口 - async debugSetLotStage(msg: { magicWord: string, code: string, auctionStage: number }, session: BackendSession) { - const { magicWord, code, auctionStage } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const lot = await LotModel.updateLotStage(code, auctionStage); - return resResult(STATUS.SUCCESS, { lot }); - } - - // ! 测试接口 - async debugAddLots(msg: { magicWord: string, sourceType: number, sourceCode: string, poolId: number }, session: BackendSession) { - const { magicWord, sourceType, sourceCode, poolId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let guildCode: string = session.get('guildCode'); - const serverId: number = session.get('serverId'); - if (!guildCode) {//创建公会 - const roleId = session.get('roleId'); - const role: RoleType = await RoleModel.findByRoleId(roleId); - // 创建公会 - const name = '测试公会' - const icon = 1 - const notice = '测试公会' - const guild = await GuildModel.createGuild({ guildCode: genCode(6), name, icon, notice }, role, serverId); - if (!guild) return resResult(STATUS.GUILD_CREATE_ERROR); - guild.leader = guild.leader; - //创建科技树 - await openGuildRefine(guild.code); - await unlockTrain(guild.code, 1); - const userGuild = await UserGuildModel.createUserGuild(guild.code, role, true); - if (!userGuild) return resResult(STATUS.GUILD_CREATE_ERROR); - - await RoleModel.joinGuild(roleId, guild.code, guild.name, true); - await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 - guildCode = guild.code; - session.set('guildCode', guildCode); - session.push('guildCode', () => {}); - } - - let rewards = getAuctionRewardByPoolId(poolId); - if(!rewards) return resResult(STATUS.WRONG_PARMS); - const result = await genAuction(guildCode, sourceType, magicWord, serverId, rewards); - if (!result) { - return resResult(STATUS.WRONG_PARMS); - } - - return resResult(STATUS.SUCCESS, result); - } - - // ! 测试接口 - async debugScheduleStartGuild(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const result = await startGuildAuction(); - if (result === true) { - return resResult(STATUS.SUCCESS); - } - return resResult(STATUS.INTERNAL_ERR); - } - - // ! 测试接口 - async debugScheduleStartWorld(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const result = await startWorldAuction(); - if (result === true) { - return resResult(STATUS.SUCCESS); - } - return resResult(STATUS.INTERNAL_ERR); - } - - // ! 测试接口 - async debugScheduleStopAuction(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const result = await stopAuction(); - if (result === true) { - return resResult(STATUS.SUCCESS); - } - return resResult(STATUS.INTERNAL_ERR); - } - - // ! 测试接口 - async debugScheduleSendUngotDividend(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const result = await sendUngotDividend(true); - if (result === true) { - return resResult(STATUS.SUCCESS); - } - return resResult(STATUS.INTERNAL_ERR); - } - - async debugSetPlayTime(msg: { magicWord: string, time: string }, session: BackendSession) { - const { magicWord, time } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let serverId = session.get('serverId'); - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: new Date(time).getTime() }); - - return resResult(STATUS.SUCCESS); - } - - // ! 测试接口 - /** - * 领取分红之前,修改分红数据信息,确保领取分红接口能正常跑通 - * debugSetDividendStatus 和 debugSetDividendStatusV2 区别 - * debugSetDividendStatus: 修改 DividendModel.status - * debugSetDividendStatus: 修改 DividendModel.status 和 DividendModel.dividends.status - * - * @param {{ magicWord: string, sourceType: number, status: number }} msg - * @param {BackendSession} session - * @return {*} - * @memberof AuctionHandler - */ - async debugSetDividendStatusV2(msg: { magicWord: string, sourceType: number, status: number }, session: BackendSession) { - const { magicWord, sourceType, status } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - const guildCode: string = session.get('guildCode'); - if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND) - let dividend = await DividendModel.updateDividendStatus(guildCode, sourceType, status); - dividend.dividends.forEach(item => { - item.status = ROLE_RECEIVE_STATUS.NO - }); - dividend = await DividendModel.updateDividend(dividend.code, { dividends: dividend.dividends }) - return resResult(STATUS.SUCCESS, { dividend }); - } -} +import { DividendModel, DividendType } from './../../../db/Dividend'; +import { Application, BackendSession, ChannelService, HandlerService, pinus, } from "pinus"; +import { AUCTION_STAGE, DEBUG_MAGIC_WORD, STATUS, CURRENCY_BY_TYPE, CURRENCY_TYPE, DATA_NAME, LOT_STATUS, CHANNEL_PREFIX, MAIL_TYPE, ITEM_CHANGE_REASON, TA_EVENT, ROLE_RECEIVE_STATUS, PUSH_ROUTE, AUCTION_BID_EXTEND_TIME } from "../../../consts"; +import { LotModel, LotParam } from "@db/Lot"; +import { ItemReward } from "@domain/dbGeneral"; +import { genCode, resResult } from "@pubUtils/util"; +import { auctionStage, calculateDividend, genAuction, sendUngotDividend, startGuildAuction, startWorldAuction, stopAuction, todayGuildBegin, getBasePrice, debugAuctionLots, officialAuctionLots, auctionBidStatus, getMaxPrice, guildBidStatus, getAuction, pushAuctionOver, pushAuctionUpdate, processDividendFormat, processSingleDividendFormat, tomorrowGuildBegin, processLotsFormat, processSingleLotFormat, getAuctionRewardByPoolId, getLotStatus, extendLotTime } from "../../../services/auctionService"; +import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { getSimpleRoleInfo } from '../../../services/roleService'; +import { getRoleOnlineInfo } from '../../../services/redisService'; +import { lockData } from '../../../services/redLockService'; +import { GuildModel } from '@db/Guild'; +import { RoleModel, RoleType } from '@db/Role'; +import { openGuildRefine } from '../../../services/guildRefineService'; +import { unlockTrain } from '../../../services/guildTrainService'; +import { UserGuildModel } from '@db/UserGuild'; +import { UserGuildApplyModel } from '@db/UserGuildApply'; +import * as dicParam from '@pubUtils/dicParam'; +import { gameData } from '@pubUtils/data'; +import { sendMailByContent } from '../../../services/mailService'; +import { reportTAEvent } from '../../../services/sdkService'; +import { sendMessageToGuildWithSuc, sendMessageToServerWithSuc } from '../../../services/pushService'; +import { LOTS_KEEP_TO_WORLD_CNT } from '../../../consts'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new AuctionHandler(app); +} + +export class AuctionHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + async getAuction(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + + const guildCode = session.get('guildCode'); + let result = await getAuction(guildCode, session, magicWord); + + return resResult(STATUS.SUCCESS, result); + } + + async leaveAuction(msg: {}, session: BackendSession) { + return resResult(STATUS.SUCCESS); + } + + + async offer(msg: { code: string, max: boolean, auctionStage: number, magicWord: string }, session: BackendSession) { + const { code, max, auctionStage, magicWord } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const ip = session.get('ip'); + let res: any = await lockData(serverId, DATA_NAME.AUCTION_LOT, '');// 加锁 + + try { + if (!!res.err) { + return resResult(STATUS.REDLOCK_ERR); + } + + const lot = await LotModel.findLot(code); + if (!lot) { + res.releaseCallback(); + return resResult(STATUS.GUILD_LOT_NOT_FOUND); + } + if (lot.status === LOT_STATUS.SOLD || lot.status === LOT_STATUS.MAX) { + res.releaseCallback(); + return resResult(STATUS.GUILD_LOT_HAS_SOLD); + } + + if (auctionStage === AUCTION_STAGE.GUILD && lot.guildCode !== guildCode) { + res.releaseCallback(); + return resResult(STATUS.AUCTION_GUILD_MEMBER_ONLY); + } + + let { curBuyer, curPrice, prePrice, maxPrice, gid, count, bidRoles, watchingRoles, seq, begin, auctionStage: lotAuctionStage } = lot; + if (auctionStage != lotAuctionStage) { + res.releaseCallback(); + return resResult(STATUS.AUCITON_STAGE_ERR); + } + + if (curBuyer === roleId && !max) { + res.releaseCallback(); + return resResult(STATUS.LOT_OFFER_SERIAL); + } + let newPrice = Math.floor(curPrice * dicParam.GUILD_AUCTION.AUCTION_PRICE_RISE); + let maxFlag = max; + if (maxFlag) { + curPrice = maxPrice; + } + if (curPrice >= maxPrice) { + curPrice = maxPrice; + newPrice = maxPrice; + maxFlag = true; + } + if(newPrice > maxPrice) { + newPrice = maxPrice; + } + + const costRes = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: curPrice }], ITEM_CHANGE_REASON.AUCTION_OFFER); + if (!costRes) { + res.releaseCallback(); + return resResult(STATUS.ROLE_COIN_NOT_ENOUGH); + } + + bidRoles.push({ roleId, price: newPrice, time: new Date() }); + let lotStatus = await getLotStatus(auctionStage, max, maxFlag) + let update: LotParam = { code, curBuyer: roleId, curPrice: newPrice, auctionStage, prePrice: curPrice, bidRoles, status: lotStatus, watchingRoles: Array.from(new Set([...watchingRoles, roleId])), seq: 0 }; + if(lotStatus == LOT_STATUS.BIDDING) update.end = new Date(Date.now() + AUCTION_BID_EXTEND_TIME * 1000); + const newLot = await LotModel.updateLot(update); + if(!newLot) { + // 如果拍卖行状态不对,那回退handleCost + if (curBuyer && prePrice > 0) { + await sendMailByContent(MAIL_TYPE.AUCTION_OVER, roleId, { goods: [getGoldObject(curPrice)] }); + } + res.releaseCallback(); + return resResult(STATUS.GUILD_LOT_HAS_SOLD); + } else { + if (curBuyer && prePrice > 0) { + await sendMailByContent(MAIL_TYPE.AUCTION_OVER, curBuyer, { goods: [getGoldObject(prePrice)] }); + } + + if (maxFlag) { + newPrice = maxPrice; + await sendMailByContent(MAIL_TYPE.AUTION_REWARD, roleId, { goods: [{ id: gid, count }] }); + let dicGoods = gameData.goods.get(gid); + reportTAEvent(roleId, TA_EVENT.AUCTION_ITEM_GET, { item_name: dicGoods?.name, item_count: count, deel_price: newPrice }, ip); + } + } + await extendLotTime(newLot); + if(seq <= LOTS_KEEP_TO_WORLD_CNT && seq > 0) await LotModel.updateOne({ begin, gid, count, status: LOT_STATUS.DEFAULT, serverId, seq: { $gt: LOTS_KEEP_TO_WORLD_CNT } }, { $set: { seq }}); + await pushAuctionOver(newLot); // 推送竞价超过标志 + res.releaseCallback(); + + const incPrice = curPrice - prePrice > 0? prePrice: 0; + let newDividend: DividendType = null; + if (auctionStage === AUCTION_STAGE.GUILD) { + const dividend = await DividendModel.updateLot(code, gid, curPrice, incPrice, max); + newDividend = await calculateDividend(dividend); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_UPDATE, { dividends: processDividendFormat([newDividend]) }) + } + let newLotResult = processSingleLotFormat(newLot); + return resResult(STATUS.SUCCESS, { lot: newLotResult, dividend: processSingleDividendFormat(newDividend) }); + } catch (e) { + console.log('offer got err:', e); + res.releaseCallback(); + return resResult(STATUS.INTERNAL_ERR); + } + } + + async watchLot(msg: { code: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const { code } = msg; + const lot = await LotModel.watchLot(code, roleId); + if (!lot) return resResult(STATUS.WRONG_PARMS); + return resResult(STATUS.SUCCESS, { lot: processSingleLotFormat(lot) }); + } + + async unWatchLot(msg: { code: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const { code } = msg; + const lot = await LotModel.unWatchLot(code, roleId); + if (!lot) return resResult(STATUS.WRONG_PARMS); + return resResult(STATUS.SUCCESS, { lot: processSingleLotFormat(lot) }); + } + + async checkDividend(msg: {}, session: BackendSession) { + const begin = await todayGuildBegin(); + const tomorrowBegin = await tomorrowGuildBegin(); + const guildCode = session.get('guildCode'); + if(guildCode) { + const dividends = await DividendModel.findGuildDividendsByBegin(guildCode, [begin, tomorrowBegin]); + return resResult(STATUS.SUCCESS, { dividends: processDividendFormat(dividends) }); + } else { + let roleId = session.get('roleId'); + + const dividends = await DividendModel.findDividendByRoleAndBegin(roleId, [begin, tomorrowBegin]); + return resResult(STATUS.SUCCESS, { dividends: processDividendFormat(dividends) }); + } + } + + async getDividend(msg: { code: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const { code } = msg; + const dividendData = await DividendModel.findReadyDividend(code); + if (!dividendData) return resResult(STATUS.DIVIDEND_NOT_READY); + const { dividends } = dividendData; + const dividend = dividends.find(item => { return item.roleId === roleId }); + if (!dividend || dividend.status == ROLE_RECEIVE_STATUS.YES) return resResult(STATUS.DIVIDEND_GUILD_PLAYER_ONLY); + let goods = await addItems(roleId, roleName, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: dividend.total }], ITEM_CHANGE_REASON.AUCTION_DIVIDEND); + await DividendModel.updateReceiveStatus(dividendData.code, roleId); + dividend.status = ROLE_RECEIVE_STATUS.YES; + return resResult(STATUS.SUCCESS, { dividend, goods }); + } + + async myWatching(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const begin = await todayGuildBegin(); + const lots = await LotModel.watchingLotsByBegin(serverId, roleId, begin); + const stage = await auctionStage(); + let newLots = await processLotsFormat(lots); + return resResult(STATUS.SUCCESS, { lots: stage === AUCTION_STAGE.END ? [] : newLots }); + } + + async offerRecs(msg: { count: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const lotsData = await LotModel.recentBidLots(serverId, roleId, msg.count); + const bidRecs = lotsData.map(lot => { + const bidRec = lot.bidRoles.find(role => { return role.roleId === roleId }); + const { gid } = lot; + return { ...bidRec, gid, status: auctionBidStatus(roleId, lot) }; + }).sort((a,b) => b.time.getTime() - a.time.getTime()); + return resResult(STATUS.SUCCESS, { bidRecs }); + } + + async guildLotRecs(msg: { count: number }, session: BackendSession) { + const guildCode = session.get('guildCode'); + const dividends = await DividendModel.findDividendsByGuild(guildCode, msg.count); + let lotsData = []; + dividends.forEach(dividend => { + const lots = dividend.lots.map(lot => { + return { ...lot, sourceType: dividend.sourceType, dividendStatus: dividend.status }; + }) + lotsData = [...lotsData, ...lots]; + }); + const lotRecs = lotsData.map(lot => { + const { gid, count, price: lotPrice } = lot; + // const price = lotPrice === 0 ? getBasePrice(gid, count) : lotPrice; + const sold = guildBidStatus(lot); + return { ...lot, price: lotPrice, sold }; + }).sort((a,b) => b.time.getTime() - a.time.getTime());; + + return resResult(STATUS.SUCCESS, { lotRecs }); + } + + // ! 测试接口 + async debugSetDividendStatus(msg: { magicWord: string, sourceType: number, status: number }, session: BackendSession) { + const { magicWord, sourceType, status } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + const guildCode: string = session.get('guildCode'); + if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND) + const dividend = await DividendModel.updateDividendStatus(guildCode, sourceType, status); + return resResult(STATUS.SUCCESS, { dividend }); + } + + // ! 测试接口 + async debugSetLotStage(msg: { magicWord: string, code: string, auctionStage: number }, session: BackendSession) { + const { magicWord, code, auctionStage } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const lot = await LotModel.updateLotStage(code, auctionStage); + return resResult(STATUS.SUCCESS, { lot }); + } + + // ! 测试接口 + async debugAddLots(msg: { magicWord: string, sourceType: number, sourceCode: string, poolId: number }, session: BackendSession) { + const { magicWord, sourceType, sourceCode, poolId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let guildCode: string = session.get('guildCode'); + const serverId: number = session.get('serverId'); + if (!guildCode) {//创建公会 + const roleId = session.get('roleId'); + const role: RoleType = await RoleModel.findByRoleId(roleId); + // 创建公会 + const name = '测试公会' + const icon = 1 + const notice = '测试公会' + const guild = await GuildModel.createGuild({ guildCode: genCode(6), name, icon, notice }, role, serverId); + if (!guild) return resResult(STATUS.GUILD_CREATE_ERROR); + guild.leader = guild.leader; + //创建科技树 + await openGuildRefine(guild.code); + await unlockTrain(guild.code, 1); + const userGuild = await UserGuildModel.createUserGuild(guild.code, role, true); + if (!userGuild) return resResult(STATUS.GUILD_CREATE_ERROR); + + await RoleModel.joinGuild(roleId, guild.code, guild.name, true); + await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 + guildCode = guild.code; + session.set('guildCode', guildCode); + session.push('guildCode', () => {}); + } + + let rewards = getAuctionRewardByPoolId(poolId); + if(!rewards) return resResult(STATUS.WRONG_PARMS); + const result = await genAuction(guildCode, sourceType, magicWord, serverId, rewards); + if (!result) { + return resResult(STATUS.WRONG_PARMS); + } + + return resResult(STATUS.SUCCESS, result); + } + + // ! 测试接口 + async debugScheduleStartGuild(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const result = await startGuildAuction(); + if (result === true) { + return resResult(STATUS.SUCCESS); + } + return resResult(STATUS.INTERNAL_ERR); + } + + // ! 测试接口 + async debugScheduleStartWorld(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const result = await startWorldAuction(); + if (result === true) { + return resResult(STATUS.SUCCESS); + } + return resResult(STATUS.INTERNAL_ERR); + } + + // ! 测试接口 + async debugScheduleStopAuction(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const result = await stopAuction(); + if (result === true) { + return resResult(STATUS.SUCCESS); + } + return resResult(STATUS.INTERNAL_ERR); + } + + // ! 测试接口 + async debugScheduleSendUngotDividend(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const result = await sendUngotDividend(true); + if (result === true) { + return resResult(STATUS.SUCCESS); + } + return resResult(STATUS.INTERNAL_ERR); + } + + async debugSetPlayTime(msg: { magicWord: string, time: string }, session: BackendSession) { + const { magicWord, time } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let serverId = session.get('serverId'); + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: new Date(time).getTime() }); + + return resResult(STATUS.SUCCESS); + } + + // ! 测试接口 + /** + * 领取分红之前,修改分红数据信息,确保领取分红接口能正常跑通 + * debugSetDividendStatus 和 debugSetDividendStatusV2 区别 + * debugSetDividendStatus: 修改 DividendModel.status + * debugSetDividendStatus: 修改 DividendModel.status 和 DividendModel.dividends.status + * + * @param {{ magicWord: string, sourceType: number, status: number }} msg + * @param {BackendSession} session + * @return {*} + * @memberof AuctionHandler + */ + async debugSetDividendStatusV2(msg: { magicWord: string, sourceType: number, status: number }, session: BackendSession) { + const { magicWord, sourceType, status } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + const guildCode: string = session.get('guildCode'); + if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND) + let dividend = await DividendModel.updateDividendStatus(guildCode, sourceType, status); + dividend.dividends.forEach(item => { + item.status = ROLE_RECEIVE_STATUS.NO + }); + dividend = await DividendModel.updateDividend(dividend.code, { dividends: dividend.dividends }) + return resResult(STATUS.SUCCESS, { dividend }); + } +} + diff --git a/game-server/app/servers/guild/handler/cityActivityHandler.ts b/game-server/app/servers/guild/handler/cityActivityHandler.ts index b4012cf0d..3233f857e 100644 --- a/game-server/app/servers/guild/handler/cityActivityHandler.ts +++ b/game-server/app/servers/guild/handler/cityActivityHandler.ts @@ -1,425 +1,426 @@ -import { Application, ChannelService, BackendSession, pinus, HandlerService, } from "pinus"; -import { GUILD_ACTIVITY_TYPE, STATUS, REDIS_KEY, CITY_STATUS, TASK_TYPE, ITEM_CHANGE_REASON, PUSH_ROUTE, GUILD_ACTIVITY_STATUS } from "../../../consts"; -import { genCode, resResult } from "../../../pubUtils/util"; -import { getGuildActivityStatus, getCityStatus as pubGetCityStatus, getCities, getCityActivityRank, sendSingleCityActEndMsg, declareCity, autoDeclareMyCity, getGAIndexInPinus, getDeclareIndex, sendCityGuildRankToUser } from "../../../services/guildActivity/guildActivityService"; -import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; -import { gameData } from "../../../pubUtils/data"; -import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; -import { leaveCityChannel, addRoleToCityChannel } from "../../../services/chatService"; -import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; -import { nowSeconds, getTimeFun } from "../../../pubUtils/timeUtil"; -import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; -import { getGoldObject, handleCost } from "../../../services/role/rewardService"; -import { Rank } from "../../../services/rankService"; -import { checkTask } from "../../../services/task/taskService"; -import { guildInter } from "../../../pubUtils/interface"; -import { dispatch } from "../../../pubUtils/dispatcher"; -import { ServerRecordModel } from "../../../db/ServerRecords"; -import { sendMessageToCityWithSuc } from "../../../services/pushService"; -import { isDebugTime } from "../../../pubUtils/sdkUtil"; -import { GuildActivityCityDeclareModel } from "../../../db/GuildActivityCityDeclare"; -import { GuildModel } from "../../../db/Guild"; -import { getHistoryCity, redisClient, setHistoryCity } from "../../../services/redisService"; -import { HeroModel } from "../../../db/Hero"; -import { getCityActivityObj } from "../../../services/memoryCache/guildActivityData"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new CityActivityHandler(app); -} - -export class CityActivityHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - private aid = GUILD_ACTIVITY_TYPE.CITY_ACTIVITY; // 诸侯混战id - - // 进入诸侯混战 - async getCityActivity(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - let index = getGAIndexInPinus(this.aid); - let declareIndex = getDeclareIndex(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let obj = getCityActivityObj(); - if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { - await autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); - } - const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); - let cities = getCities(guildCode, dbCities); - let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); - let ranks = await getCityActivityRank(guildCode, serverId, guildActivityRec?.challengeCityId, roleId, roleName); - - return resResult(STATUS.SUCCESS, { - ...statusResult, - cities, - ...ranks - }); - } - - // 获取单个城池状态 - async getCityStatus(msg: { cityId: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - let sid = session.get('sid'); - - const { cityId } = msg; - let index = getGAIndexInPinus(this.aid); - let declareIndex = getDeclareIndex(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let dicCity = gameData.cityActivity.get(cityId); - if (!dicCity) return resResult(STATUS.CITY_NOT_FOUND); - let obj = getCityActivityObj(); - let {gateHp, maxHp} = await obj.getGateHpAndInc(serverId, cityId); - - let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); - if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); - - let myGuildActivityRec = await UserGuildActivityRecModel.findByRoleId(roleId, guildActivityRec.code); - let challengeTime = 0; - if (myGuildActivityRec) { - challengeTime = myGuildActivityRec.challengeTime; - } - - const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); - let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity, dbCities); - if (cityStatus == CITY_STATUS.DECLARED) { - obj.pushGuild(guildCode, serverId, cityId); - } - - let historyCity = await getHistoryCity(roleId); - if (historyCity) { - await leaveCityChannel(roleId, sid, serverId, `${historyCity}`); - } - await addRoleToCityChannel(roleId, sid, serverId, cityId); - await setHistoryCity(roleId, cityId); - - let ranks = await getCityActivityRank(guildCode, serverId, cityId, roleId, roleName); - - return resResult(STATUS.SUCCESS, { - cityId, - ...statusResult, - cityStatus, - gateHp, maxHp, - challengeTime, - ...ranks - }); - } - - // 宣战 - async declareCity(msg: { cityId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - // const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - let { cityId } = msg; - let dicCity = gameData.cityActivity.get(cityId); - if (dicCity.preCity.length > 0) return resResult(STATUS.CAN_NOT_DECLARE); - - let declareIndex = getDeclareIndex(); - let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); - if (!!checkResult) return resResult(STATUS.HAS_DECLARED); - await GuildActivityCityModel.getCity(serverId, cityId, declareIndex); - - let declareResult = await declareCity(serverId, roleId, guildCode, cityId, false, declareIndex); - if(!declareResult) return resResult(STATUS.HAS_DECLARED); - - const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); - let cities = getCities(guildCode, dbCities); - return resResult(STATUS.SUCCESS, { cities }); - } - - // 开始挑战 - async checkBattle(msg: guildInter & { cityId: number, heroes: number[] }, session: BackendSession) { - let { cityId, heroes, myUserGuild: userGuild } = msg; - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - let index = getGAIndexInPinus(this.aid); - let declareIndex = getDeclareIndex(); - - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); - if (!checkResult) return resResult(STATUS.HAS_NOT_DECLARED); - - let obj = getCityActivityObj(); - - const dicCity = gameData.cityActivity.get(cityId); - if (!dicCity) return resResult(STATUS.CITY_NOT_FOUND); - - let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); - if (gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index, [], cityId); - if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); - - let { code: sourceCode } = guildActivityRec; - - let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); - if (myGuildActivityRec.challengeTime > nowSeconds()) { - return resResult(STATUS.CHALLENGE_TIME_NOT_REACH); - } - - myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); - - let { code } = myGuildActivityRec; - - // 更新公会参与的玩家 - obj.pushMembers(guildCode, roleId, userGuild.job, myGuildActivityRec.code); - - // 返回当前军团总军功 - let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); - let guildScore = await r.getMyScore({ guildCode }); - - const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); - let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity, dbCities); - // 全服活跃统计 - await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); - - return resResult(STATUS.SUCCESS, { - code, - cityId, - cityStatus, - ...statusResult, - gateHp, maxHp, - guildScore, - myScore: 0 - }); - } - - async resetChallengeTime(msg: {}, session: BackendSession) { - if(1==1) return resResult(STATUS.FUNCTION_CLOSE); - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - let index = getGAIndexInPinus(this.aid); - - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); - if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); - - let { code: sourceCode } = guildActivityRec; - - let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); - - let goldObj = getGoldObject(GUILDACTIVITY.CITYACTIVITY_CD_COST); - const costRes = await handleCost(roleId, sid, [goldObj], ITEM_CHANGE_REASON.CITY_ACT_RESET_CHALLENGE_TIME); - if (!costRes) { - return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - } - - myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(myGuildActivityRec.code, { challengeTime: 0 }); - - return resResult(STATUS.SUCCESS, { - challengeTime: myGuildActivityRec.challengeTime - }); - } - - - // 上报城门受到伤害 - async hitGate(msg: { cityId: number, code: string, damage: number, hid: number, round: number, timegap: number, roundTime: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - - let { cityId, code, damage, hid, round, timegap = 0, roundTime = 0 } = msg; - let obj = getCityActivityObj(); - let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); - if (gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); - - let member = obj.getMember(guildCode, roleId); - if(!member) return resResult(STATUS.NOT_CHECK_BATTLE); - if(!member.startActionTime || member.startActionTime == 0) { - member.startActionTime = nowSeconds(); - } - if ((roundTime > 0 && roundTime < 500) || (timegap - (nowSeconds() - member.startActionTime) > 5)) { // 前后端误差超过5秒拦截 - return resResult(STATUS.SUCCESS, { - isError: true, - timegap: nowSeconds() - member.startActionTime - }); - } - - - let hero = await HeroModel.findBySeqIdAndRole(hid, roleId); - if(!hero && (damage/maxHp > 0.01)) damage = 0; - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - if(statusResult.status != GUILD_ACTIVITY_STATUS.START) { - return resResult(STATUS.SUCCESS, { - code, - ...statusResult, - isError: false, - timegap: nowSeconds() - member.startActionTime, - }) - } - - let challengeTime = nowSeconds() + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; - if(isDebugTime()) { - let guilds = pinus.app.getServersByType('guild'); - let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); - let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); - challengeTime = Math.floor(currentTime/1000) + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; - } - - let pushResult = await UserGuildActivityRecModel.pushCityRecord(code, { round, hid, damage }, challengeTime); - if (!pushResult) return resResult(STATUS.WRONG_PARMS); - - let nextWeek = getTimeFun().getAfterDayWithHour(7); - // 更新redis数据 - let index = getGAIndexInPinus(this.aid); - let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); - let myScore = await myR.setRankWithRoleInfo(roleId, damage, obj.getTimeGap(), null, true); - await myR.setExpire(nextWeek); - - let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); - let guildScore = await r.setRankWithGuildInfo(guildCode, damage, obj.getTimeGap(), null, true); - await r.setExpire(nextWeek); - - ({gateHp, maxHp} = await obj.getGateHpAndInc(serverId, cityId, -1 * damage)); - if (gateHp <= 0) { - // 推送 停止活动并结算奖励 - await sendSingleCityActEndMsg(cityId, serverId); - } - // 推送 城门血量 - await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_ACT_HP, { cityId, gateHp, maxHp }); - await sendCityGuildRankToUser(serverId, cityId, guildCode, roleId); - - return resResult(STATUS.SUCCESS, { - code, - ...statusResult, - guildScore, - myScore, - gateHp, - isError: false, - timegap: nowSeconds() - member.startActionTime, - }) - } - - // 结束挑战 - async battleEnd(msg: { cityId: number, code: string, isSuccess: boolean }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - - let { cityId, code, isSuccess } = msg; - let obj = getCityActivityObj(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let dicCity = gameData.cityActivity.get(cityId); - if (!dicCity) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 更新userGuildActivityRecord - let challengeTime = nowSeconds() + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; - if(isDebugTime()) { - let guilds = pinus.app.getServersByType('guild'); - let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); - let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); - challengeTime = Math.floor(currentTime/1000) + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; - } - let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true, cityId, challengeTime }); - if (!myGuildActivityRec) return resResult(STATUS.WRONG_PARMS); - - // 返回当前军团总军功 - let index = getGAIndexInPinus(this.aid); - let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); - let myScore = await myR.getMyScore({ roleId }); - let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); - let guildScore = await r.getMyScore({ guildCode }); - let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); - - return resResult(STATUS.SUCCESS, { - isSuccess, - code, - ...statusResult, - guildScore, - myScore, - gateHp, - maxHp, - challengeTime: myGuildActivityRec.challengeTime - }); - } - - async debugTestAutoDeclare(msg: { }, session: BackendSession) { - let serverId = session.get('serverId'); - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - let declareIndex = getDeclareIndex(); - for(let i = 0; i < 1000; i++) { - autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); - } - return resResult(STATUS.SUCCESS) - } - - private interval: NodeJS.Timer; - async debugStartHitGate(msg: { param: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - let { param = 1000 } = msg; - - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - if(statusResult.status != GUILD_ACTIVITY_STATUS.START) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - - if(this.interval) { - clearInterval(this.interval); - } - - let fun = async () => { - for(let [cityId] of gameData.cityActivity) { - let guilds = pinus.app.getServersByType('guild'); - let guild = await dispatch(redisClient(), `${cityId}`, guilds, 'guild'); - await pinus.app.rpc.guild.guildActivityRemote.debugSendGateHp.toServer(guild.id, serverId, cityId); - } - await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(this.aid); - }; - await fun(); - this.interval = setInterval(fun, param) - return resResult(STATUS.SUCCESS) - } - - async debugStopHitGate(msg: { magicWord: string }, session: BackendSession) { - - if(this.interval) { - clearInterval(this.interval); - } - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, ChannelService, BackendSession, pinus, HandlerService, } from "pinus"; +import { GUILD_ACTIVITY_TYPE, STATUS, REDIS_KEY, CITY_STATUS, TASK_TYPE, ITEM_CHANGE_REASON, PUSH_ROUTE, GUILD_ACTIVITY_STATUS } from "../../../consts"; +import { genCode, resResult } from "@pubUtils/util"; +import { getGuildActivityStatus, getCityStatus as pubGetCityStatus, getCities, getCityActivityRank, sendSingleCityActEndMsg, declareCity, autoDeclareMyCity, getGAIndexInPinus, getDeclareIndex, sendCityGuildRankToUser } from "../../../services/guildActivity/guildActivityService"; +import { GuildActivityCityModel } from "@db/GuildActivityCity"; +import { gameData } from "@pubUtils/data"; +import { UserGuildActivityRecModel } from "@db/UserGuildActivityRec"; +import { leaveCityChannel, addRoleToCityChannel } from "../../../services/chatService"; +import { GuildActivityRecordModel } from "@db/GuildActivityRec"; +import { nowSeconds, getTimeFun } from "@pubUtils/timeUtil"; +import { GUILDACTIVITY } from "@pubUtils/dicParam"; +import { getGoldObject, handleCost } from "../../../services/role/rewardService"; +import { Rank } from "../../../services/rankService"; +import { checkTask } from "../../../services/task/taskService"; +import { guildInter } from "@pubUtils/interface"; +import { dispatch } from "@pubUtils/dispatcher"; +import { ServerRecordModel } from "@db/ServerRecords"; +import { sendMessageToCityWithSuc } from "../../../services/pushService"; +import { isDebugTime } from "@pubUtils/sdkUtil"; +import { GuildActivityCityDeclareModel } from "@db/GuildActivityCityDeclare"; +import { GuildModel } from "@db/Guild"; +import { getHistoryCity, redisClient, setHistoryCity } from "../../../services/redisService"; +import { HeroModel } from "@db/Hero"; +import { getCityActivityObj } from "../../../services/memoryCache/guildActivityData"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new CityActivityHandler(app); +} + +export class CityActivityHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + private aid = GUILD_ACTIVITY_TYPE.CITY_ACTIVITY; // 诸侯混战id + + // 进入诸侯混战 + async getCityActivity(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + let index = getGAIndexInPinus(this.aid); + let declareIndex = getDeclareIndex(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let obj = getCityActivityObj(); + if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { + await autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); + } + const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); + let cities = getCities(guildCode, dbCities); + let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); + let ranks = await getCityActivityRank(guildCode, serverId, guildActivityRec?.challengeCityId, roleId, roleName); + + return resResult(STATUS.SUCCESS, { + ...statusResult, + cities, + ...ranks + }); + } + + // 获取单个城池状态 + async getCityStatus(msg: { cityId: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + let sid = session.get('sid'); + + const { cityId } = msg; + let index = getGAIndexInPinus(this.aid); + let declareIndex = getDeclareIndex(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let dicCity = gameData.cityActivity.get(cityId); + if (!dicCity) return resResult(STATUS.CITY_NOT_FOUND); + let obj = getCityActivityObj(); + let {gateHp, maxHp} = await obj.getGateHpAndInc(serverId, cityId); + + let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); + if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); + + let myGuildActivityRec = await UserGuildActivityRecModel.findByRoleId(roleId, guildActivityRec.code); + let challengeTime = 0; + if (myGuildActivityRec) { + challengeTime = myGuildActivityRec.challengeTime; + } + + const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); + let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity, dbCities); + if (cityStatus == CITY_STATUS.DECLARED) { + obj.pushGuild(guildCode, serverId, cityId); + } + + let historyCity = await getHistoryCity(roleId); + if (historyCity) { + await leaveCityChannel(roleId, sid, serverId, `${historyCity}`); + } + await addRoleToCityChannel(roleId, sid, serverId, cityId); + await setHistoryCity(roleId, cityId); + + let ranks = await getCityActivityRank(guildCode, serverId, cityId, roleId, roleName); + + return resResult(STATUS.SUCCESS, { + cityId, + ...statusResult, + cityStatus, + gateHp, maxHp, + challengeTime, + ...ranks + }); + } + + // 宣战 + async declareCity(msg: { cityId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + // const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let { cityId } = msg; + let dicCity = gameData.cityActivity.get(cityId); + if (dicCity.preCity.length > 0) return resResult(STATUS.CAN_NOT_DECLARE); + + let declareIndex = getDeclareIndex(); + let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); + if (!!checkResult) return resResult(STATUS.HAS_DECLARED); + await GuildActivityCityModel.getCity(serverId, cityId, declareIndex); + + let declareResult = await declareCity(serverId, roleId, guildCode, cityId, false, declareIndex); + if(!declareResult) return resResult(STATUS.HAS_DECLARED); + + const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); + let cities = getCities(guildCode, dbCities); + return resResult(STATUS.SUCCESS, { cities }); + } + + // 开始挑战 + async checkBattle(msg: guildInter & { cityId: number, heroes: number[] }, session: BackendSession) { + let { cityId, heroes, myUserGuild: userGuild } = msg; + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + let index = getGAIndexInPinus(this.aid); + let declareIndex = getDeclareIndex(); + + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); + if (!checkResult) return resResult(STATUS.HAS_NOT_DECLARED); + + let obj = getCityActivityObj(); + + const dicCity = gameData.cityActivity.get(cityId); + if (!dicCity) return resResult(STATUS.CITY_NOT_FOUND); + + let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); + if (gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index, [], cityId); + if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); + + let { code: sourceCode } = guildActivityRec; + + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + if (myGuildActivityRec.challengeTime > nowSeconds()) { + return resResult(STATUS.CHALLENGE_TIME_NOT_REACH); + } + + myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); + + let { code } = myGuildActivityRec; + + // 更新公会参与的玩家 + obj.pushMembers(guildCode, roleId, userGuild.job, myGuildActivityRec.code); + + // 返回当前军团总军功 + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); + let guildScore = await r.getMyScore({ guildCode }); + + const dbCities = await GuildActivityCityModel.getAllCities(serverId, declareIndex); + let cityStatus = pubGetCityStatus(guildCode, cityId, dicCity, dbCities); + // 全服活跃统计 + await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); + + return resResult(STATUS.SUCCESS, { + code, + cityId, + cityStatus, + ...statusResult, + gateHp, maxHp, + guildScore, + myScore: 0 + }); + } + + async resetChallengeTime(msg: {}, session: BackendSession) { + if(1==1) return resResult(STATUS.FUNCTION_CLOSE); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + let index = getGAIndexInPinus(this.aid); + + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let guildActivityRec = await GuildActivityRecordModel.findByGuild(guildCode, this.aid, index); + if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); + + let { code: sourceCode } = guildActivityRec; + + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + + let goldObj = getGoldObject(GUILDACTIVITY.CITYACTIVITY_CD_COST); + const costRes = await handleCost(roleId, sid, [goldObj], ITEM_CHANGE_REASON.CITY_ACT_RESET_CHALLENGE_TIME); + if (!costRes) { + return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + } + + myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(myGuildActivityRec.code, { challengeTime: 0 }); + + return resResult(STATUS.SUCCESS, { + challengeTime: myGuildActivityRec.challengeTime + }); + } + + + // 上报城门受到伤害 + async hitGate(msg: { cityId: number, code: string, damage: number, hid: number, round: number, timegap: number, roundTime: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + let { cityId, code, damage, hid, round, timegap = 0, roundTime = 0 } = msg; + let obj = getCityActivityObj(); + let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); + if (gateHp <= 0) return resResult(STATUS.GATE_HP_IS_ZERO); + + let member = obj.getMember(guildCode, roleId); + if(!member) return resResult(STATUS.NOT_CHECK_BATTLE); + if(!member.startActionTime || member.startActionTime == 0) { + member.startActionTime = nowSeconds(); + } + if ((roundTime > 0 && roundTime < 500) || (timegap - (nowSeconds() - member.startActionTime) > 5)) { // 前后端误差超过5秒拦截 + return resResult(STATUS.SUCCESS, { + isError: true, + timegap: nowSeconds() - member.startActionTime + }); + } + + + let hero = await HeroModel.findBySeqIdAndRole(hid, roleId); + if(!hero && (damage/maxHp > 0.01)) damage = 0; + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + if(statusResult.status != GUILD_ACTIVITY_STATUS.START) { + return resResult(STATUS.SUCCESS, { + code, + ...statusResult, + isError: false, + timegap: nowSeconds() - member.startActionTime, + }) + } + + let challengeTime = nowSeconds() + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; + if(isDebugTime()) { + let guilds = pinus.app.getServersByType('guild'); + let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); + let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); + challengeTime = Math.floor(currentTime/1000) + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; + } + + let pushResult = await UserGuildActivityRecModel.pushCityRecord(code, { round, hid, damage }, challengeTime); + if (!pushResult) return resResult(STATUS.WRONG_PARMS); + + let nextWeek = getTimeFun().getAfterDayWithHour(7); + // 更新redis数据 + let index = getGAIndexInPinus(this.aid); + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); + let myScore = await myR.setRankWithRoleInfo(roleId, damage, obj.getTimeGap(), null, true); + await myR.setExpire(nextWeek); + + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); + let guildScore = await r.setRankWithGuildInfo(guildCode, damage, obj.getTimeGap(), null, true); + await r.setExpire(nextWeek); + + ({gateHp, maxHp} = await obj.getGateHpAndInc(serverId, cityId, -1 * damage)); + if (gateHp <= 0) { + // 推送 停止活动并结算奖励 + await sendSingleCityActEndMsg(cityId, serverId); + } + // 推送 城门血量 + await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_ACT_HP, { cityId, gateHp, maxHp }); + await sendCityGuildRankToUser(serverId, cityId, guildCode, roleId); + + return resResult(STATUS.SUCCESS, { + code, + ...statusResult, + guildScore, + myScore, + gateHp, + isError: false, + timegap: nowSeconds() - member.startActionTime, + }) + } + + // 结束挑战 + async battleEnd(msg: { cityId: number, code: string, isSuccess: boolean }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + + let { cityId, code, isSuccess } = msg; + let obj = getCityActivityObj(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let dicCity = gameData.cityActivity.get(cityId); + if (!dicCity) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 更新userGuildActivityRecord + let challengeTime = nowSeconds() + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; + if(isDebugTime()) { + let guilds = pinus.app.getServersByType('guild'); + let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); + let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); + challengeTime = Math.floor(currentTime/1000) + GUILDACTIVITY.CITYACTIVITY_CHALLENGE_CD; + } + let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true, cityId, challengeTime }); + if (!myGuildActivityRec) return resResult(STATUS.WRONG_PARMS); + + // 返回当前军团总军功 + let index = getGAIndexInPinus(this.aid); + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); + let myScore = await myR.getMyScore({ roleId }); + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); + let guildScore = await r.getMyScore({ guildCode }); + let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); + + return resResult(STATUS.SUCCESS, { + isSuccess, + code, + ...statusResult, + guildScore, + myScore, + gateHp, + maxHp, + challengeTime: myGuildActivityRec.challengeTime + }); + } + + async debugTestAutoDeclare(msg: { }, session: BackendSession) { + let serverId = session.get('serverId'); + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + let declareIndex = getDeclareIndex(); + for(let i = 0; i < 1000; i++) { + autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); + } + return resResult(STATUS.SUCCESS) + } + + private interval: NodeJS.Timer; + async debugStartHitGate(msg: { param: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + let { param = 1000 } = msg; + + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + if(statusResult.status != GUILD_ACTIVITY_STATUS.START) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + if(this.interval) { + clearInterval(this.interval); + } + + let fun = async () => { + for(let [cityId] of gameData.cityActivity) { + let guilds = pinus.app.getServersByType('guild'); + let guild = await dispatch(redisClient(), `${cityId}`, guilds, 'guild'); + await pinus.app.rpc.guild.guildActivityRemote.debugSendGateHp.toServer(guild.id, serverId, cityId); + } + await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(this.aid); + }; + await fun(); + this.interval = setInterval(fun, param) + return resResult(STATUS.SUCCESS) + } + + async debugStopHitGate(msg: { magicWord: string }, session: BackendSession) { + + if(this.interval) { + clearInterval(this.interval); + } + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/donateHandler.ts b/game-server/app/servers/guild/handler/donateHandler.ts index c1d283096..9e813e77b 100644 --- a/game-server/app/servers/guild/handler/donateHandler.ts +++ b/game-server/app/servers/guild/handler/donateHandler.ts @@ -1,157 +1,158 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { resResult } from '../../../pubUtils/util'; -import { DATA_NAME, ITEM_CHANGE_REASON, STATUS, TASK_TYPE } from '../../../consts'; -import { DonationModel } from '../../../db/Donation'; -import { getZeroPoint, nowSeconds } from '../../../pubUtils/timeUtil'; -import { getArmyDonateBaseByLv, getArmyDonateBoxBaseById, getArmyDonateBoxBaseByLvAndIndex } from '../../../pubUtils/data'; -import { GuildModel } from '../../../db/Guild'; -import { handleCost, addItems } from '../../../services/role/rewardService'; -import { CHAT_SERVER, GUILD_POINT_WAYS } from '../../../consts'; -import { addFund, donate, getDonation, getGuildFundByRefTime } from '../../../services/donateService'; -import { getUserGuildWithRefActive } from '../../../services/guildService'; -import { ARMY } from '../../../pubUtils/dicParam'; -import { addActive } from '../../../services/guildService' -import { checkTask, checkTaskInDonate } from '../../../services/task/taskService'; -import { guildInter } from '../../../pubUtils/interface'; -import { lockData } from '../../../services/redLockService'; -import { getVipDonateConsume } from '../../../services/activity/monthlyTicketService'; -import { changeReceiveBoxIdByLvAndIndex } from '../../../services/donateService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new DonationHandler(app); -} - -export class DonationHandler { - constructor(private app: Application) { - - } - /** - * 捐献所的等级,捐献的次数,战报,捐献达到的基金,领取宝箱记录 - * @param msg - * @param session - */ - async getDonation(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) return resResult(STATUS.WRONG_PARMS); - - let guild = await GuildModel.findGuild(userGuild.guildCode, serverId, 'structure lv'); - if(!guild) { - return resResult(STATUS.WRONG_PARMS); - } - const { guildCode: code, donateCnt, receiveBoxs } = userGuild; - let { donateFund, reports, donationLv } = await getDonation(code, guild); - // 根据donationLv, 和index, 转化成对应的箱子id - let haveGotBoxIds: number[] = changeReceiveBoxIdByLvAndIndex(receiveBoxs, donationLv); - return resResult(STATUS.SUCCESS, { receiveBoxs: haveGotBoxIds, donateFund, reports, donateCnt: donateCnt || 0, donationLv }); - } - /** - * 捐献 - * @param msg - * @param session - */ - async donate(msg: guildInter & { id: number }, session: BackendSession) { - const { id } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = parseInt(session.get('serverId')); - const sid: string = session.get('sid'); - const guildCode: string = session.get('guildCode'); - let res: any = await lockData(serverId, DATA_NAME.DONATE, guildCode);// 锁定资金的增加 - try { - if (!!res.err) { - return resResult(STATUS.REDLOCK_ERR); - } - - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) { - res.releaseCallback(); - return resResult(STATUS.WRONG_PARMS); - } - const { guildCode: code, donateCnt: resdonateCnt } = userGuild; - - let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); - if(!guild) { - res.releaseCallback(); - return resResult(STATUS.WRONG_PARMS); - } - - if (resdonateCnt >= ARMY.ARMY_DONATE_TIMES) { - res.releaseCallback(); - return resResult(STATUS.GUILD_DONATE_TIMES_NOT_ENOUGH); - } - let { donationLv } = await getGuildFundByRefTime(code, getZeroPoint()); - let { donateReward } = getArmyDonateBaseByLv(donationLv); - let { rewardGood, rewardFund, cosume } = donateReward.get(id); - let consumeResult = getVipDonateConsume(cosume, session.get('vipStartTime')); - let result = await handleCost(roleId, sid, consumeResult, ITEM_CHANGE_REASON.DONATE); - if (!result) { - res.releaseCallback(); - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - let { donateCnt } = await UserGuildModel.donateFund(roleId, 1); - - let { donateFund, reports } = await donate(code, rewardFund, id, roleName, donationLv); - let goods = []; - if (!!rewardGood) - goods = await addItems(roleId, roleName, sid, [rewardGood], ITEM_CHANGE_REASON.DONATE); - //增加基金 - await addFund(code, serverId, rewardFund); - - await checkTaskInDonate(serverId, roleId, sid, cosume); - await addActive(roleId, serverId, GUILD_POINT_WAYS.DONATE, id); - res.releaseCallback(); - return resResult(STATUS.SUCCESS, { donateFund, reports, donateCnt, simpleGoods: goods }); - } catch (e) { - res.releaseCallback(); - throw e; - } - } - /** - * 领取宝箱 - * @param msg - * @param session - */ - async receiveBox(msg: guildInter & { id: number }, session: BackendSession) { - const { id, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const serverId: number = parseInt(session.get('serverId')); - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code, receiveBoxs: resReceiveBoxs } = userGuild; - - let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); - if(!guild) { - return resResult(STATUS.WRONG_PARMS); - } - - // 领取限制: 一天内,相同index的箱子不允许重复领取 - // 当前要领取的箱子index - const {index: curBoxIndex} = getArmyDonateBoxBaseById(id); - for (let haveGotId of resReceiveBoxs) { - // 已领取箱子index - let {index: haveGotIndex} = getArmyDonateBoxBaseById(haveGotId); - if (haveGotIndex === curBoxIndex) { - return resResult(STATUS.GUILD_DONATE_BOXS_IS_GOT); - } - } - let { boxRewards, fund, level } = getArmyDonateBoxBaseById(id); - let { donateFund, donationLv } = await getDonation(code, guild); - if( donationLv < level) return resResult(STATUS.GUILD_DONATE_LV_NOT_ENOUGH) - if (donateFund < fund) - return resResult(STATUS.GUILD_DONATE_BOXS_NOT_GOT); - resReceiveBoxs.push(id); - let { receiveBoxs } = await UserGuildModel.updateInfo(roleId, { receiveBoxs: resReceiveBoxs }, {}, 'receiveBoxs'); - let goods = await addItems(roleId, roleName, sid, boxRewards, ITEM_CHANGE_REASON.DONATE_BOX); - // 根据donationLv, 和index, 转化成对应的箱子id - let haveGotBoxIds: number[] = changeReceiveBoxIdByLvAndIndex(receiveBoxs, donationLv); - return resResult(STATUS.SUCCESS, { receiveBoxs: haveGotBoxIds, goods }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { UserGuildModel } from '@db/UserGuild'; +import { resResult } from '@pubUtils/util'; +import { DATA_NAME, ITEM_CHANGE_REASON, STATUS, TASK_TYPE } from '../../../consts'; +import { DonationModel } from '@db/Donation'; +import { getZeroPoint, nowSeconds } from '@pubUtils/timeUtil'; +import { getArmyDonateBaseByLv, getArmyDonateBoxBaseById, getArmyDonateBoxBaseByLvAndIndex } from '@pubUtils/data'; +import { GuildModel } from '@db/Guild'; +import { handleCost, addItems } from '../../../services/role/rewardService'; +import { CHAT_SERVER, GUILD_POINT_WAYS } from '../../../consts'; +import { addFund, donate, getDonation, getGuildFundByRefTime } from '../../../services/donateService'; +import { getUserGuildWithRefActive } from '../../../services/guildService'; +import { ARMY } from '@pubUtils/dicParam'; +import { addActive } from '../../../services/guildService' +import { checkTask, checkTaskInDonate } from '../../../services/task/taskService'; +import { guildInter } from '@pubUtils/interface'; +import { lockData } from '../../../services/redLockService'; +import { getVipDonateConsume } from '../../../services/activity/monthlyTicketService'; +import { changeReceiveBoxIdByLvAndIndex } from '../../../services/donateService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new DonationHandler(app); +} + +export class DonationHandler { + constructor(private app: Application) { + + } + /** + * 捐献所的等级,捐献的次数,战报,捐献达到的基金,领取宝箱记录 + * @param msg + * @param session + */ + async getDonation(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) return resResult(STATUS.WRONG_PARMS); + + let guild = await GuildModel.findGuild(userGuild.guildCode, serverId, 'structure lv'); + if(!guild) { + return resResult(STATUS.WRONG_PARMS); + } + const { guildCode: code, donateCnt, receiveBoxs } = userGuild; + let { donateFund, reports, donationLv } = await getDonation(code, guild); + // 根据donationLv, 和index, 转化成对应的箱子id + let haveGotBoxIds: number[] = changeReceiveBoxIdByLvAndIndex(receiveBoxs, donationLv); + return resResult(STATUS.SUCCESS, { receiveBoxs: haveGotBoxIds, donateFund, reports, donateCnt: donateCnt || 0, donationLv }); + } + /** + * 捐献 + * @param msg + * @param session + */ + async donate(msg: guildInter & { id: number }, session: BackendSession) { + const { id } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = parseInt(session.get('serverId')); + const sid: string = session.get('sid'); + const guildCode: string = session.get('guildCode'); + let res: any = await lockData(serverId, DATA_NAME.DONATE, guildCode);// 锁定资金的增加 + try { + if (!!res.err) { + return resResult(STATUS.REDLOCK_ERR); + } + + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) { + res.releaseCallback(); + return resResult(STATUS.WRONG_PARMS); + } + const { guildCode: code, donateCnt: resdonateCnt } = userGuild; + + let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); + if(!guild) { + res.releaseCallback(); + return resResult(STATUS.WRONG_PARMS); + } + + if (resdonateCnt >= ARMY.ARMY_DONATE_TIMES) { + res.releaseCallback(); + return resResult(STATUS.GUILD_DONATE_TIMES_NOT_ENOUGH); + } + let { donationLv } = await getGuildFundByRefTime(code, getZeroPoint()); + let { donateReward } = getArmyDonateBaseByLv(donationLv); + let { rewardGood, rewardFund, cosume } = donateReward.get(id); + let consumeResult = getVipDonateConsume(cosume, session.get('vipStartTime')); + let result = await handleCost(roleId, sid, consumeResult, ITEM_CHANGE_REASON.DONATE); + if (!result) { + res.releaseCallback(); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + let { donateCnt } = await UserGuildModel.donateFund(roleId, 1); + + let { donateFund, reports } = await donate(code, rewardFund, id, roleName, donationLv); + let goods = []; + if (!!rewardGood) + goods = await addItems(roleId, roleName, sid, [rewardGood], ITEM_CHANGE_REASON.DONATE); + //增加基金 + await addFund(code, serverId, rewardFund); + + await checkTaskInDonate(serverId, roleId, sid, cosume); + await addActive(roleId, serverId, GUILD_POINT_WAYS.DONATE, id); + res.releaseCallback(); + return resResult(STATUS.SUCCESS, { donateFund, reports, donateCnt, simpleGoods: goods }); + } catch (e) { + res.releaseCallback(); + throw e; + } + } + /** + * 领取宝箱 + * @param msg + * @param session + */ + async receiveBox(msg: guildInter & { id: number }, session: BackendSession) { + const { id, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const serverId: number = parseInt(session.get('serverId')); + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code, receiveBoxs: resReceiveBoxs } = userGuild; + + let guild = await GuildModel.findGuild(code, serverId, 'structure lv'); + if(!guild) { + return resResult(STATUS.WRONG_PARMS); + } + + // 领取限制: 一天内,相同index的箱子不允许重复领取 + // 当前要领取的箱子index + const {index: curBoxIndex} = getArmyDonateBoxBaseById(id); + for (let haveGotId of resReceiveBoxs) { + // 已领取箱子index + let {index: haveGotIndex} = getArmyDonateBoxBaseById(haveGotId); + if (haveGotIndex === curBoxIndex) { + return resResult(STATUS.GUILD_DONATE_BOXS_IS_GOT); + } + } + let { boxRewards, fund, level } = getArmyDonateBoxBaseById(id); + let { donateFund, donationLv } = await getDonation(code, guild); + if( donationLv < level) return resResult(STATUS.GUILD_DONATE_LV_NOT_ENOUGH) + if (donateFund < fund) + return resResult(STATUS.GUILD_DONATE_BOXS_NOT_GOT); + resReceiveBoxs.push(id); + let { receiveBoxs } = await UserGuildModel.updateInfo(roleId, { receiveBoxs: resReceiveBoxs }, {}, 'receiveBoxs'); + let goods = await addItems(roleId, roleName, sid, boxRewards, ITEM_CHANGE_REASON.DONATE_BOX); + // 根据donationLv, 和index, 转化成对应的箱子id + let haveGotBoxIds: number[] = changeReceiveBoxIdByLvAndIndex(receiveBoxs, donationLv); + return resResult(STATUS.SUCCESS, { receiveBoxs: haveGotBoxIds, goods }); + } +} + diff --git a/game-server/app/servers/guild/handler/gateActivityHandler.ts b/game-server/app/servers/guild/handler/gateActivityHandler.ts index 01f8db1ab..ea70f404f 100644 --- a/game-server/app/servers/guild/handler/gateActivityHandler.ts +++ b/game-server/app/servers/guild/handler/gateActivityHandler.ts @@ -1,332 +1,333 @@ -import { Application, BackendSession, ChannelService, pinus, HandlerService, } from "pinus"; -import { getGuildActivityStatus, getRecordScore, participants, getGateActivityRank, getGAIndexInPinus } from "../../../services/guildActivity/guildActivityService"; -import { resResult } from "../../../pubUtils/util"; -import { STATUS, GUILD_ACTIVITY_TYPE, GUILD_POINT_WAYS, ENEMIES_TYPE, GET_POINT_WAYS, TASK_TYPE, GUILD_ACTIVITY_STATUS } from "../../../consts"; -import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; -import { GUILDACTIVITY } from "../../../pubUtils/dicParam"; -import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; -import { delGuildActivityRank } from "../../../services/redisService"; -import { REDIS_KEY } from "../../../consts"; -import { gameData } from "../../../pubUtils/data"; -import { UserGuildModel } from "../../../db/UserGuild"; -import { GuildActivityCityModel } from "../../../db/GuildActivityCity"; -import { Rank } from "../../../services/rankService"; -import { getTimeFun, getZeroPointD } from "../../../pubUtils/timeUtil"; -import { checkTask } from "../../../services/task/taskService"; -import { guildInter } from "../../../pubUtils/interface"; -import { ServerRecordModel } from "../../../db/ServerRecords"; -import { getGateActivityObj } from "../../../services/memoryCache/guildActivityData"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GateActivityHandler(app); -} - -export class GateActivityHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - private aid = GUILD_ACTIVITY_TYPE.GATE_ACTIVITY; // 蛮夷入侵id - - // 进入蛮夷入侵界面 - async getGateActivity(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - let index = getGAIndexInPinus(this.aid); - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index); - if (!guildActivityRec) return resResult(STATUS.INTERNAL_ERR); - - let { code: sourceCode } = guildActivityRec; - let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); - let { challengeCnt } = myGuildActivityRec; - - let ranks = await getGateActivityRank(guildCode, serverId, roleId, roleName); - - return resResult(STATUS.SUCCESS, { - ...statusResult, - challengeCnt: GUILDACTIVITY.GATEACTIVITY_CHALLENGE_TIMES - challengeCnt, - ...ranks - }); - } - - // 开启挑战 - async checkBattle(msg: guildInter & { heroes: number[] }, session: BackendSession) { - let { heroes, myUserGuild: userGuild } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - let obj = getGateActivityObj(); - let index = getGAIndexInPinus(this.aid); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index); - if (!guildActivityRec) return resResult(STATUS.INTERNAL_ERR); - - let { code: sourceCode } = guildActivityRec; - let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); - if (myGuildActivityRec.challengeCnt > 0) { - return resResult(STATUS.CHALLENGE_CNT_NOT_ENOUGH); - } - myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); - let { code, challengeCnt } = myGuildActivityRec; - - // 更新公会参与的玩家 - obj.pushMembers(guildCode, serverId, roleId, userGuild.job, code); - - // 返回当前军团总军功 - let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); - let guildScore = await r.getMyScore({ guildCode }); - // 全服活跃统计 - await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); - return resResult(STATUS.SUCCESS, { - code, - ...statusResult, - guildScore: guildScore || 0, - myScore: 0, - challengeCnt: GUILDACTIVITY.GATEACTIVITY_CHALLENGE_TIMES - challengeCnt, - }); - } - - // 上报玩家获得军功 - async action(msg: { code: string, round: number, record: { round: number, dataId: number }[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - - let { code, round, record } = msg; - let obj = getGateActivityObj(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - if(statusResult.status != GUILD_ACTIVITY_STATUS.START) { - return resResult(STATUS.SUCCESS, { - code, - ...statusResult - }) - } - - // 计算record内得分 - let memberRecord = obj.getMemberRecord(code, roleId); - let scoreResult = getRecordScore(this.aid, round, record, memberRecord); - if (!scoreResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let { score, newRecords, memberRecord: newMemberRecord } = scoreResult; - obj.setMemberRecord(code, newMemberRecord); - - let nextWeek = getTimeFun().getAfterDayWithHour(7); - // console.log('####### nextWeek', nextWeek) - let index = getGAIndexInPinus(this.aid); - // 更新redis数据 - let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); - let myScore = await myR.setRankWithRoleInfo(roleId, score, obj.getTimeGap(), null, true); - await myR.setExpire(nextWeek); - - let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); - let guildScore = await r.setRankWithGuildInfo(guildCode, score, obj.getTimeGap(), null, true); - await r.setExpire(nextWeek); - - // 更新数据库 - let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords, round); - - return resResult(STATUS.SUCCESS, { - code: rec.code, - ...statusResult, - guildScore: guildScore || 0, - myScore: myScore || 0 - }); - } - - // 结束挑战 - async battleEnd(msg: { code: string, isSuccess: boolean, gateHp: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - - let { code, isSuccess, gateHp } = msg; - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 更新userGuildActivityRecord - let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true, gateHp }); - if (!myGuildActivityRec) return resResult(STATUS.INTERNAL_ERR); - - // 功劳簿计算 - let { record, round } = myGuildActivityRec; - let enemyCnt = 0, littleBossCnt = 0, bossCnt = 0; - for (let { enemyType, round: r } of record) { - if (enemyType == ENEMIES_TYPE.ENEMY || enemyType == ENEMIES_TYPE.ELITE_ENEMY) { - enemyCnt++; - } else if (enemyType == ENEMIES_TYPE.LITTLE_BOSS) { - littleBossCnt++; - } else if (enemyType == ENEMIES_TYPE.BOSS) { - bossCnt++; - } - } - - let index = getGAIndexInPinus(this.aid); - let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); - let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); - if (isSuccess && statusResult.status == GUILD_ACTIVITY_STATUS.START) { - let obj = getGateActivityObj(); - let score = gameData.gateActivityPoint.get(GET_POINT_WAYS.DEFENSE_SUCCESS); - - if(score > 0) { - await myR.setRankWithRoleInfo(roleId, score, obj.getTimeGap(), null, true); - await r.setRankWithGuildInfo(guildCode, score, obj.getTimeGap(), null, true); - } - } - - // 返回当前军团总军功 - let guildScore = await r.getMyScore({ guildCode }); - let myScore = await myR.getMyScore({ roleId }); - - let info = { - round, - enemyCnt, littleBossCnt, bossCnt, - isSuccess - } - - return resResult(STATUS.SUCCESS, { - code, - ...statusResult, - guildScore, - myScore, - info - }) - } - - // ! 测试接口 - async debugGetPrivate(msg: {}, session: BackendSession) { - let guildCode = session.get('guildCode'); - // console.log(guildCode); - let serverId = session.get('serverId'); - let res = getGateActivityObj().getObj(guildCode, serverId); - return resResult(STATUS.SUCCESS, res) - } - - // ! 测试接口 - async test(msg: { sourceType: number, sourceCode: string }, session: BackendSession) { - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - - // await GuildActivityCityModel.declare(serverId, 1, guildCode); - let { sourceType, sourceCode } = msg; - let result = await participants(guildCode, sourceType, sourceCode); - return result; - - // let result = await setMedianCe(); - // return resResult(STATUS.SUCCESS, {result}); - } - - // ! 测试接口 - async debugIncChallengeCnt(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let today = getZeroPointD(); - await UserGuildActivityRecModel.updateMany( - { roleId, createdAt: { $gte: today } }, { $set: { challengeCnt: -100 } }, { new: true }).lean(); - - return resResult(STATUS.SUCCESS); - } - - // ! 测试接口 - async debugStartActivity(msg: { aid: number }, session: BackendSession) { - let { aid } = msg; - let dic = gameData.guildActivity.get(aid); - if (!dic) return resResult(STATUS.WRONG_PARMS); - let result = await pinus.app.rpc.systimer.systimerRemote.guildActivityStart.toServer('systimer-server-1', dic); - if (!result) { - return resResult(STATUS.GUILD_ACTIVITY_IS_OPEN) - } - - // !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 - let now = new Date(); - let guildServers = pinus.app.getServersByType('guild'); - for (let server of guildServers) { - pinus.app.rpc.guild.guildActivityRemote.updateGuildActivityData.toServer(server.id, aid, true); - } - - return resResult(STATUS.SUCCESS); - } - - // ! 测试接口 - async debugSetDay(msg: { week: number }, session: BackendSession) { - await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(msg.week); - await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(msg.week); - await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(msg.week); - - if (msg.week <= 2) { - await GuildActivityCityModel.deleteMany({}); - } - await delGuildActivityRank(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - await delGuildActivityRank(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - await delGuildActivityRank(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); - return resResult(STATUS.SUCCESS); - } - - // ! 测试接口 - async debugEndActivity(msg: { aid: number }, session: BackendSession) { - let { aid } = msg; - if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - await pinus.app.rpc.systimer.systimerRemote.gateActivityEnd.toServer('systimer-server-1'); - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - await pinus.app.rpc.systimer.systimerRemote.cityActivityEnd.toServer('systimer-server-1'); - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - await pinus.app.rpc.systimer.systimerRemote.raceActivityEnd.toServer('systimer-server-1'); - } else { - return resResult(STATUS.WRONG_PARMS) - } - - // !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 - let now = new Date(); - let guildServers = pinus.app.getServersByType('guild'); - for (let server of guildServers) { - pinus.app.rpc.guild.guildActivityRemote.updateGuildActivityData.toServer(server.id, aid, false); - } - return resResult(STATUS.SUCCESS); - } - - async debugDelRedis(msg: { aid: number }, session: BackendSession) { - let { aid } = msg; - await delGuildActivityRank(aid); - } - - // ! 测试接口 将自己添加进活动roleId里 - async debugAddParticipants(msg: { aid: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND); - let serverId = session.get('serverId'); - let { aid } = msg; - let index = getGAIndexInPinus(aid); - await GuildActivityRecordModel.getRecord(guildCode, serverId, aid, index); - let userGuild = await UserGuildModel.getMyGuild(roleId); - let result = await GuildActivityRecordModel.updateInfo(guildCode, aid, index, { memberCnt: 1, members: [{ roleId, job: userGuild.job, code: '' }], auctionType: aid + 1 }); - - return resResult(STATUS.SUCCESS, { - sourceType: result.auctionType, - sourceCode: result.code - }); - } -} +import { Application, BackendSession, ChannelService, pinus, HandlerService, } from "pinus"; +import { getGuildActivityStatus, getRecordScore, participants, getGateActivityRank, getGAIndexInPinus } from "../../../services/guildActivity/guildActivityService"; +import { resResult } from "@pubUtils/util"; +import { STATUS, GUILD_ACTIVITY_TYPE, GUILD_POINT_WAYS, ENEMIES_TYPE, GET_POINT_WAYS, TASK_TYPE, GUILD_ACTIVITY_STATUS } from "../../../consts"; +import { UserGuildActivityRecModel } from "@db/UserGuildActivityRec"; +import { GUILDACTIVITY } from "@pubUtils/dicParam"; +import { GuildActivityRecordModel } from "@db/GuildActivityRec"; +import { delGuildActivityRank } from "../../../services/redisService"; +import { REDIS_KEY } from "../../../consts"; +import { gameData } from "@pubUtils/data"; +import { UserGuildModel } from "@db/UserGuild"; +import { GuildActivityCityModel } from "@db/GuildActivityCity"; +import { Rank } from "../../../services/rankService"; +import { getTimeFun, getZeroPointD } from "@pubUtils/timeUtil"; +import { checkTask } from "../../../services/task/taskService"; +import { guildInter } from "@pubUtils/interface"; +import { ServerRecordModel } from "@db/ServerRecords"; +import { getGateActivityObj } from "../../../services/memoryCache/guildActivityData"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GateActivityHandler(app); +} + +export class GateActivityHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + private aid = GUILD_ACTIVITY_TYPE.GATE_ACTIVITY; // 蛮夷入侵id + + // 进入蛮夷入侵界面 + async getGateActivity(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + let index = getGAIndexInPinus(this.aid); + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index); + if (!guildActivityRec) return resResult(STATUS.INTERNAL_ERR); + + let { code: sourceCode } = guildActivityRec; + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + let { challengeCnt } = myGuildActivityRec; + + let ranks = await getGateActivityRank(guildCode, serverId, roleId, roleName); + + return resResult(STATUS.SUCCESS, { + ...statusResult, + challengeCnt: GUILDACTIVITY.GATEACTIVITY_CHALLENGE_TIMES - challengeCnt, + ...ranks + }); + } + + // 开启挑战 + async checkBattle(msg: guildInter & { heroes: number[] }, session: BackendSession) { + let { heroes, myUserGuild: userGuild } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + let obj = getGateActivityObj(); + let index = getGAIndexInPinus(this.aid); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, index); + if (!guildActivityRec) return resResult(STATUS.INTERNAL_ERR); + + let { code: sourceCode } = guildActivityRec; + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + if (myGuildActivityRec.challengeCnt > 0) { + return resResult(STATUS.CHALLENGE_CNT_NOT_ENOUGH); + } + myGuildActivityRec = await UserGuildActivityRecModel.incChallengeCnt(myGuildActivityRec.code, heroes); + let { code, challengeCnt } = myGuildActivityRec; + + // 更新公会参与的玩家 + obj.pushMembers(guildCode, serverId, roleId, userGuild.job, code); + + // 返回当前军团总军功 + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); + let guildScore = await r.getMyScore({ guildCode }); + // 全服活跃统计 + await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); + return resResult(STATUS.SUCCESS, { + code, + ...statusResult, + guildScore: guildScore || 0, + myScore: 0, + challengeCnt: GUILDACTIVITY.GATEACTIVITY_CHALLENGE_TIMES - challengeCnt, + }); + } + + // 上报玩家获得军功 + async action(msg: { code: string, round: number, record: { round: number, dataId: number }[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + + let { code, round, record } = msg; + let obj = getGateActivityObj(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + if(statusResult.status != GUILD_ACTIVITY_STATUS.START) { + return resResult(STATUS.SUCCESS, { + code, + ...statusResult + }) + } + + // 计算record内得分 + let memberRecord = obj.getMemberRecord(code, roleId); + let scoreResult = getRecordScore(this.aid, round, record, memberRecord); + if (!scoreResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let { score, newRecords, memberRecord: newMemberRecord } = scoreResult; + obj.setMemberRecord(code, newMemberRecord); + + let nextWeek = getTimeFun().getAfterDayWithHour(7); + // console.log('####### nextWeek', nextWeek) + let index = getGAIndexInPinus(this.aid); + // 更新redis数据 + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); + let myScore = await myR.setRankWithRoleInfo(roleId, score, obj.getTimeGap(), null, true); + await myR.setExpire(nextWeek); + + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); + let guildScore = await r.setRankWithGuildInfo(guildCode, score, obj.getTimeGap(), null, true); + await r.setExpire(nextWeek); + + // 更新数据库 + let rec = await UserGuildActivityRecModel.pushRecord(code, newRecords, round); + + return resResult(STATUS.SUCCESS, { + code: rec.code, + ...statusResult, + guildScore: guildScore || 0, + myScore: myScore || 0 + }); + } + + // 结束挑战 + async battleEnd(msg: { code: string, isSuccess: boolean, gateHp: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + + let { code, isSuccess, gateHp } = msg; + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 更新userGuildActivityRecord + let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true, gateHp }); + if (!myGuildActivityRec) return resResult(STATUS.INTERNAL_ERR); + + // 功劳簿计算 + let { record, round } = myGuildActivityRec; + let enemyCnt = 0, littleBossCnt = 0, bossCnt = 0; + for (let { enemyType, round: r } of record) { + if (enemyType == ENEMIES_TYPE.ENEMY || enemyType == ENEMIES_TYPE.ELITE_ENEMY) { + enemyCnt++; + } else if (enemyType == ENEMIES_TYPE.LITTLE_BOSS) { + littleBossCnt++; + } else if (enemyType == ENEMIES_TYPE.BOSS) { + bossCnt++; + } + } + + let index = getGAIndexInPinus(this.aid); + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId }, true); + if (isSuccess && statusResult.status == GUILD_ACTIVITY_STATUS.START) { + let obj = getGateActivityObj(); + let score = gameData.gateActivityPoint.get(GET_POINT_WAYS.DEFENSE_SUCCESS); + + if(score > 0) { + await myR.setRankWithRoleInfo(roleId, score, obj.getTimeGap(), null, true); + await r.setRankWithGuildInfo(guildCode, score, obj.getTimeGap(), null, true); + } + } + + // 返回当前军团总军功 + let guildScore = await r.getMyScore({ guildCode }); + let myScore = await myR.getMyScore({ roleId }); + + let info = { + round, + enemyCnt, littleBossCnt, bossCnt, + isSuccess + } + + return resResult(STATUS.SUCCESS, { + code, + ...statusResult, + guildScore, + myScore, + info + }) + } + + // ! 测试接口 + async debugGetPrivate(msg: {}, session: BackendSession) { + let guildCode = session.get('guildCode'); + // console.log(guildCode); + let serverId = session.get('serverId'); + let res = getGateActivityObj().getObj(guildCode, serverId); + return resResult(STATUS.SUCCESS, res) + } + + // ! 测试接口 + async test(msg: { sourceType: number, sourceCode: string }, session: BackendSession) { + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + + // await GuildActivityCityModel.declare(serverId, 1, guildCode); + let { sourceType, sourceCode } = msg; + let result = await participants(guildCode, sourceType, sourceCode); + return result; + + // let result = await setMedianCe(); + // return resResult(STATUS.SUCCESS, {result}); + } + + // ! 测试接口 + async debugIncChallengeCnt(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let today = getZeroPointD(); + await UserGuildActivityRecModel.updateMany( + { roleId, createdAt: { $gte: today } }, { $set: { challengeCnt: -100 } }, { new: true }).lean(); + + return resResult(STATUS.SUCCESS); + } + + // ! 测试接口 + async debugStartActivity(msg: { aid: number }, session: BackendSession) { + let { aid } = msg; + let dic = gameData.guildActivity.get(aid); + if (!dic) return resResult(STATUS.WRONG_PARMS); + let result = await pinus.app.rpc.systimer.systimerRemote.guildActivityStart.toServer('systimer-server-1', dic); + if (!result) { + return resResult(STATUS.GUILD_ACTIVITY_IS_OPEN) + } + + // !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 + let now = new Date(); + let guildServers = pinus.app.getServersByType('guild'); + for (let server of guildServers) { + pinus.app.rpc.guild.guildActivityRemote.updateGuildActivityData.toServer(server.id, aid, true); + } + + return resResult(STATUS.SUCCESS); + } + + // ! 测试接口 + async debugSetDay(msg: { week: number }, session: BackendSession) { + await pinus.app.rpc.guild.guildActivityRemote.setDay.broadcast(msg.week); + await pinus.app.rpc.systimer.systimerRemote.setDay.broadcast(msg.week); + await pinus.app.rpc.connector.connectorRemote.setDay.broadcast(msg.week); + + if (msg.week <= 2) { + await GuildActivityCityModel.deleteMany({}); + } + await delGuildActivityRank(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + await delGuildActivityRank(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + await delGuildActivityRank(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); + return resResult(STATUS.SUCCESS); + } + + // ! 测试接口 + async debugEndActivity(msg: { aid: number }, session: BackendSession) { + let { aid } = msg; + if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + await pinus.app.rpc.systimer.systimerRemote.gateActivityEnd.toServer('systimer-server-1'); + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + await pinus.app.rpc.systimer.systimerRemote.cityActivityEnd.toServer('systimer-server-1'); + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + await pinus.app.rpc.systimer.systimerRemote.raceActivityEnd.toServer('systimer-server-1'); + } else { + return resResult(STATUS.WRONG_PARMS) + } + + // !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 + let now = new Date(); + let guildServers = pinus.app.getServersByType('guild'); + for (let server of guildServers) { + pinus.app.rpc.guild.guildActivityRemote.updateGuildActivityData.toServer(server.id, aid, false); + } + return resResult(STATUS.SUCCESS); + } + + async debugDelRedis(msg: { aid: number }, session: BackendSession) { + let { aid } = msg; + await delGuildActivityRank(aid); + } + + // ! 测试接口 将自己添加进活动roleId里 + async debugAddParticipants(msg: { aid: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND); + let serverId = session.get('serverId'); + let { aid } = msg; + let index = getGAIndexInPinus(aid); + await GuildActivityRecordModel.getRecord(guildCode, serverId, aid, index); + let userGuild = await UserGuildModel.getMyGuild(roleId); + let result = await GuildActivityRecordModel.updateInfo(guildCode, aid, index, { memberCnt: 1, members: [{ roleId, job: userGuild.job, code: '' }], auctionType: aid + 1 }); + + return resResult(STATUS.SUCCESS, { + sourceType: result.auctionType, + sourceCode: result.code + }); + } +} + diff --git a/game-server/app/servers/guild/handler/guildBossHandler.ts b/game-server/app/servers/guild/handler/guildBossHandler.ts index fdc0bda4b..ecc377354 100644 --- a/game-server/app/servers/guild/handler/guildBossHandler.ts +++ b/game-server/app/servers/guild/handler/guildBossHandler.ts @@ -1,298 +1,299 @@ -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { resResult, genCode, getRandSingleEelm } from '../../../pubUtils/util'; -import { AUCTION_SOURCE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, MAIL_TYPE, PUSH_ROUTE, STATUS, TASK_TYPE, WAR_TYPE } from '../../../consts'; -import { BossInstanceModel } from '../../../db/BossInstance'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { nowSeconds, getZeroPoint, getSeconds } from '../../../pubUtils/timeUtil'; -import { getBossInstanceInfo, checkBossBattleMemberExists, pushBossHpMessage, addBossInstance, refreshUserGuildOfBoss, refreshGuildOfBoss, getBossHp, getBossInstanceInfoByData, pushBossStatus, zoomOutDamage, zoomInDamage } from '../../../services/guildBossService'; -import { findWhere } from 'underscore' -import { GUILD_STRUCTURE, GUILD_BOSS_STATUS, GUILD_POINT_WAYS } from '../../../consts/constModules/guildConst'; -import { DATA_NAME } from '../../../consts/dataName'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { addActive, addBossWarExtendActive } from '../../../services/guildService'; -import { GuildModel } from '../../../db/Guild'; -import { gameData, getBossByLv } from '../../../pubUtils/data'; -import { lockData } from '../../../services/redLockService'; -import { pushGuildBossSucMsg, getGuildChannelSid } from '../../../services/chatService'; -import { checkTask } from '../../../services/task/taskService'; -import { guildInter, pvpEndParamInter } from '../../../pubUtils/interface'; -import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { RoleModel } from '../../../db/Role'; -import { sendMailToGuildByContent } from '../../../services/mailService'; -import { genAuction, getAuctionRewardByPoolId } from '../../../services/auctionService'; -import { sendMessageToGuildWithSuc } from '../../../services/pushService'; -import { getBattleRecordParam } from '../../../services/normalBattleService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildHandler(app); -} - -export class GuildHandler { - constructor(private app: Application) { - } - - // 获得boss关卡 - async getBossInstance(msg: guildInter & {}, session: BackendSession) { - let { myUserGuild: userGuild } = msg; - let result = await getBossInstanceInfo(userGuild); - return resResult(STATUS.SUCCESS, result); - } - - //开启演武场 - async openBossInstance(msg: guildInter & {}, session: BackendSession) { - - const serverId: number = parseInt(session.get('serverId')); - const { myUserGuild: userGuild } = msg; - - const { guildCode: code } = userGuild; - let res: any = await lockData(serverId, DATA_NAME.BOSS_SCRIPT, code);//加锁 - if (!!res.err) - return resResult(STATUS.REDLOCK_ERR); - const guild = await GuildModel.findByCode(code, serverId, 'code lv structure refOpenBossTime openBossCnt'); - if (!guild) { - res.releaseCallback(); - return resResult(STATUS.GUILD_NOT_FOUND); - } - const { structure } = guild; - const curStructure = structure.find(cur => cur.id == GUILD_STRUCTURE.BOSS); - if (!curStructure) { - res.releaseCallback(); - return resResult(STATUS.GUILD_STRUCTURE_NOT_FOUND); - } - let bossBase = getBossByLv(curStructure.lv); - let dicBossBaseWar = getRandSingleEelm(bossBase.wars); - // let bossHp = Math.ceil(medianCe * bossBase.ratio); - let { ratio, bossHp } = await getBossHp(serverId, code, dicBossBaseWar, bossBase.bossLevel); - - let resGuild = await GuildModel.costFund(code, bossBase.opencost); - if (!resGuild) { - res.releaseCallback(); - return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); - } - let bossInstance = await BossInstanceModel.findBossInstance(code); - if (!!bossInstance && bossInstance.status == GUILD_BOSS_STATUS.OPEN) { - res.releaseCallback(); - return resResult(STATUS.GUILD_SCRIPT_IS_OPENED_TODAY); - } - // 每天开启一次 - let { leaderOpenCnt } = await refreshGuildOfBoss(guild); - if(leaderOpenCnt >= dicParam.GUILD_BOSS.GUILD_BOSS_OPEN_COUNT) { - res.releaseCallback(); - return resResult(STATUS.GUILD_SCRIPT_IS_OPENED_TODAY); - } - await refreshGuildOfBoss(guild, 1); - - bossInstance = await BossInstanceModel.openBossInstance(code, bossHp, ratio, dicBossBaseWar.warId, bossBase.bossLevel); - res.releaseCallback(); - - let result = await getBossInstanceInfoByData(bossInstance, userGuild, guild); - await pushBossStatus(code, result); - return resResult(STATUS.SUCCESS, result); - } - - async battleBoss(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { myUserGuild: userGuild } = msg; - const { guildCode } = userGuild; - let bossInstance = await BossInstanceModel.findBossInstance(guildCode); - if (!bossInstance) - return resResult(STATUS.GUILD_SCRIPT_NOT_OPENED); - if (bossInstance.bossHp <= 0) - return resResult(STATUS.GUILD_SCRIPT_IS_COMPLETE); - let { myChallengeCnt } = await refreshUserGuildOfBoss(userGuild, 0, 0); - if(myChallengeCnt >= dicParam.GUILD_BOSS.GUILD_BOSS_CHALLENGE_COUNT) { - return resResult(STATUS.GUILD_SCRIPT_IS_BATTLED); - } - - let { code: bossCode, warId, ranks, bossHp, encourageCnt } = bossInstance; - const battleCode = genCode(8); // 关卡唯一值 - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId: warId, warType: WAR_TYPE.BOSS, - status: 0, - record: { heroes: [], bossInstanceCode: bossCode, bossHp: zoomOutDamage(bossHp), encourageCnt }, - } - }, true); - const serverId: number = parseInt(session.get('serverId')); - await addBossInstance(guildCode, serverId, roleId); - if (!findWhere(ranks, { roleId })) { - await BossInstanceModel.pushRanks(bossCode, { roleId, score: 0, time: nowSeconds(), job: userGuild.job }); - } else { - await BossInstanceModel.updateRank(bossCode, roleId); - } - let { myChallengeCnt: newMyChallengeCnt } = await refreshUserGuildOfBoss(userGuild, 0, 1); - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_BOSS); - await addActive(roleId, serverId, GUILD_POINT_WAYS.BOSS_WAR);//获得活跃值 - - return resResult(STATUS.SUCCESS, { battleCode, bossCode: bossInstance.code, myChallengeCnt: newMyChallengeCnt }); - } - - async getBossInstanceByBattleCode(msg: guildInter & { battleCode: string }, session: BackendSession) { - const { battleCode, myUserGuild: userGuild } = msg; - let result = { - status: 0, - bossInfo: null - }; - let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); - if(battleRecord && battleRecord.record && battleRecord.record.bossInstanceCode) { - let bossInstance = await BossInstanceModel.findByCode(battleRecord.record.bossInstanceCode); - if(bossInstance) { - let info = await getBossInstanceInfoByData(bossInstance, userGuild); - result.status = bossInstance.status; - result.bossInfo = info.bossInfo && { ...info.bossInfo, encourageCnt: battleRecord.record.encourageCnt } - } - } - return resResult(STATUS.SUCCESS, result); - } - - async action(msg: guildInter & { bossCode: string, damage: number, battleCode: string }, session: BackendSession) { - const { battleCode, damage, myUserGuild: userGuild, bossCode } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = parseInt(session.get('serverId')); - if(!userGuild) return resResult(STATUS.GUILD_NOT_FOUND); - const { guildCode } = userGuild; - let flag = await checkBossBattleMemberExists(guildCode, serverId, roleId, battleCode); - if (!flag) { - return resResult(STATUS.SUCCESS); - } - - //记录伤害 - let bossInstance = await BossInstanceModel.updateBossHp(bossCode, zoomInDamage(damage), roleId); - if(!bossInstance) { // 如果已经被扣成负的了 - return resResult(STATUS.SUCCESS, { bossHp: 0 }); - } - await BattleRecordModel.incBossDamage(battleCode, zoomInDamage(damage), bossInstance.bossHp); - - if (bossInstance.bossHp <= 0) {//进入结算 - - let res:any = await lockData(serverId, DATA_NAME.BOSS_SCRIPT, guildCode);//加锁 - if (!!res.err) - return resResult(STATUS.SUCCESS, { bossHp: 0 }); - bossInstance = await BossInstanceModel.clearBoss(bossCode, bossInstance.bossHp, roleId); - if (!bossInstance) return resResult(STATUS.SUCCESS, { bossHp: 0 }); - - let { warId, bossLv } = bossInstance;//锁定关卡信息 - - await pushBossHpMessage(guildCode, serverId, 0, true); - // 击杀奖励&伤害奖励 - let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); - let dicWar = gameData.war.get(warId); - await sendMailToGuildByContent(MAIL_TYPE.GUILD_BOSS_REWARD, guildCode, { - params: [`${dicWar.gk_name?.split('&')[1]}`], goods: dicBossBase.killReward - }); - - // 加入拍卖行 - if(dicBossBase) { - let rewards = getAuctionRewardByPoolId(dicBossBase.rewards); - await genAuction(guildCode, AUCTION_SOURCE.BOSS, bossCode, serverId, rewards); - } - - let result = await getBossInstanceInfoByData(bossInstance, userGuild); - await pushBossStatus(guildCode, result); - pushGuildBossSucMsg(roleId, roleName, guildCode, bossInstance); - - await addBossWarExtendActive(bossCode, serverId) - - res.releaseCallback();//解锁 - return resResult(STATUS.SUCCESS, { bossHp: 0 }); - } else { - pushBossHpMessage(guildCode, serverId, bossInstance.bossHp); - return resResult(STATUS.SUCCESS, { bossHp: bossInstance.bossHp }); - } - } - - async battleBossEnd(msg: guildInter & { bossCode: string, battleCode: string, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - const { battleCode, myUserGuild: userGuild, bossCode, damageRecords, round } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - - let bossInstance = await BossInstanceModel.findByCode(bossCode); - if(!bossInstance) return resResult(STATUS.WRONG_PARMS); - - let battleRecord = await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { status: 1, ...getBattleRecordParam(damageRecords, round) }//战斗结束统一设置成1 - }, true); - - let { bossDamage = 0 } = battleRecord.record; // 伤害奖励 - let dicBossBase = gameData.bossBaseByBossLv.get(bossInstance.bossLv); - let { basicReward, damageRewardTotal } = dicBossBase; - let damageReward = damageRewardTotal.map(cur => { - return { id: cur.id, count: Math.ceil(cur.count * bossDamage / bossInstance.bossTotalHp )} - }) - let reward = [...basicReward, ...damageReward]; - - let battleGoods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.BOSS_BATTLE_END); - - let result = await getBossInstanceInfoByData(bossInstance, userGuild); - - return resResult(STATUS.SUCCESS, { ...result, battleGoods, createdAt: getSeconds(battleRecord.createdAt) }); - } - - async encourage(msg: guildInter & { count: number }, session: BackendSession) { - const { count, myUserGuild: userGuild } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - - let bossInstance = await BossInstanceModel.findBossInstance(userGuild.guildCode); - if(!bossInstance) return resResult(STATUS.GUILD_SCRIPT_NOT_OPENED); - - let { myEncourageCnt } = await refreshUserGuildOfBoss(userGuild); - let freeCount = dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_FREECOUNT - myEncourageCnt > 0? dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_FREECOUNT - myEncourageCnt: 0; - let costGold = (count - freeCount) * dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_COST; - if(costGold < 0) costGold = 0; - let { gold } = await RoleModel.findByRoleId(roleId, 'gold'); - if(gold < costGold) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - - let { code, bossLv } = bossInstance; - let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); - - bossInstance = await BossInstanceModel.encourage(code, count, dicBossBase.encourageSum); // 军团次数 - if(!bossInstance) return resResult(STATUS.GUILD_SCRIPT_ENCOURGE_NOT_ENOUGH); - - let consume = getGoldObject(costGold); - let costResult = await handleCost(roleId, sid, [consume], ITEM_CHANGE_REASON.GUILD_BOSS_ENCOURAGE); - if(!costResult) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - - let { myEncourageCnt: myEncourageCntResult } = await refreshUserGuildOfBoss(userGuild, count); - - let result = { - encourageCnt: bossInstance.encourageCnt, - encourageMax: dicBossBase.encourageSum, - myEncourageCnt: myEncourageCntResult - } - await sendMessageToGuildWithSuc(userGuild.guildCode, PUSH_ROUTE.GUILD_BOSS_ENCOURAGE, result); - return resResult(STATUS.SUCCESS, result); - - } - - async debugAddBattleTimes(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const roleId: string = session.get('roleId'); - await UserGuildModel.updateInfo(roleId, { bossChallengeCnt: 0 }, {}); - - return resResult(STATUS.SUCCESS); - - } - - async debugAddOpenTimes(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const guildCode: string = session.get('guildCode'); - await GuildModel.updateInfo(guildCode, { openBossCnt: 0 }, {}); - - return resResult(STATUS.SUCCESS); - - } -} \ No newline at end of file +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { resResult, genCode, getRandSingleEelm } from '@pubUtils/util'; +import { AUCTION_SOURCE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, MAIL_TYPE, PUSH_ROUTE, STATUS, TASK_TYPE, WAR_TYPE } from '../../../consts'; +import { BossInstanceModel } from '@db/BossInstance'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { nowSeconds, getZeroPoint, getSeconds } from '@pubUtils/timeUtil'; +import { getBossInstanceInfo, checkBossBattleMemberExists, pushBossHpMessage, addBossInstance, refreshUserGuildOfBoss, refreshGuildOfBoss, getBossHp, getBossInstanceInfoByData, pushBossStatus, zoomOutDamage, zoomInDamage } from '../../../services/guildBossService'; +import { findWhere } from 'underscore' +import { GUILD_STRUCTURE, GUILD_BOSS_STATUS, GUILD_POINT_WAYS } from '@consts/constModules/guildConst'; +import { DATA_NAME } from '@consts/dataName'; +import { UserGuildModel } from '@db/UserGuild'; +import { addActive, addBossWarExtendActive } from '../../../services/guildService'; +import { GuildModel } from '@db/Guild'; +import { gameData, getBossByLv } from '@pubUtils/data'; +import { lockData } from '../../../services/redLockService'; +import { pushGuildBossSucMsg, getGuildChannelSid } from '../../../services/chatService'; +import { checkTask } from '../../../services/task/taskService'; +import { guildInter, pvpEndParamInter } from '@pubUtils/interface'; +import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService'; +import * as dicParam from '@pubUtils/dicParam'; +import { RoleModel } from '@db/Role'; +import { sendMailToGuildByContent } from '../../../services/mailService'; +import { genAuction, getAuctionRewardByPoolId } from '../../../services/auctionService'; +import { sendMessageToGuildWithSuc } from '../../../services/pushService'; +import { getBattleRecordParam } from '../../../services/normalBattleService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildHandler(app); +} + +export class GuildHandler { + constructor(private app: Application) { + } + + // 获得boss关卡 + async getBossInstance(msg: guildInter & {}, session: BackendSession) { + let { myUserGuild: userGuild } = msg; + let result = await getBossInstanceInfo(userGuild); + return resResult(STATUS.SUCCESS, result); + } + + //开启演武场 + async openBossInstance(msg: guildInter & {}, session: BackendSession) { + + const serverId: number = parseInt(session.get('serverId')); + const { myUserGuild: userGuild } = msg; + + const { guildCode: code } = userGuild; + let res: any = await lockData(serverId, DATA_NAME.BOSS_SCRIPT, code);//加锁 + if (!!res.err) + return resResult(STATUS.REDLOCK_ERR); + const guild = await GuildModel.findByCode(code, serverId, 'code lv structure refOpenBossTime openBossCnt'); + if (!guild) { + res.releaseCallback(); + return resResult(STATUS.GUILD_NOT_FOUND); + } + const { structure } = guild; + const curStructure = structure.find(cur => cur.id == GUILD_STRUCTURE.BOSS); + if (!curStructure) { + res.releaseCallback(); + return resResult(STATUS.GUILD_STRUCTURE_NOT_FOUND); + } + let bossBase = getBossByLv(curStructure.lv); + let dicBossBaseWar = getRandSingleEelm(bossBase.wars); + // let bossHp = Math.ceil(medianCe * bossBase.ratio); + let { ratio, bossHp } = await getBossHp(serverId, code, dicBossBaseWar, bossBase.bossLevel); + + let resGuild = await GuildModel.costFund(code, bossBase.opencost); + if (!resGuild) { + res.releaseCallback(); + return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); + } + let bossInstance = await BossInstanceModel.findBossInstance(code); + if (!!bossInstance && bossInstance.status == GUILD_BOSS_STATUS.OPEN) { + res.releaseCallback(); + return resResult(STATUS.GUILD_SCRIPT_IS_OPENED_TODAY); + } + // 每天开启一次 + let { leaderOpenCnt } = await refreshGuildOfBoss(guild); + if(leaderOpenCnt >= dicParam.GUILD_BOSS.GUILD_BOSS_OPEN_COUNT) { + res.releaseCallback(); + return resResult(STATUS.GUILD_SCRIPT_IS_OPENED_TODAY); + } + await refreshGuildOfBoss(guild, 1); + + bossInstance = await BossInstanceModel.openBossInstance(code, bossHp, ratio, dicBossBaseWar.warId, bossBase.bossLevel); + res.releaseCallback(); + + let result = await getBossInstanceInfoByData(bossInstance, userGuild, guild); + await pushBossStatus(code, result); + return resResult(STATUS.SUCCESS, result); + } + + async battleBoss(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { myUserGuild: userGuild } = msg; + const { guildCode } = userGuild; + let bossInstance = await BossInstanceModel.findBossInstance(guildCode); + if (!bossInstance) + return resResult(STATUS.GUILD_SCRIPT_NOT_OPENED); + if (bossInstance.bossHp <= 0) + return resResult(STATUS.GUILD_SCRIPT_IS_COMPLETE); + let { myChallengeCnt } = await refreshUserGuildOfBoss(userGuild, 0, 0); + if(myChallengeCnt >= dicParam.GUILD_BOSS.GUILD_BOSS_CHALLENGE_COUNT) { + return resResult(STATUS.GUILD_SCRIPT_IS_BATTLED); + } + + let { code: bossCode, warId, ranks, bossHp, encourageCnt } = bossInstance; + const battleCode = genCode(8); // 关卡唯一值 + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId: warId, warType: WAR_TYPE.BOSS, + status: 0, + record: { heroes: [], bossInstanceCode: bossCode, bossHp: zoomOutDamage(bossHp), encourageCnt }, + } + }, true); + const serverId: number = parseInt(session.get('serverId')); + await addBossInstance(guildCode, serverId, roleId); + if (!findWhere(ranks, { roleId })) { + await BossInstanceModel.pushRanks(bossCode, { roleId, score: 0, time: nowSeconds(), job: userGuild.job }); + } else { + await BossInstanceModel.updateRank(bossCode, roleId); + } + let { myChallengeCnt: newMyChallengeCnt } = await refreshUserGuildOfBoss(userGuild, 0, 1); + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_BOSS); + await addActive(roleId, serverId, GUILD_POINT_WAYS.BOSS_WAR);//获得活跃值 + + return resResult(STATUS.SUCCESS, { battleCode, bossCode: bossInstance.code, myChallengeCnt: newMyChallengeCnt }); + } + + async getBossInstanceByBattleCode(msg: guildInter & { battleCode: string }, session: BackendSession) { + const { battleCode, myUserGuild: userGuild } = msg; + let result = { + status: 0, + bossInfo: null + }; + let battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode); + if(battleRecord && battleRecord.record && battleRecord.record.bossInstanceCode) { + let bossInstance = await BossInstanceModel.findByCode(battleRecord.record.bossInstanceCode); + if(bossInstance) { + let info = await getBossInstanceInfoByData(bossInstance, userGuild); + result.status = bossInstance.status; + result.bossInfo = info.bossInfo && { ...info.bossInfo, encourageCnt: battleRecord.record.encourageCnt } + } + } + return resResult(STATUS.SUCCESS, result); + } + + async action(msg: guildInter & { bossCode: string, damage: number, battleCode: string }, session: BackendSession) { + const { battleCode, damage, myUserGuild: userGuild, bossCode } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = parseInt(session.get('serverId')); + if(!userGuild) return resResult(STATUS.GUILD_NOT_FOUND); + const { guildCode } = userGuild; + let flag = await checkBossBattleMemberExists(guildCode, serverId, roleId, battleCode); + if (!flag) { + return resResult(STATUS.SUCCESS); + } + + //记录伤害 + let bossInstance = await BossInstanceModel.updateBossHp(bossCode, zoomInDamage(damage), roleId); + if(!bossInstance) { // 如果已经被扣成负的了 + return resResult(STATUS.SUCCESS, { bossHp: 0 }); + } + await BattleRecordModel.incBossDamage(battleCode, zoomInDamage(damage), bossInstance.bossHp); + + if (bossInstance.bossHp <= 0) {//进入结算 + + let res:any = await lockData(serverId, DATA_NAME.BOSS_SCRIPT, guildCode);//加锁 + if (!!res.err) + return resResult(STATUS.SUCCESS, { bossHp: 0 }); + bossInstance = await BossInstanceModel.clearBoss(bossCode, bossInstance.bossHp, roleId); + if (!bossInstance) return resResult(STATUS.SUCCESS, { bossHp: 0 }); + + let { warId, bossLv } = bossInstance;//锁定关卡信息 + + await pushBossHpMessage(guildCode, serverId, 0, true); + // 击杀奖励&伤害奖励 + let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); + let dicWar = gameData.war.get(warId); + await sendMailToGuildByContent(MAIL_TYPE.GUILD_BOSS_REWARD, guildCode, { + params: [`${dicWar.gk_name?.split('&')[1]}`], goods: dicBossBase.killReward + }); + + // 加入拍卖行 + if(dicBossBase) { + let rewards = getAuctionRewardByPoolId(dicBossBase.rewards); + await genAuction(guildCode, AUCTION_SOURCE.BOSS, bossCode, serverId, rewards); + } + + let result = await getBossInstanceInfoByData(bossInstance, userGuild); + await pushBossStatus(guildCode, result); + pushGuildBossSucMsg(roleId, roleName, guildCode, bossInstance); + + await addBossWarExtendActive(bossCode, serverId) + + res.releaseCallback();//解锁 + return resResult(STATUS.SUCCESS, { bossHp: 0 }); + } else { + pushBossHpMessage(guildCode, serverId, bossInstance.bossHp); + return resResult(STATUS.SUCCESS, { bossHp: bossInstance.bossHp }); + } + } + + async battleBossEnd(msg: guildInter & { bossCode: string, battleCode: string, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + const { battleCode, myUserGuild: userGuild, bossCode, damageRecords, round } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + + let bossInstance = await BossInstanceModel.findByCode(bossCode); + if(!bossInstance) return resResult(STATUS.WRONG_PARMS); + + let battleRecord = await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { status: 1, ...getBattleRecordParam(damageRecords, round) }//战斗结束统一设置成1 + }, true); + + let { bossDamage = 0 } = battleRecord.record; // 伤害奖励 + let dicBossBase = gameData.bossBaseByBossLv.get(bossInstance.bossLv); + let { basicReward, damageRewardTotal } = dicBossBase; + let damageReward = damageRewardTotal.map(cur => { + return { id: cur.id, count: Math.ceil(cur.count * bossDamage / bossInstance.bossTotalHp )} + }) + let reward = [...basicReward, ...damageReward]; + + let battleGoods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.BOSS_BATTLE_END); + + let result = await getBossInstanceInfoByData(bossInstance, userGuild); + + return resResult(STATUS.SUCCESS, { ...result, battleGoods, createdAt: getSeconds(battleRecord.createdAt) }); + } + + async encourage(msg: guildInter & { count: number }, session: BackendSession) { + const { count, myUserGuild: userGuild } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + + let bossInstance = await BossInstanceModel.findBossInstance(userGuild.guildCode); + if(!bossInstance) return resResult(STATUS.GUILD_SCRIPT_NOT_OPENED); + + let { myEncourageCnt } = await refreshUserGuildOfBoss(userGuild); + let freeCount = dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_FREECOUNT - myEncourageCnt > 0? dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_FREECOUNT - myEncourageCnt: 0; + let costGold = (count - freeCount) * dicParam.GUILD_BOSS.GUILD_BOSS_ENCOURAGE_COST; + if(costGold < 0) costGold = 0; + let { gold } = await RoleModel.findByRoleId(roleId, 'gold'); + if(gold < costGold) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + + let { code, bossLv } = bossInstance; + let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); + + bossInstance = await BossInstanceModel.encourage(code, count, dicBossBase.encourageSum); // 军团次数 + if(!bossInstance) return resResult(STATUS.GUILD_SCRIPT_ENCOURGE_NOT_ENOUGH); + + let consume = getGoldObject(costGold); + let costResult = await handleCost(roleId, sid, [consume], ITEM_CHANGE_REASON.GUILD_BOSS_ENCOURAGE); + if(!costResult) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + + let { myEncourageCnt: myEncourageCntResult } = await refreshUserGuildOfBoss(userGuild, count); + + let result = { + encourageCnt: bossInstance.encourageCnt, + encourageMax: dicBossBase.encourageSum, + myEncourageCnt: myEncourageCntResult + } + await sendMessageToGuildWithSuc(userGuild.guildCode, PUSH_ROUTE.GUILD_BOSS_ENCOURAGE, result); + return resResult(STATUS.SUCCESS, result); + + } + + async debugAddBattleTimes(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const roleId: string = session.get('roleId'); + await UserGuildModel.updateInfo(roleId, { bossChallengeCnt: 0 }, {}); + + return resResult(STATUS.SUCCESS); + + } + + async debugAddOpenTimes(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const guildCode: string = session.get('guildCode'); + await GuildModel.updateInfo(guildCode, { openBossCnt: 0 }, {}); + + return resResult(STATUS.SUCCESS); + + } +} + diff --git a/game-server/app/servers/guild/handler/guildHandler.ts b/game-server/app/servers/guild/handler/guildHandler.ts index 0a04b6b91..d172b7241 100644 --- a/game-server/app/servers/guild/handler/guildHandler.ts +++ b/game-server/app/servers/guild/handler/guildHandler.ts @@ -1,1035 +1,1036 @@ -import { Application, BackendSession, ChannelService, HandlerService, } from 'pinus'; -import { resResult, getRandEelm, shouldRefresh, sortArrRandom } from '../../../pubUtils/util'; -import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE, REDIS_KEY, GUILD_SELECT, USER_GUILD_SELECT, TASK_TYPE, DEBUG_MAGIC_WORD, CHANNEL_PREFIX, MSG_TYPE, MSG_SOURCE, ITEM_CHANGE_REASON, TA_EVENT, GUILD_DISMISS_WAY, GUILD_MASTER_CHANGE_WAY, GUILD_QUIT_WAY, PUSH_ROUTE } from '../../../consts'; -import { UserGuildModel, UserGuildType } from '../../../db/UserGuild'; -import { checkAuth, joinGuild, getUserGuildWithRefActive, addActive, settleGuildWeekly, getMyGuildInfo, setUserGuildSession, getInvitationList, addGuildRecord, pushChangeGuildLeader, pushGuildMemberQuit, pushGuildDismiss, pushGuildInfoUpdate, getTodayGuildActive, getGuildQuitCdTime } from '../../../services/guildService'; -import { GuildModel, GuildType, GuildUpdateParam } from '../../../db/Guild'; -import { RoleModel, RoleType } from '../../../db/Role'; -import { ARMY } from '../../../pubUtils/dicParam'; -import { handleCost, addItems, getGoldObject } from '../../../services/role/rewardService'; -import { nowSeconds, getTimeFun, getSeconds, getZeroPointD, DAY_TO_MS, HOUR_TO_MS } from '../../../pubUtils/timeUtil'; -import { GuildListInfo, GuildMemberParam } from '../../../domain/battleField/guild'; -import { GuildLeader } from '../../../domain/rank'; -import { UserGuildApplyModel } from '../../../db/UserGuildApply'; -import { hasStructureConsume, getStructureConsume, gameData } from '../../../pubUtils/data'; -import { GuildRecModel } from '../../../db/GuildRec'; -import { sendMailByContent, SendMailFun, sendMailToGuildByContent } from '../../../services/mailService'; -import { updateUserInfo, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService'; - -import { openGuildRefine } from '../../../services/guildRefineService'; -import { unlockTrain } from '../../../services/guildTrainService'; -import { removeBossRank } from '../../../services/guildBossService'; -import { removeTrainRank } from '../../../services/guildTrainService'; -import { pushGuildNoticeUpdateMsg, pushGuildUpStructureMsg, addRoleToGuildChannel, getGuildChannelSid, createGroupMsg, pushGroupMsgToRoom } from '../../../services/chatService'; -import { Rank } from '../../../services/rankService'; -import { checkTask } from '../../../services/task/taskService'; -import { guildInter } from '../../../pubUtils/interface'; -import * as dicParam from '../../../pubUtils/dicParam'; -import { reportTAEvent } from '../../../services/sdkService'; -import { changeGuildActivity, guildDismisActivity, guildPayQuitGuild } from '../../../services/activity/guildPayService'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; -import { GuildActiveModel } from '../../../db/GuildActive'; -import { leaveRaceActivityToRemote, leaveRaceWhenDismissToRemote, leaveRaceWhenQuitGuildToRemote } from '../../../services/guildActivity/guildActivityService'; -import { getGVGInfoInGuild } from '../../../services/gvg/gvgService'; -import { guildAbdicateToLeague, guildDismissToLeague, memberQuitGuildToLeague } from '../../../services/gvg/gvgTeamService'; -import { leaveCity } from '../../../services/gvg/gvgBattleService'; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildHandler(app); -} - -export class GuildHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 创建军团 - async createGuild(msg: guildInter & { guildCode: string } & { name: string, icon: number, notice: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { name, icon, notice, guildCode } = msg; - - // 检查名字是否重 - const checkNameResult = await GuildModel.checkName(name, serverId); - if (checkNameResult) return resResult(STATUS.GUILD_NAME_DUP); - - // 检查元宝是否够 - const role = await RoleModel.findByRoleId(roleId); - if (ARMY.ARMY_CREAT_COST > role.gold) { - return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); - } - - // 检查是否充值过 - if(ARMY.ARMY_CREAT_CONDITION > role.totalPay) { - return resResult(STATUS.GUILD_PAY_CONDITION); - } - if(role.lv < 16) return resResult(STATUS.LV_LIMIT); - - await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_CREAT_COST)], ITEM_CHANGE_REASON.CREATE_GUILD); - - // 创建公会 - const guild = await GuildModel.createGuild({ guildCode, name, icon, notice }, role, serverId); - if (!guild) return resResult(STATUS.GUILD_CREATE_ERROR); - guild.leader = guild.leader; - //创建科技树 - await openGuildRefine(guild.code); - await unlockTrain(guild.code, 1); - const userGuild = await UserGuildModel.createUserGuild(guild.code, role, true); - if (!userGuild) return resResult(STATUS.GUILD_CREATE_ERROR); - - await RoleModel.joinGuild(roleId, guild.code, guild.name, true); - await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 - - // 加入排行 - let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild); - let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await r2.setRankWithGuildInfo2(guild.code, guild.lv, guild.activeWeekly, Date.now(), guild); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: name }]); - - let rank = await r.getMyRank({ guildCode: guild.code }); - - // 加入channel - setUserGuildSession(session, userGuild); - addRoleToGuildChannel(roleId, sid, guild.code); - - // 添加动态 - await addGuildRecord(roleId, guild.code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); - - // 返回 - const result = { ...guild, rank, myInfo: { ...userGuild, isOnline: true } }; - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_JOIN); - return resResult(STATUS.SUCCESS, result); - } - - // 获取军团列表 - async getGuildList(msg: guildInter & { page: number, showPeopleMax: boolean, name: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - // const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { page = 1, showPeopleMax, name } = msg; - - const guildList = await GuildModel.getGuildList(page, showPeopleMax, name, serverId); - const applyList = await UserGuildApplyModel.findApplyByRole(roleId); - - const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId); - - const list = new Array(); - for (let guild of guildList) { - let info = new GuildListInfo(guild); - - let hasApply = applyList.find(cur => cur.guildCode == guild.code); - info.setApply(!!hasApply); - list.push(info); - } - return resResult(STATUS.SUCCESS, { quitTime, cdTime: await getGuildQuitCdTime(serverId), list }); - } - - // 团长修改军团名等信息 - async setGuildInfo(msg: guildInter & { code: string, name: string, notice: string, introduce: string, ceLimit: number, isAuto: boolean, icon: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const { code, name, notice, introduce, ceLimit, isAuto, icon } = msg; - if (!code) return resResult(STATUS.WRONG_PARMS); - - // 检查名字是否重 - if(name != undefined) { - const checkNameResult = await GuildModel.checkName(name, serverId); - if (checkNameResult) return resResult(STATUS.GUILD_NAME_DUP); - } - - const select = ['code', 'name', 'notice', 'introduce', 'ceLimit', 'isAuto', 'icon', '+members']; - let updateInfo: GuildUpdateParam = {}; - if(name != undefined) updateInfo.name = name; - if(notice != undefined) updateInfo.notice = notice; - if(introduce != undefined) updateInfo.introduce = introduce; - if(ceLimit != undefined) updateInfo.ceLimit = ceLimit; - if(isAuto != undefined) updateInfo.isAuto = isAuto; - if(icon != undefined) updateInfo.icon = icon; - const guild = await GuildModel.updateInfo(code, updateInfo, {}, select.join(' ')); - await pushGuildInfoUpdate(code, { name, notice, introduce, ceLimit, isAuto }); - - if(name != undefined) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]); - for(let roleId of guild.members) { - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: name }]); - } - await RoleModel.updateGuildName(code, name); - } - if (notice != undefined) { - pushGuildNoticeUpdateMsg(roleId, roleName, guild); - } - if(icon != undefined) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'icon', value: icon }]); - } - // 返回 - return resResult(STATUS.SUCCESS, { ...guild }); - } - - // 游客查看军团详细信息 - async getGuildInfo(msg: guildInter & { code: string }, session: BackendSession) { - - const serverId = session.get('serverId'); - const { code } = msg; - - const select = ['code', 'name', 'notice', 'ceLimit', 'isAuto', 'icon', 'lv', 'memberCnt', 'guildCe']; - const guild = await GuildModel.findByCode(code, null, select.join(' ')); - if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); - let leader = guild.leader; - delete guild.leader; - // 返回 - return resResult(STATUS.SUCCESS, { ...guild, leader: leader.roleName }); - - } - - // 团长授权头衔 - async setAuth(msg: guildInter & { roleId: string, auth: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const ip = session.get('ip'); - const { roleId: memberRoleId, auth, myUserGuild, hisUserGuild } = msg; - - const { guildCode: code } = myUserGuild; - - if (auth == hisUserGuild.auth) { - return resResult(STATUS.GUILD_AUTH_NOT_CHANGE); - } - - // 管理员最大数 等策划表 - let guild = await GuildModel.findByCode(code, serverId, 'managerCnt lv leagueCode'); - if (!guild) { - return resResult(STATUS.GUILD_NOT_FOUND); - } - - let managerCntInc = 0; - if (auth == GUILD_AUTH.LEADER) { // 转让团长 - if (hisUserGuild.auth == GUILD_AUTH.MANAGER) { - managerCntInc = -1; - } - } else { - managerCntInc = auth == GUILD_AUTH.MANAGER ? 1 : -1; - } - - let maxManagerCnt = gameData.centerBase.get(guild.lv); - if (!maxManagerCnt) return STATUS.DIC_DATA_NOT_FOUND; - - if (guild.managerCnt + managerCntInc > maxManagerCnt.managerNum) { - return resResult(STATUS.GUILD_MANAGER_REACH_MAX); - } - - const userGuild = await UserGuildModel.updateInfo(memberRoleId, { auth, job: auth == GUILD_AUTH.LEADER ? GUILD_JOB.DAJIANGJUN : hisUserGuild.job }, {}, 'auth'); // 设置权限 - if (!userGuild) { - return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); - } - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: memberRoleId, userGuild }]); - - const role = await RoleModel.findByRoleId(memberRoleId); - let updateObject = {}; - if (auth == GUILD_AUTH.LEADER) { // 转让团长 - updateObject['leader'] = role._id; - let myUserGuild = await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}); // 自己降权限 - setUserGuildSession(session, myUserGuild); - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(role) }]); - await RoleModel.updateRoleInfo(memberRoleId, { isGuildLeader: true }); - await RoleModel.updateRoleInfo(roleId, { isGuildLeader: false }); - await guildAbdicateToLeague(guild, roleId, role); - } - - guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader - let chatSid = await getGuildChannelSid(code); - - // 添加动态 - if (auth == GUILD_AUTH.MANAGER) { - await pushGuildInfoUpdate(code, { managerCnt: guild.managerCnt }); - await addGuildRecord(roleId, code, GUILD_REC_TYPE.SET_MANAGER, [role.roleName]); - await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MANAGER, memberRoleId, { sendName: roleName, params: [guild.name] }); - } else if (auth == GUILD_AUTH.LEADER) { - await pushChangeGuildLeader(code, guild.managerCnt, role, roleId); - await addGuildRecord(roleId, code, GUILD_REC_TYPE.SET_LEADER, [roleName, role.roleName]); - await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, memberRoleId, { sendName: roleName, params: [guild.name] }); - - reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY, change_id_after: memberRoleId }, ip); - } else { - await pushGuildInfoUpdate(code, { managerCnt: guild.managerCnt }); - await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MEMBER, memberRoleId, { sendName: roleName, params: [guild.name] }); - } - - - // 返回 - return resResult(STATUS.SUCCESS, { - roleId: memberRoleId, auth: userGuild.auth, managerCnt: guild.managerCnt - }); - - } - - // 团员获取自己军团详细信息 - async getMyGuildInfo(msg: guildInter & {}, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) { - return resResult(STATUS.SUCCESS, { hasGuild: false }) - }; - - let guild = await GuildModel.findByCode(userGuild.guildCode, serverId, '+serverId'); - if (!guild) { - return resResult(STATUS.GUILD_NOT_FOUND); - } - - let result = await getMyGuildInfo(roleId, sid, userGuild, guild, serverId, session); - let gvg = await getGVGInfoInGuild(roleId, guild); - return resResult(STATUS.SUCCESS, { ...result, gvg }); - } - - // 玩家申请公会 - async applyGuild(msg: guildInter & { code: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const { code } = msg; - - const guild = await GuildModel.findByCode(code, serverId); - if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); - - const { isMemberMax, isAuto, ceLimit, lv } = guild; - if (isMemberMax) { - return resResult(STATUS.GUILD_MEMBER_MAX); - } - - const role = await RoleModel.findByRoleId(roleId, null, true); - if (ceLimit > role.ce) { - return resResult(STATUS.GUILD_NOT_REACH_CONDI); - } - if(role.lv < 16) return resResult(STATUS.LV_LIMIT); - - if(nowSeconds() - role.quitGuildTime < (await getGuildQuitCdTime(serverId)) * 60) { - return resResult(STATUS.GUILD_QUIT_TIME); - } - - let hasGuild = false; - if (isAuto) { // 自动加入 - const joinResult = await joinGuild(code, guild.name, lv, roleId, serverId, session); - if (joinResult.status == -1) { - return joinResult.resResult; - } - - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); - // 更新人数增加 - await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); - - hasGuild = true; - } else { // 不自动加入,插入申请表 - await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.APPLY); - } - - // 返回 - return resResult(STATUS.SUCCESS, { code, hasGuild }); - } - - // 玩家申请公会 - async getApplyList(msg: guildInter & { code: string, lastApplyCode: string }, session: BackendSession) { - - const { code, lastApplyCode } = msg; - - const result = await UserGuildApplyModel.findApplyByGuild(code, lastApplyCode); - const list = []; - for (let cur of result) { - let role = cur.role; - delete cur.role; - let isOnline = await isRoleOnline(role.roleId); - list.push({ applyCode: cur.applyCode, ...role, isOnline, createTime: getSeconds(cur.createdAt) }); - } - - return resResult(STATUS.SUCCESS, { list }); - } - - // 团长同意/拒绝公会申请 - async receiveApply(msg: guildInter & { code: string, applyCodeList: [string], isReceived: boolean }, session: BackendSession) { - - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const { code, applyCodeList, isReceived } = msg; - - const applyList = await UserGuildApplyModel.getListByApplyCode(applyCodeList); - - const guild = await GuildModel.findByCode(code, serverId); - let roleIds = new Array(); - if (isReceived) { // 同意申请,加入 - - for (let { roleId } of applyList) { - const joinResult = await joinGuild(code, guild.name, guild.lv, roleId, serverId, session); - if (joinResult.status == -1) continue; - // 更新人数增加 - await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]); - roleIds.push(roleId); - } - } else { // 拒绝申请,删除申请 - for (let { roleId } of applyList) { - await sendMailByContent(MAIL_TYPE.GUILD_APPLY_REFUSE, roleId, { sendName: roleName, params: [guild.name] }); - roleIds.push(roleId); - } - - await UserGuildApplyModel.deleteByApplyCode(applyCodeList); - } - - return resResult(STATUS.SUCCESS, { roleIds }); - } - - // 团长查看(刷新)可邀请人列表 - async getInviteMemberList(msg: guildInter & {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { myUserGuild: myGuild } = msg; - let guild = await GuildModel.findByCode(myGuild.guildCode, serverId, GUILD_SELECT.INVITED_MEMBER); - let invitedMembers = guild.invitedMembers; - if (shouldRefresh(guild.inviteTime, new Date())) { - invitedMembers = []; - } - - // 离线时间,三天内在线且尚未加入军团。按以下规则排序 离线时间 玩家等级 玩家战力 - - const day = getTimeFun().getBeforeDay(3); - - const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId); - let allList = await RoleModel.getInviteList(day, serverId); - allList = allList.filter(cur => !invitedMembers.includes(cur.roleId)) - let list = getRandEelm(allList, 10); - if (!list.length) list = allList; - list = sortArrRandom(list); - - let result = []; - for (let cur of list) { - let isOnline = await isRoleOnline(cur.roleId); - result.push({ ...cur, isOnline }) - } - - return resResult(STATUS.SUCCESS, { quitTime, list: result }); - - } - - // 团长(一键)邀请人 - async inviteMember(msg: guildInter & { code: string, roleIds: string[] }, session: BackendSession) { - - const serverId = session.get('serverId'); - const { code, roleIds } = msg; - - const guild = await GuildModel.findByCode(code, serverId, GUILD_SELECT.INVITED_MEMBER); - if (guild.isMemberMax) return resResult(STATUS.GUILD_MEMBER_MAX); - - const roleList = await RoleModel.findByRoleIds(roleIds); - let result = new Array(); - - for (let role of roleList) { - if (!role.hasGuild || role.serverId == serverId) { - let apply = await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.INVITE); - result.push(role.roleId); - let hisInfo = await getRoleOnlineInfo(role.roleId); - if (hisInfo.isOnline) { - let guild = apply.guild; - let leader = guild.leader; - let invitation = { applyCode: apply.applyCode, ...guild, leader: leader.roleName }; - sendMessageToUserWithSuc(role.roleId, PUSH_ROUTE.GUILD_INVITE, { invitation }, hisInfo.sid); - } - } - } - if(result.length <= 0) { - return resResult(STATUS.GUILD_CANNOT_INVITE) - } - - await GuildModel.recordInvitedMember(code, serverId, roleIds, shouldRefresh(guild.inviteTime, new Date())); - - return resResult(STATUS.SUCCESS, { roleIds: result }); - - } - - // 成员收到邀请列表 - async getInvitationList(msg: guildInter & { lastApplyCode: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const { lastApplyCode } = msg; - let list = await getInvitationList(roleId, lastApplyCode); - - return resResult(STATUS.SUCCESS, { list }); - - } - - - // 成员同意/拒绝邀请 - async receiveInvitation(msg: guildInter & { applyCode: string, isReceived: boolean }, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { applyCode, isReceived } = msg; - - const invite = await UserGuildApplyModel.findByCode(applyCode); - if (!invite) return resResult(STATUS.GUILD_INVITE_NOT_FOUND); - - let code: string; - if (isReceived) { // 同意申请,加入 - - const role = await RoleModel.findByRoleId(roleId, 'lv'); - if(role.lv < 16) return resResult(STATUS.LV_LIMIT); - - const { guildCode } = invite; - const guild = await GuildModel.findByCode(guildCode, serverId); - if (!guild) { - await UserGuildApplyModel.deleteByApplyCode([applyCode]); // 删除这条邀请 - return resResult(STATUS.GUILD_DELETE_ERROR); - } - - const joinResult = await joinGuild(guildCode, guild.name, guild.lv, roleId, serverId, session); - if (joinResult.status == -1) { - return joinResult.resResult; - } - - // 更新人数增加 - await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]); - - code = guild.code; - } - await UserGuildApplyModel.deleteByApplyCode([applyCode]); // 删除这条邀请 - - return resResult(STATUS.SUCCESS, { applyCode, code, isReceived, hasGuild: isReceived }); - } - - // 获取军团成员 - async getGuildMember(msg: { code: string, sort: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const guildAuth: number = session.get('guildAuth'); - // const serverId = session.get('serverId'); - const { code, sort } = msg; - - let select = ['role', 'job']; - const checkDetailResult = await checkAuth(GUILD_OPERATE.GET_MEMBER_LIST_DETAIL, code, guildAuth); - if (checkDetailResult) { - select.push('auth', 'activeWeekly activeUpdateTime'); - } - let list = await UserGuildModel.getListByGuild(code, select.join(' '), { auth: 1 }); - let result: GuildMemberParam[] = []; - for (let cur of list) { - let role = cur.role; - if(role) { - let param = new GuildMemberParam(cur, role); - param.setOnline(role.loginTime == role.quitTime); - result.push(param); - } - } - - if (result && result.length > 0) { - let leader = result.shift(); // 团长在最上面 - result.sort((a, b) => { - if (sort == 'active') { - if (b.activeWeekly == a.activeWeekly) { - return a.activeUpdateTime - b.activeUpdateTime - } else { - return b.activeWeekly - a.activeWeekly - } - } else if (sort == 'loginTime') { - return b.quitTime - a.quitTime; - } else { - return b.ce - a.ce; - } - }); - result.unshift(leader); - } else { - // 此处应有异常 - } - return resResult(STATUS.SUCCESS, { list: result }); - } - - // 团长解散军团 - async dismiss(msg: guildInter & { code: string }, session: BackendSession) { - - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleId = session.get('roleId'); - const ip = session.get('ip'); - const { code } = msg; - - let guild = await GuildModel.findByCode(code, serverId, 'leagueCode'); - if(guild.leagueCode) return resResult(STATUS.GVG_GUILD_HAS_LEAGUE); - - guild = await GuildModel.dismiss(code, serverId); - if (!guild) return resResult(STATUS.GUILD_DELETE_ERROR); - - await sendMailToGuildByContent(MAIL_TYPE.GUILD_DISSMISS, code, {}, guild); - await UserGuildModel.dismiss(code); - const { members } = guild; - await RoleModel.dissmissGuild(members); - await UserGuildApplyModel.deleteApplyByGuild(code); - await guildDismissToLeague(guild); - - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast(members.map(roleId => { return { roleId, userGuild: null } })); // 更新session - - // 删除channel - await guildDismisActivity(code, serverId); - await pushGuildDismiss(code); - let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - await r.removeFromRank({ guildCode: code }); - let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await r2.removeFromRank({ guildCode: code }); - reportTAEvent(roleId, TA_EVENT.GUILD_DISMISS, { name: guild.name, way: GUILD_DISMISS_WAY.GAME }, ip); - for(let roleId of members) { - reportTAEvent(roleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.DISMISS }, ip); - updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: '' }]); - } - leaveRaceWhenDismissToRemote(serverId, code); - - return resResult(STATUS.SUCCESS, { code, status: guild.status }); - } - - // 成员退出军团 - async quit(msg: guildInter & { code: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - const ip = session.get('ip'); - const { code } = msg; - - const userGuild = await UserGuildModel.quit(code, roleId); - if (!userGuild) return resResult(STATUS.GUILD_QUIT_ERROR); - - const role = await RoleModel.quitGuild(roleId, nowSeconds()); - if (!role) return resResult(STATUS.GUILD_QUIT_ERROR); - - const guild = await GuildModel.quit(code, roleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); - if (!guild) return resResult(STATUS.GUILD_QUIT_ERROR); - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: '' }]); - await memberQuitGuildToLeague(guild, role); - - //删除排名信息 - await removeBossRank(code, roleId); - await removeTrainRank(code, roleId, guild.trainId); - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [roleName]); - await pushGuildMemberQuit(roleId, code, guild, sid); - - setUserGuildSession(session, null); - reportTAEvent(roleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.QUIT }, ip); - changeGuildActivity('', serverId, roleId, sid); - leaveRaceWhenQuitGuildToRemote(serverId, guildCode, roleId); - guildPayQuitGuild(serverId, code, roleId); - leaveCity(true, roleId, serverId, guildCode); - - return resResult(STATUS.SUCCESS, { hasGuild: role.hasGuild }); - } - - // 团长踢退出军团 - async kick(msg: guildInter & { code: string, roleId: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const { code, roleId: memberRoleId } = msg; - - const userGuild = await UserGuildModel.quit(code, memberRoleId); - if (!userGuild) return resResult(STATUS.GUILD_KICK_ERROR); - - const role = await RoleModel.quitGuild(memberRoleId, nowSeconds()); - if (!role) return resResult(STATUS.GUILD_KICK_ERROR); - - const guild = await GuildModel.quit(code, memberRoleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); - if (!guild) return resResult(STATUS.GUILD_KICK_ERROR); - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) - await updateUserInfo(REDIS_KEY.USER_INFO, memberRoleId, [{ field: 'guildName', value: '' }]); - await memberQuitGuildToLeague(guild, role); - - //删除排名信息 - await removeBossRank(code, memberRoleId); - await removeTrainRank(code, roleId, guild.trainId); - const { isOnline, sid } = await getRoleOnlineInfo(memberRoleId); - await pushGuildMemberQuit(memberRoleId, code, guild, sid); - - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [role.roleName]); - if(isOnline) { - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid,[{ roleId: memberRoleId, userGuild }]); - changeGuildActivity('', serverId, memberRoleId, sid); - } - - await sendMailByContent(MAIL_TYPE.GUILD_BE_KICK, memberRoleId, { sendName: roleName, params: [guild.name] }); - reportTAEvent(memberRoleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.KICK }); - leaveRaceWhenQuitGuildToRemote(serverId, code, memberRoleId); - guildPayQuitGuild(serverId, code, memberRoleId); - leaveCity(true, memberRoleId, serverId, code); - - return resResult(STATUS.SUCCESS, { memberCnt: guild.memberCnt }); - } - - // 团员弹劾团长 - async impeach(msg: guildInter & { code: string, roleId: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const ip = session.get('ip'); - const { code, roleId: leaderRoleId } = msg; - - // 离线72小时 - const { roleName: oldRoleName, quitTime } = await RoleModel.findByRoleId(leaderRoleId); - if (quitTime > getTimeFun().getBeforeDay(3)) { - return resResult(STATUS.GUILD_LEADER_LOGIN); - } - // 上周周功勋最高的人 - const topUserGuilds = await UserGuildModel.findTopActive(code, 'auth role roleId'); - if (topUserGuilds.length <= 0) { - return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); - } - let topUserGuild: UserGuildType; - for (let userGuild of topUserGuilds) { - let role = await RoleModel.findByRoleId(userGuild.roleId, 'quitTime'); - if (role && role.quitTime > getTimeFun().getBeforeDay(3)) { - topUserGuild = userGuild; break; - } - } - if (!topUserGuild) { - return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); - } - - // 检查元宝是否够 - const role = await RoleModel.findByRoleId(roleId); - if (ARMY.ARMY_IMPEACH_COST > role.gold) { - return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); - } - await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_IMPEACH_COST)], ITEM_CHANGE_REASON.GUILD_IMPEACH); - - const topUser = topUserGuild.role; - // 交换 - - let oldLeaderUserGuild = await UserGuildModel.updateInfo(leaderRoleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}, 'auth'); // 团长撤 - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: leaderRoleId, userGuild: oldLeaderUserGuild }]); // 更新session - - let newLeaderUserGuild = await UserGuildModel.updateInfo(topUserGuild.roleId, { auth: GUILD_AUTH.LEADER, job: GUILD_JOB.DAJIANGJUN }, {}, 'auth'); // 最高功勋人升 - await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: topUserGuild.roleId, userGuild: newLeaderUserGuild }]); // 更新session - - let managerCntInc = topUserGuild.auth == GUILD_AUTH.MANAGER ? -1 : 0; // 管理人数 - - const guild = await GuildModel.updateInfo(code, { leader: topUser._id }, { managerCnt: managerCntInc }, 'managerCnt name leagueCode'); // 如果有转让团长设置leader - - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.IMPEACH, [oldRoleName, topUser.roleName]); - await pushChangeGuildLeader(code, guild.managerCnt, topUser, leaderRoleId); - await sendMailByContent(MAIL_TYPE.GUILD_BE_IMPEACH, leaderRoleId, { sendName: roleName, params: [guild.name] }); - await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, topUser.roleId, { sendName: roleName, params: [guild.name] }); - - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(topUser) }]); - await RoleModel.updateRoleInfo(leaderRoleId, { isGuildLeader: false }); - let newLeader = await RoleModel.updateRoleInfo(topUser.roleId, { isGuildLeader: true }); - await guildAbdicateToLeague(guild, leaderRoleId, newLeader); - reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY.IMPEACH, change_id_after: topUser.roleId }, ip) - - let isOnline = await isRoleOnline(topUser.roleId); - const leader = { ...topUser, ce: topUser.ce, isOnline } - return resResult(STATUS.SUCCESS, { - code, managerCnt: guild.managerCnt, leader - }); - } - - // 升级建筑物等级 - async upStructure(msg: guildInter & { code: string, id: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const { code, id } = msg; - - const guild = await GuildModel.findByCode(code, serverId, 'lv structure activeWeekly lvUpdateTime'); - if (!guild) { - return resResult(STATUS.GUILD_NOT_FOUND); - } - - const { lv, structure } = guild; - const curStructure = structure.find(cur => cur.id == id); - if (!curStructure) { - return resResult(STATUS.GUILD_STRUCTURE_NOT_FOUND); - } - if (id != GUILD_STRUCTURE.ARMY_CENTER && curStructure.lv >= lv) { // 中军大帐以外建筑物 - if (curStructure.lv >= lv) { - return resResult(STATUS.GUILD_STRUCTURE_LV_MAX); - } - } - if (!hasStructureConsume(id, curStructure.lv + 1)) { - return resResult(STATUS.GUILD_STRUCTURE_LV_MAX); - } - const cost = getStructureConsume(id, curStructure.lv); - - const result = await GuildModel.upStructure(code, id, cost, 'code fund structure lv activeWeekly lvUpdateTime name'); - if (!result) { - return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); - } - if (id == GUILD_STRUCTURE.ARMY_CENTER) { - let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await r.setRankWithGuildInfo2(code, result.lv, result.activeWeekly, result.lvUpdateTime, result); - } - - const resultStructure = result.structure.find(cur => cur.id == id); - - // 修改信息 - await pushGuildInfoUpdate(code, { ...result }); - await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'lv', value: result.lv }]); - - // 添加动态 - const structureName = GUILD_STRUCTURE_NAME.get(id); - await addGuildRecord(roleId, code, GUILD_REC_TYPE.STRUCTURE_UP, [structureName, resultStructure.lv.toString()]); - - // 军团频道聊天消息 - pushGuildUpStructureMsg(roleId, roleName, result, resultStructure); - - return resResult(STATUS.SUCCESS, result); - } - - - // 获取动态 - async getRec(msg: guildInter & { code: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const { code } = msg; - - // console.log(startTime) - const list = await GuildRecModel.getGuildRec(code, getTimeFun().getBeforeDayWithHour(3)); - - return resResult(STATUS.SUCCESS, { list }); - } - - // 团长发送消息给军团内所有成员的邮箱 - async sendMail(msg: guildInter & { code: string, info: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const { code, info, myUserGuild } = msg; - - const guild = await GuildModel.findByCode(code, serverId, 'members'); - if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); - - const { members } = guild; - const jobName = myUserGuild.auth == 1? '大将军': '管理'; - //下发邮件 - await sendMailToGuildByContent(MAIL_TYPE.GUILD_MAIL, code, { sendName: `${jobName}:${roleName}`, params: [info] }, guild); - - return resResult(STATUS.SUCCESS, { isSuccess: true }); - } - - // 团长发送世界频道 - async recruit(msg: guildInter & { code: string, info: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - - const { code, info } = msg; - const guild = await GuildModel.findByCode(code, serverId); - if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); - - - // 发送世界频道消息 - let channelId = `${serverId}`; - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.WORLD, channelId, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_RECURIT, JSON.stringify({ guildCode: guild.code, guildName: guild.name, info }), '', ''); - if (!msgData) return resResult(STATUS.WRONG_PARMS); - await pushGroupMsgToRoom(msgData); - - return resResult(STATUS.SUCCESS, { isSuccess: true }); - } - - // 领取活跃奖励 - async receiveActiveBox(msg: guildInter & { code: string, id: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - const { code, id } = msg; - - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) return resResult(STATUS.GUILD_NOT_FOUND); - - let activeDayReward = gameData.guildActiveDayReward.get(id); - if (!activeDayReward) return resResult(STATUS.GUILD_ACTIVE_BOX_NOT_FOUND); - - const guildActive = await getTodayGuildActive(code); - if (guildActive < activeDayReward.activeDayPoint) { - return resResult(STATUS.GUILD_ACTIVE_POINT_NOT_REACH); - } - - if (userGuild.receivedActive.includes(id)) { - return resResult(STATUS.GUILD_ACTIVE_BOX_HAS_RECEIVED); - } - userGuild.receivedActive.push(id); - - let goods = await addItems(roleId, roleName, sid, activeDayReward.reward, ITEM_CHANGE_REASON.GUILD_ACTIVE_REWARD); - userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive: userGuild.receivedActive }, {}, 'receivedActive'); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_RECEIVE_BOX); - return resResult(STATUS.SUCCESS, { goods, receivedActive: userGuild.receivedActive }); - } - - // 查看活跃排行榜 - async getActiveRank(msg: guildInter & {}, session: BackendSession) { - let serverId = session.get('serverId') - const { myUserGuild } = msg; - - let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild.guildCode }); - if (!myRank) { - let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly'); - myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); - } - - return resResult(STATUS.SUCCESS, { ranks, myRank }); - } - - // debug接口: 添加公会活跃值 - async debugAddActive(msg: guildInter & { magicWord: string, code: string, active: number, id: number }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { code, active, id } = msg; - - const result = await addActive(roleId, serverId, id, null, active); - if (result.status == 0) return result.resResult; - const { guild, userGuild } = result; - let today = getZeroPointD(); - let guildActive = await GuildActiveModel.addActive(code, today, active); - - let { activeWeekly } = guild; - await pushGuildInfoUpdate(code, { activeDaily: guildActive? guildActive.active: 0, activeWeekly }); - return resResult(STATUS.SUCCESS, { activeDaily: guildActive? guildActive.active: 0, activeWeekly, myInfo: userGuild }); - } - - // debug接口: 调用定时任务 - async debugWeeklyRask(msg: guildInter & { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - await settleGuildWeekly(); - return resResult(STATUS.SUCCESS); - } - - // debug接口: 添加军团资金 - async debugAdddFund(msg: guildInter & { magicWord: string, code: string, count: number }, session: BackendSession) { - - const { code, count, magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const guild = await GuildModel.updateInfo(code, {}, { fund: count }, 'fund'); - await pushGuildInfoUpdate(code, { fund: guild.fund }); - return resResult(STATUS.SUCCESS, { code, fund: guild.fund }); - } - - // debug接口: 加长会长离线时间 - async debugLeaderLeaveTime(msg: guildInter & { magicWord: string, code: string }, session: BackendSession) { - - const { code, magicWord } = msg; - // if (magicWord !== DEBUG_MAGIC_WORD) { - // return resResult(STATUS.TOKEN_ERR); - // } - const serverId = session.get('serverId'); - const guild = await GuildModel.findByCode(code, serverId); - const leader = guild.leader; - let threeDaysBefore = getTimeFun().getBeforeDay(3); - await RoleModel.updateRoleInfo(leader.roleId, { quitTime: threeDaysBefore }); - - return resResult(STATUS.SUCCESS, { code }); - } - - // debug接口: 情况退军团时间 - async debugClearQuitGuildTime(msg: { magicWord: string, type: number }, session: BackendSession) { - - const { magicWord, type = 0 } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const roleId = session.get('roleId'); - const quitGuildTime = type ? Math.floor((new Date().getTime() - HOUR_TO_MS * 2) / 1000) : 0; - await RoleModel.updateRoleInfo(roleId, { quitGuildTime: quitGuildTime }); - - return resResult(STATUS.SUCCESS); - } - - // debug接口: 加入公会 - async debugJoinGuild(msg: guildInter & { magicWord: string, code: string }, session: BackendSession) { - const { code, magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - - const guild = await GuildModel.findByCode(code, serverId); - if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); - - const { isMemberMax, isAuto, ceLimit, lv } = guild; - - let role = await RoleModel.findByRoleId(roleId); - if (role.guildCode) { - let oldCode = role.guildCode; - const userGuild = await UserGuildModel.quit(oldCode, roleId); - if (!userGuild) return resResult(STATUS.GUILD_QUIT_ERROR); - - role = await RoleModel.quitGuild(roleId, nowSeconds()); - if (!role) return resResult(STATUS.GUILD_QUIT_ERROR); - - const guild = await GuildModel.quit(oldCode, roleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); - if (!guild) return resResult(STATUS.GUILD_QUIT_ERROR); - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) - - //删除排名信息 - await removeBossRank(oldCode, roleId); - await removeTrainRank(oldCode, roleId, guild.trainId); - // 添加动态 - await addGuildRecord(roleId, oldCode, GUILD_REC_TYPE.QUIT_GUILD, [roleName]); - await pushGuildMemberQuit(roleId, oldCode, guild, sid); - - setUserGuildSession(session, userGuild); - } - - const joinResult = await joinGuild(code, guild.name, lv, roleId, serverId, session); - if (joinResult.status == -1) { - return joinResult.resResult; - } - - // 添加动态 - await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); - // 更新人数增加 - await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); - return resResult(STATUS.SUCCESS, { code }); - } -} - +import { Application, BackendSession, ChannelService, HandlerService, } from 'pinus'; +import { resResult, getRandEelm, shouldRefresh, sortArrRandom } from '@pubUtils/util'; +import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE, REDIS_KEY, GUILD_SELECT, USER_GUILD_SELECT, TASK_TYPE, DEBUG_MAGIC_WORD, CHANNEL_PREFIX, MSG_TYPE, MSG_SOURCE, ITEM_CHANGE_REASON, TA_EVENT, GUILD_DISMISS_WAY, GUILD_MASTER_CHANGE_WAY, GUILD_QUIT_WAY, PUSH_ROUTE } from '../../../consts'; +import { UserGuildModel, UserGuildType } from '@db/UserGuild'; +import { checkAuth, joinGuild, getUserGuildWithRefActive, addActive, settleGuildWeekly, getMyGuildInfo, setUserGuildSession, getInvitationList, addGuildRecord, pushChangeGuildLeader, pushGuildMemberQuit, pushGuildDismiss, pushGuildInfoUpdate, getTodayGuildActive, getGuildQuitCdTime } from '../../../services/guildService'; +import { GuildModel, GuildType, GuildUpdateParam } from '@db/Guild'; +import { RoleModel, RoleType } from '@db/Role'; +import { ARMY } from '@pubUtils/dicParam'; +import { handleCost, addItems, getGoldObject } from '../../../services/role/rewardService'; +import { nowSeconds, getTimeFun, getSeconds, getZeroPointD, DAY_TO_MS, HOUR_TO_MS } from '@pubUtils/timeUtil'; +import { GuildListInfo, GuildMemberParam } from '@domain/battleField/guild'; +import { GuildLeader } from '@domain/rank'; +import { UserGuildApplyModel } from '@db/UserGuildApply'; +import { hasStructureConsume, getStructureConsume, gameData } from '@pubUtils/data'; +import { GuildRecModel } from '@db/GuildRec'; +import { sendMailByContent, SendMailFun, sendMailToGuildByContent } from '../../../services/mailService'; +import { updateUserInfo, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService'; + +import { openGuildRefine } from '../../../services/guildRefineService'; +import { unlockTrain } from '../../../services/guildTrainService'; +import { removeBossRank } from '../../../services/guildBossService'; +import { removeTrainRank } from '../../../services/guildTrainService'; +import { pushGuildNoticeUpdateMsg, pushGuildUpStructureMsg, addRoleToGuildChannel, getGuildChannelSid, createGroupMsg, pushGroupMsgToRoom } from '../../../services/chatService'; +import { Rank } from '../../../services/rankService'; +import { checkTask } from '../../../services/task/taskService'; +import { guildInter } from '@pubUtils/interface'; +import * as dicParam from '@pubUtils/dicParam'; +import { reportTAEvent } from '../../../services/sdkService'; +import { changeGuildActivity, guildDismisActivity, guildPayQuitGuild } from '../../../services/activity/guildPayService'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; +import { GuildActiveModel } from '@db/GuildActive'; +import { leaveRaceActivityToRemote, leaveRaceWhenDismissToRemote, leaveRaceWhenQuitGuildToRemote } from '../../../services/guildActivity/guildActivityService'; +import { getGVGInfoInGuild } from '../../../services/gvg/gvgService'; +import { guildAbdicateToLeague, guildDismissToLeague, memberQuitGuildToLeague } from '../../../services/gvg/gvgTeamService'; +import { leaveCity } from '../../../services/gvg/gvgBattleService'; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildHandler(app); +} + +export class GuildHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 创建军团 + async createGuild(msg: guildInter & { guildCode: string } & { name: string, icon: number, notice: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { name, icon, notice, guildCode } = msg; + + // 检查名字是否重 + const checkNameResult = await GuildModel.checkName(name, serverId); + if (checkNameResult) return resResult(STATUS.GUILD_NAME_DUP); + + // 检查元宝是否够 + const role = await RoleModel.findByRoleId(roleId); + if (ARMY.ARMY_CREAT_COST > role.gold) { + return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); + } + + // 检查是否充值过 + if(ARMY.ARMY_CREAT_CONDITION > role.totalPay) { + return resResult(STATUS.GUILD_PAY_CONDITION); + } + if(role.lv < 16) return resResult(STATUS.LV_LIMIT); + + await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_CREAT_COST)], ITEM_CHANGE_REASON.CREATE_GUILD); + + // 创建公会 + const guild = await GuildModel.createGuild({ guildCode, name, icon, notice }, role, serverId); + if (!guild) return resResult(STATUS.GUILD_CREATE_ERROR); + guild.leader = guild.leader; + //创建科技树 + await openGuildRefine(guild.code); + await unlockTrain(guild.code, 1); + const userGuild = await UserGuildModel.createUserGuild(guild.code, role, true); + if (!userGuild) return resResult(STATUS.GUILD_CREATE_ERROR); + + await RoleModel.joinGuild(roleId, guild.code, guild.name, true); + await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 + + // 加入排行 + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild); + let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await r2.setRankWithGuildInfo2(guild.code, guild.lv, guild.activeWeekly, Date.now(), guild); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: name }]); + + let rank = await r.getMyRank({ guildCode: guild.code }); + + // 加入channel + setUserGuildSession(session, userGuild); + addRoleToGuildChannel(roleId, sid, guild.code); + + // 添加动态 + await addGuildRecord(roleId, guild.code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); + + // 返回 + const result = { ...guild, rank, myInfo: { ...userGuild, isOnline: true } }; + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_JOIN); + return resResult(STATUS.SUCCESS, result); + } + + // 获取军团列表 + async getGuildList(msg: guildInter & { page: number, showPeopleMax: boolean, name: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + // const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { page = 1, showPeopleMax, name } = msg; + + const guildList = await GuildModel.getGuildList(page, showPeopleMax, name, serverId); + const applyList = await UserGuildApplyModel.findApplyByRole(roleId); + + const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId); + + const list = new Array(); + for (let guild of guildList) { + let info = new GuildListInfo(guild); + + let hasApply = applyList.find(cur => cur.guildCode == guild.code); + info.setApply(!!hasApply); + list.push(info); + } + return resResult(STATUS.SUCCESS, { quitTime, cdTime: await getGuildQuitCdTime(serverId), list }); + } + + // 团长修改军团名等信息 + async setGuildInfo(msg: guildInter & { code: string, name: string, notice: string, introduce: string, ceLimit: number, isAuto: boolean, icon: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const { code, name, notice, introduce, ceLimit, isAuto, icon } = msg; + if (!code) return resResult(STATUS.WRONG_PARMS); + + // 检查名字是否重 + if(name != undefined) { + const checkNameResult = await GuildModel.checkName(name, serverId); + if (checkNameResult) return resResult(STATUS.GUILD_NAME_DUP); + } + + const select = ['code', 'name', 'notice', 'introduce', 'ceLimit', 'isAuto', 'icon', '+members']; + let updateInfo: GuildUpdateParam = {}; + if(name != undefined) updateInfo.name = name; + if(notice != undefined) updateInfo.notice = notice; + if(introduce != undefined) updateInfo.introduce = introduce; + if(ceLimit != undefined) updateInfo.ceLimit = ceLimit; + if(isAuto != undefined) updateInfo.isAuto = isAuto; + if(icon != undefined) updateInfo.icon = icon; + const guild = await GuildModel.updateInfo(code, updateInfo, {}, select.join(' ')); + await pushGuildInfoUpdate(code, { name, notice, introduce, ceLimit, isAuto }); + + if(name != undefined) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]); + for(let roleId of guild.members) { + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: name }]); + } + await RoleModel.updateGuildName(code, name); + } + if (notice != undefined) { + pushGuildNoticeUpdateMsg(roleId, roleName, guild); + } + if(icon != undefined) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'icon', value: icon }]); + } + // 返回 + return resResult(STATUS.SUCCESS, { ...guild }); + } + + // 游客查看军团详细信息 + async getGuildInfo(msg: guildInter & { code: string }, session: BackendSession) { + + const serverId = session.get('serverId'); + const { code } = msg; + + const select = ['code', 'name', 'notice', 'ceLimit', 'isAuto', 'icon', 'lv', 'memberCnt', 'guildCe']; + const guild = await GuildModel.findByCode(code, null, select.join(' ')); + if(!guild) return resResult(STATUS.GUILD_NOT_FOUND); + let leader = guild.leader; + delete guild.leader; + // 返回 + return resResult(STATUS.SUCCESS, { ...guild, leader: leader.roleName }); + + } + + // 团长授权头衔 + async setAuth(msg: guildInter & { roleId: string, auth: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const ip = session.get('ip'); + const { roleId: memberRoleId, auth, myUserGuild, hisUserGuild } = msg; + + const { guildCode: code } = myUserGuild; + + if (auth == hisUserGuild.auth) { + return resResult(STATUS.GUILD_AUTH_NOT_CHANGE); + } + + // 管理员最大数 等策划表 + let guild = await GuildModel.findByCode(code, serverId, 'managerCnt lv leagueCode'); + if (!guild) { + return resResult(STATUS.GUILD_NOT_FOUND); + } + + let managerCntInc = 0; + if (auth == GUILD_AUTH.LEADER) { // 转让团长 + if (hisUserGuild.auth == GUILD_AUTH.MANAGER) { + managerCntInc = -1; + } + } else { + managerCntInc = auth == GUILD_AUTH.MANAGER ? 1 : -1; + } + + let maxManagerCnt = gameData.centerBase.get(guild.lv); + if (!maxManagerCnt) return STATUS.DIC_DATA_NOT_FOUND; + + if (guild.managerCnt + managerCntInc > maxManagerCnt.managerNum) { + return resResult(STATUS.GUILD_MANAGER_REACH_MAX); + } + + const userGuild = await UserGuildModel.updateInfo(memberRoleId, { auth, job: auth == GUILD_AUTH.LEADER ? GUILD_JOB.DAJIANGJUN : hisUserGuild.job }, {}, 'auth'); // 设置权限 + if (!userGuild) { + return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); + } + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: memberRoleId, userGuild }]); + + const role = await RoleModel.findByRoleId(memberRoleId); + let updateObject = {}; + if (auth == GUILD_AUTH.LEADER) { // 转让团长 + updateObject['leader'] = role._id; + let myUserGuild = await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}); // 自己降权限 + setUserGuildSession(session, myUserGuild); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(role) }]); + await RoleModel.updateRoleInfo(memberRoleId, { isGuildLeader: true }); + await RoleModel.updateRoleInfo(roleId, { isGuildLeader: false }); + await guildAbdicateToLeague(guild, roleId, role); + } + + guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader + let chatSid = await getGuildChannelSid(code); + + // 添加动态 + if (auth == GUILD_AUTH.MANAGER) { + await pushGuildInfoUpdate(code, { managerCnt: guild.managerCnt }); + await addGuildRecord(roleId, code, GUILD_REC_TYPE.SET_MANAGER, [role.roleName]); + await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MANAGER, memberRoleId, { sendName: roleName, params: [guild.name] }); + } else if (auth == GUILD_AUTH.LEADER) { + await pushChangeGuildLeader(code, guild.managerCnt, role, roleId); + await addGuildRecord(roleId, code, GUILD_REC_TYPE.SET_LEADER, [roleName, role.roleName]); + await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, memberRoleId, { sendName: roleName, params: [guild.name] }); + + reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY, change_id_after: memberRoleId }, ip); + } else { + await pushGuildInfoUpdate(code, { managerCnt: guild.managerCnt }); + await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MEMBER, memberRoleId, { sendName: roleName, params: [guild.name] }); + } + + + // 返回 + return resResult(STATUS.SUCCESS, { + roleId: memberRoleId, auth: userGuild.auth, managerCnt: guild.managerCnt + }); + + } + + // 团员获取自己军团详细信息 + async getMyGuildInfo(msg: guildInter & {}, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) { + return resResult(STATUS.SUCCESS, { hasGuild: false }) + }; + + let guild = await GuildModel.findByCode(userGuild.guildCode, serverId, '+serverId'); + if (!guild) { + return resResult(STATUS.GUILD_NOT_FOUND); + } + + let result = await getMyGuildInfo(roleId, sid, userGuild, guild, serverId, session); + let gvg = await getGVGInfoInGuild(roleId, guild); + return resResult(STATUS.SUCCESS, { ...result, gvg }); + } + + // 玩家申请公会 + async applyGuild(msg: guildInter & { code: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const { code } = msg; + + const guild = await GuildModel.findByCode(code, serverId); + if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); + + const { isMemberMax, isAuto, ceLimit, lv } = guild; + if (isMemberMax) { + return resResult(STATUS.GUILD_MEMBER_MAX); + } + + const role = await RoleModel.findByRoleId(roleId, null, true); + if (ceLimit > role.ce) { + return resResult(STATUS.GUILD_NOT_REACH_CONDI); + } + if(role.lv < 16) return resResult(STATUS.LV_LIMIT); + + if(nowSeconds() - role.quitGuildTime < (await getGuildQuitCdTime(serverId)) * 60) { + return resResult(STATUS.GUILD_QUIT_TIME); + } + + let hasGuild = false; + if (isAuto) { // 自动加入 + const joinResult = await joinGuild(code, guild.name, lv, roleId, serverId, session); + if (joinResult.status == -1) { + return joinResult.resResult; + } + + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); + // 更新人数增加 + await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); + + hasGuild = true; + } else { // 不自动加入,插入申请表 + await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.APPLY); + } + + // 返回 + return resResult(STATUS.SUCCESS, { code, hasGuild }); + } + + // 玩家申请公会 + async getApplyList(msg: guildInter & { code: string, lastApplyCode: string }, session: BackendSession) { + + const { code, lastApplyCode } = msg; + + const result = await UserGuildApplyModel.findApplyByGuild(code, lastApplyCode); + const list = []; + for (let cur of result) { + let role = cur.role; + delete cur.role; + let isOnline = await isRoleOnline(role.roleId); + list.push({ applyCode: cur.applyCode, ...role, isOnline, createTime: getSeconds(cur.createdAt) }); + } + + return resResult(STATUS.SUCCESS, { list }); + } + + // 团长同意/拒绝公会申请 + async receiveApply(msg: guildInter & { code: string, applyCodeList: [string], isReceived: boolean }, session: BackendSession) { + + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const { code, applyCodeList, isReceived } = msg; + + const applyList = await UserGuildApplyModel.getListByApplyCode(applyCodeList); + + const guild = await GuildModel.findByCode(code, serverId); + let roleIds = new Array(); + if (isReceived) { // 同意申请,加入 + + for (let { roleId } of applyList) { + const joinResult = await joinGuild(code, guild.name, guild.lv, roleId, serverId, session); + if (joinResult.status == -1) continue; + // 更新人数增加 + await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]); + roleIds.push(roleId); + } + } else { // 拒绝申请,删除申请 + for (let { roleId } of applyList) { + await sendMailByContent(MAIL_TYPE.GUILD_APPLY_REFUSE, roleId, { sendName: roleName, params: [guild.name] }); + roleIds.push(roleId); + } + + await UserGuildApplyModel.deleteByApplyCode(applyCodeList); + } + + return resResult(STATUS.SUCCESS, { roleIds }); + } + + // 团长查看(刷新)可邀请人列表 + async getInviteMemberList(msg: guildInter & {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { myUserGuild: myGuild } = msg; + let guild = await GuildModel.findByCode(myGuild.guildCode, serverId, GUILD_SELECT.INVITED_MEMBER); + let invitedMembers = guild.invitedMembers; + if (shouldRefresh(guild.inviteTime, new Date())) { + invitedMembers = []; + } + + // 离线时间,三天内在线且尚未加入军团。按以下规则排序 离线时间 玩家等级 玩家战力 + + const day = getTimeFun().getBeforeDay(3); + + const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId); + let allList = await RoleModel.getInviteList(day, serverId); + allList = allList.filter(cur => !invitedMembers.includes(cur.roleId)) + let list = getRandEelm(allList, 10); + if (!list.length) list = allList; + list = sortArrRandom(list); + + let result = []; + for (let cur of list) { + let isOnline = await isRoleOnline(cur.roleId); + result.push({ ...cur, isOnline }) + } + + return resResult(STATUS.SUCCESS, { quitTime, list: result }); + + } + + // 团长(一键)邀请人 + async inviteMember(msg: guildInter & { code: string, roleIds: string[] }, session: BackendSession) { + + const serverId = session.get('serverId'); + const { code, roleIds } = msg; + + const guild = await GuildModel.findByCode(code, serverId, GUILD_SELECT.INVITED_MEMBER); + if (guild.isMemberMax) return resResult(STATUS.GUILD_MEMBER_MAX); + + const roleList = await RoleModel.findByRoleIds(roleIds); + let result = new Array(); + + for (let role of roleList) { + if (!role.hasGuild || role.serverId == serverId) { + let apply = await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.INVITE); + result.push(role.roleId); + let hisInfo = await getRoleOnlineInfo(role.roleId); + if (hisInfo.isOnline) { + let guild = apply.guild; + let leader = guild.leader; + let invitation = { applyCode: apply.applyCode, ...guild, leader: leader.roleName }; + sendMessageToUserWithSuc(role.roleId, PUSH_ROUTE.GUILD_INVITE, { invitation }, hisInfo.sid); + } + } + } + if(result.length <= 0) { + return resResult(STATUS.GUILD_CANNOT_INVITE) + } + + await GuildModel.recordInvitedMember(code, serverId, roleIds, shouldRefresh(guild.inviteTime, new Date())); + + return resResult(STATUS.SUCCESS, { roleIds: result }); + + } + + // 成员收到邀请列表 + async getInvitationList(msg: guildInter & { lastApplyCode: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const { lastApplyCode } = msg; + let list = await getInvitationList(roleId, lastApplyCode); + + return resResult(STATUS.SUCCESS, { list }); + + } + + + // 成员同意/拒绝邀请 + async receiveInvitation(msg: guildInter & { applyCode: string, isReceived: boolean }, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { applyCode, isReceived } = msg; + + const invite = await UserGuildApplyModel.findByCode(applyCode); + if (!invite) return resResult(STATUS.GUILD_INVITE_NOT_FOUND); + + let code: string; + if (isReceived) { // 同意申请,加入 + + const role = await RoleModel.findByRoleId(roleId, 'lv'); + if(role.lv < 16) return resResult(STATUS.LV_LIMIT); + + const { guildCode } = invite; + const guild = await GuildModel.findByCode(guildCode, serverId); + if (!guild) { + await UserGuildApplyModel.deleteByApplyCode([applyCode]); // 删除这条邀请 + return resResult(STATUS.GUILD_DELETE_ERROR); + } + + const joinResult = await joinGuild(guildCode, guild.name, guild.lv, roleId, serverId, session); + if (joinResult.status == -1) { + return joinResult.resResult; + } + + // 更新人数增加 + await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]); + + code = guild.code; + } + await UserGuildApplyModel.deleteByApplyCode([applyCode]); // 删除这条邀请 + + return resResult(STATUS.SUCCESS, { applyCode, code, isReceived, hasGuild: isReceived }); + } + + // 获取军团成员 + async getGuildMember(msg: { code: string, sort: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const guildAuth: number = session.get('guildAuth'); + // const serverId = session.get('serverId'); + const { code, sort } = msg; + + let select = ['role', 'job']; + const checkDetailResult = await checkAuth(GUILD_OPERATE.GET_MEMBER_LIST_DETAIL, code, guildAuth); + if (checkDetailResult) { + select.push('auth', 'activeWeekly activeUpdateTime'); + } + let list = await UserGuildModel.getListByGuild(code, select.join(' '), { auth: 1 }); + let result: GuildMemberParam[] = []; + for (let cur of list) { + let role = cur.role; + if(role) { + let param = new GuildMemberParam(cur, role); + param.setOnline(role.loginTime == role.quitTime); + result.push(param); + } + } + + if (result && result.length > 0) { + let leader = result.shift(); // 团长在最上面 + result.sort((a, b) => { + if (sort == 'active') { + if (b.activeWeekly == a.activeWeekly) { + return a.activeUpdateTime - b.activeUpdateTime + } else { + return b.activeWeekly - a.activeWeekly + } + } else if (sort == 'loginTime') { + return b.quitTime - a.quitTime; + } else { + return b.ce - a.ce; + } + }); + result.unshift(leader); + } else { + // 此处应有异常 + } + return resResult(STATUS.SUCCESS, { list: result }); + } + + // 团长解散军团 + async dismiss(msg: guildInter & { code: string }, session: BackendSession) { + + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleId = session.get('roleId'); + const ip = session.get('ip'); + const { code } = msg; + + let guild = await GuildModel.findByCode(code, serverId, 'leagueCode'); + if(guild.leagueCode) return resResult(STATUS.GVG_GUILD_HAS_LEAGUE); + + guild = await GuildModel.dismiss(code, serverId); + if (!guild) return resResult(STATUS.GUILD_DELETE_ERROR); + + await sendMailToGuildByContent(MAIL_TYPE.GUILD_DISSMISS, code, {}, guild); + await UserGuildModel.dismiss(code); + const { members } = guild; + await RoleModel.dissmissGuild(members); + await UserGuildApplyModel.deleteApplyByGuild(code); + await guildDismissToLeague(guild); + + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast(members.map(roleId => { return { roleId, userGuild: null } })); // 更新session + + // 删除channel + await guildDismisActivity(code, serverId); + await pushGuildDismiss(code); + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await r.removeFromRank({ guildCode: code }); + let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await r2.removeFromRank({ guildCode: code }); + reportTAEvent(roleId, TA_EVENT.GUILD_DISMISS, { name: guild.name, way: GUILD_DISMISS_WAY.GAME }, ip); + for(let roleId of members) { + reportTAEvent(roleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.DISMISS }, ip); + updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: '' }]); + } + leaveRaceWhenDismissToRemote(serverId, code); + + return resResult(STATUS.SUCCESS, { code, status: guild.status }); + } + + // 成员退出军团 + async quit(msg: guildInter & { code: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + const ip = session.get('ip'); + const { code } = msg; + + const userGuild = await UserGuildModel.quit(code, roleId); + if (!userGuild) return resResult(STATUS.GUILD_QUIT_ERROR); + + const role = await RoleModel.quitGuild(roleId, nowSeconds()); + if (!role) return resResult(STATUS.GUILD_QUIT_ERROR); + + const guild = await GuildModel.quit(code, roleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); + if (!guild) return resResult(STATUS.GUILD_QUIT_ERROR); + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: '' }]); + await memberQuitGuildToLeague(guild, role); + + //删除排名信息 + await removeBossRank(code, roleId); + await removeTrainRank(code, roleId, guild.trainId); + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [roleName]); + await pushGuildMemberQuit(roleId, code, guild, sid); + + setUserGuildSession(session, null); + reportTAEvent(roleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.QUIT }, ip); + changeGuildActivity('', serverId, roleId, sid); + leaveRaceWhenQuitGuildToRemote(serverId, guildCode, roleId); + guildPayQuitGuild(serverId, code, roleId); + leaveCity(true, roleId, serverId, guildCode); + + return resResult(STATUS.SUCCESS, { hasGuild: role.hasGuild }); + } + + // 团长踢退出军团 + async kick(msg: guildInter & { code: string, roleId: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const { code, roleId: memberRoleId } = msg; + + const userGuild = await UserGuildModel.quit(code, memberRoleId); + if (!userGuild) return resResult(STATUS.GUILD_KICK_ERROR); + + const role = await RoleModel.quitGuild(memberRoleId, nowSeconds()); + if (!role) return resResult(STATUS.GUILD_KICK_ERROR); + + const guild = await GuildModel.quit(code, memberRoleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); + if (!guild) return resResult(STATUS.GUILD_KICK_ERROR); + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) + await updateUserInfo(REDIS_KEY.USER_INFO, memberRoleId, [{ field: 'guildName', value: '' }]); + await memberQuitGuildToLeague(guild, role); + + //删除排名信息 + await removeBossRank(code, memberRoleId); + await removeTrainRank(code, roleId, guild.trainId); + const { isOnline, sid } = await getRoleOnlineInfo(memberRoleId); + await pushGuildMemberQuit(memberRoleId, code, guild, sid); + + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [role.roleName]); + if(isOnline) { + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid,[{ roleId: memberRoleId, userGuild }]); + changeGuildActivity('', serverId, memberRoleId, sid); + } + + await sendMailByContent(MAIL_TYPE.GUILD_BE_KICK, memberRoleId, { sendName: roleName, params: [guild.name] }); + reportTAEvent(memberRoleId, TA_EVENT.GUILD_QUIT, { name: guild.name, way: GUILD_QUIT_WAY.KICK }); + leaveRaceWhenQuitGuildToRemote(serverId, code, memberRoleId); + guildPayQuitGuild(serverId, code, memberRoleId); + leaveCity(true, memberRoleId, serverId, code); + + return resResult(STATUS.SUCCESS, { memberCnt: guild.memberCnt }); + } + + // 团员弹劾团长 + async impeach(msg: guildInter & { code: string, roleId: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const ip = session.get('ip'); + const { code, roleId: leaderRoleId } = msg; + + // 离线72小时 + const { roleName: oldRoleName, quitTime } = await RoleModel.findByRoleId(leaderRoleId); + if (quitTime > getTimeFun().getBeforeDay(3)) { + return resResult(STATUS.GUILD_LEADER_LOGIN); + } + // 上周周功勋最高的人 + const topUserGuilds = await UserGuildModel.findTopActive(code, 'auth role roleId'); + if (topUserGuilds.length <= 0) { + return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); + } + let topUserGuild: UserGuildType; + for (let userGuild of topUserGuilds) { + let role = await RoleModel.findByRoleId(userGuild.roleId, 'quitTime'); + if (role && role.quitTime > getTimeFun().getBeforeDay(3)) { + topUserGuild = userGuild; break; + } + } + if (!topUserGuild) { + return resResult(STATUS.GUILD_MEMBER_NOT_FOUND); + } + + // 检查元宝是否够 + const role = await RoleModel.findByRoleId(roleId); + if (ARMY.ARMY_IMPEACH_COST > role.gold) { + return resResult(STATUS.DAILY_REFRESH_GOLD_LACK); + } + await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_IMPEACH_COST)], ITEM_CHANGE_REASON.GUILD_IMPEACH); + + const topUser = topUserGuild.role; + // 交换 + + let oldLeaderUserGuild = await UserGuildModel.updateInfo(leaderRoleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}, 'auth'); // 团长撤 + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: leaderRoleId, userGuild: oldLeaderUserGuild }]); // 更新session + + let newLeaderUserGuild = await UserGuildModel.updateInfo(topUserGuild.roleId, { auth: GUILD_AUTH.LEADER, job: GUILD_JOB.DAJIANGJUN }, {}, 'auth'); // 最高功勋人升 + await this.app.rpc.connector.connectorRemote.setOtherUserGuildSession.broadcast([{ roleId: topUserGuild.roleId, userGuild: newLeaderUserGuild }]); // 更新session + + let managerCntInc = topUserGuild.auth == GUILD_AUTH.MANAGER ? -1 : 0; // 管理人数 + + const guild = await GuildModel.updateInfo(code, { leader: topUser._id }, { managerCnt: managerCntInc }, 'managerCnt name leagueCode'); // 如果有转让团长设置leader + + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.IMPEACH, [oldRoleName, topUser.roleName]); + await pushChangeGuildLeader(code, guild.managerCnt, topUser, leaderRoleId); + await sendMailByContent(MAIL_TYPE.GUILD_BE_IMPEACH, leaderRoleId, { sendName: roleName, params: [guild.name] }); + await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, topUser.roleId, { sendName: roleName, params: [guild.name] }); + + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'leader', value: new GuildLeader(topUser) }]); + await RoleModel.updateRoleInfo(leaderRoleId, { isGuildLeader: false }); + let newLeader = await RoleModel.updateRoleInfo(topUser.roleId, { isGuildLeader: true }); + await guildAbdicateToLeague(guild, leaderRoleId, newLeader); + reportTAEvent(roleId, TA_EVENT.GUILD_MASTER_CHANGE, { way: GUILD_MASTER_CHANGE_WAY.IMPEACH, change_id_after: topUser.roleId }, ip) + + let isOnline = await isRoleOnline(topUser.roleId); + const leader = { ...topUser, ce: topUser.ce, isOnline } + return resResult(STATUS.SUCCESS, { + code, managerCnt: guild.managerCnt, leader + }); + } + + // 升级建筑物等级 + async upStructure(msg: guildInter & { code: string, id: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const { code, id } = msg; + + const guild = await GuildModel.findByCode(code, serverId, 'lv structure activeWeekly lvUpdateTime'); + if (!guild) { + return resResult(STATUS.GUILD_NOT_FOUND); + } + + const { lv, structure } = guild; + const curStructure = structure.find(cur => cur.id == id); + if (!curStructure) { + return resResult(STATUS.GUILD_STRUCTURE_NOT_FOUND); + } + if (id != GUILD_STRUCTURE.ARMY_CENTER && curStructure.lv >= lv) { // 中军大帐以外建筑物 + if (curStructure.lv >= lv) { + return resResult(STATUS.GUILD_STRUCTURE_LV_MAX); + } + } + if (!hasStructureConsume(id, curStructure.lv + 1)) { + return resResult(STATUS.GUILD_STRUCTURE_LV_MAX); + } + const cost = getStructureConsume(id, curStructure.lv); + + const result = await GuildModel.upStructure(code, id, cost, 'code fund structure lv activeWeekly lvUpdateTime name'); + if (!result) { + return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); + } + if (id == GUILD_STRUCTURE.ARMY_CENTER) { + let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await r.setRankWithGuildInfo2(code, result.lv, result.activeWeekly, result.lvUpdateTime, result); + } + + const resultStructure = result.structure.find(cur => cur.id == id); + + // 修改信息 + await pushGuildInfoUpdate(code, { ...result }); + await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'lv', value: result.lv }]); + + // 添加动态 + const structureName = GUILD_STRUCTURE_NAME.get(id); + await addGuildRecord(roleId, code, GUILD_REC_TYPE.STRUCTURE_UP, [structureName, resultStructure.lv.toString()]); + + // 军团频道聊天消息 + pushGuildUpStructureMsg(roleId, roleName, result, resultStructure); + + return resResult(STATUS.SUCCESS, result); + } + + + // 获取动态 + async getRec(msg: guildInter & { code: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const { code } = msg; + + // console.log(startTime) + const list = await GuildRecModel.getGuildRec(code, getTimeFun().getBeforeDayWithHour(3)); + + return resResult(STATUS.SUCCESS, { list }); + } + + // 团长发送消息给军团内所有成员的邮箱 + async sendMail(msg: guildInter & { code: string, info: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const { code, info, myUserGuild } = msg; + + const guild = await GuildModel.findByCode(code, serverId, 'members'); + if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); + + const { members } = guild; + const jobName = myUserGuild.auth == 1? '大将军': '管理'; + //下发邮件 + await sendMailToGuildByContent(MAIL_TYPE.GUILD_MAIL, code, { sendName: `${jobName}:${roleName}`, params: [info] }, guild); + + return resResult(STATUS.SUCCESS, { isSuccess: true }); + } + + // 团长发送世界频道 + async recruit(msg: guildInter & { code: string, info: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + + const { code, info } = msg; + const guild = await GuildModel.findByCode(code, serverId); + if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); + + + // 发送世界频道消息 + let channelId = `${serverId}`; + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.WORLD, channelId, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_RECURIT, JSON.stringify({ guildCode: guild.code, guildName: guild.name, info }), '', ''); + if (!msgData) return resResult(STATUS.WRONG_PARMS); + await pushGroupMsgToRoom(msgData); + + return resResult(STATUS.SUCCESS, { isSuccess: true }); + } + + // 领取活跃奖励 + async receiveActiveBox(msg: guildInter & { code: string, id: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + const { code, id } = msg; + + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) return resResult(STATUS.GUILD_NOT_FOUND); + + let activeDayReward = gameData.guildActiveDayReward.get(id); + if (!activeDayReward) return resResult(STATUS.GUILD_ACTIVE_BOX_NOT_FOUND); + + const guildActive = await getTodayGuildActive(code); + if (guildActive < activeDayReward.activeDayPoint) { + return resResult(STATUS.GUILD_ACTIVE_POINT_NOT_REACH); + } + + if (userGuild.receivedActive.includes(id)) { + return resResult(STATUS.GUILD_ACTIVE_BOX_HAS_RECEIVED); + } + userGuild.receivedActive.push(id); + + let goods = await addItems(roleId, roleName, sid, activeDayReward.reward, ITEM_CHANGE_REASON.GUILD_ACTIVE_REWARD); + userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive: userGuild.receivedActive }, {}, 'receivedActive'); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_RECEIVE_BOX); + return resResult(STATUS.SUCCESS, { goods, receivedActive: userGuild.receivedActive }); + } + + // 查看活跃排行榜 + async getActiveRank(msg: guildInter & {}, session: BackendSession) { + let serverId = session.get('serverId') + const { myUserGuild } = msg; + + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild.guildCode }); + if (!myRank) { + let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly'); + myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); + } + + return resResult(STATUS.SUCCESS, { ranks, myRank }); + } + + // debug接口: 添加公会活跃值 + async debugAddActive(msg: guildInter & { magicWord: string, code: string, active: number, id: number }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { code, active, id } = msg; + + const result = await addActive(roleId, serverId, id, null, active); + if (result.status == 0) return result.resResult; + const { guild, userGuild } = result; + let today = getZeroPointD(); + let guildActive = await GuildActiveModel.addActive(code, today, active); + + let { activeWeekly } = guild; + await pushGuildInfoUpdate(code, { activeDaily: guildActive? guildActive.active: 0, activeWeekly }); + return resResult(STATUS.SUCCESS, { activeDaily: guildActive? guildActive.active: 0, activeWeekly, myInfo: userGuild }); + } + + // debug接口: 调用定时任务 + async debugWeeklyRask(msg: guildInter & { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + await settleGuildWeekly(); + return resResult(STATUS.SUCCESS); + } + + // debug接口: 添加军团资金 + async debugAdddFund(msg: guildInter & { magicWord: string, code: string, count: number }, session: BackendSession) { + + const { code, count, magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const guild = await GuildModel.updateInfo(code, {}, { fund: count }, 'fund'); + await pushGuildInfoUpdate(code, { fund: guild.fund }); + return resResult(STATUS.SUCCESS, { code, fund: guild.fund }); + } + + // debug接口: 加长会长离线时间 + async debugLeaderLeaveTime(msg: guildInter & { magicWord: string, code: string }, session: BackendSession) { + + const { code, magicWord } = msg; + // if (magicWord !== DEBUG_MAGIC_WORD) { + // return resResult(STATUS.TOKEN_ERR); + // } + const serverId = session.get('serverId'); + const guild = await GuildModel.findByCode(code, serverId); + const leader = guild.leader; + let threeDaysBefore = getTimeFun().getBeforeDay(3); + await RoleModel.updateRoleInfo(leader.roleId, { quitTime: threeDaysBefore }); + + return resResult(STATUS.SUCCESS, { code }); + } + + // debug接口: 情况退军团时间 + async debugClearQuitGuildTime(msg: { magicWord: string, type: number }, session: BackendSession) { + + const { magicWord, type = 0 } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const roleId = session.get('roleId'); + const quitGuildTime = type ? Math.floor((new Date().getTime() - HOUR_TO_MS * 2) / 1000) : 0; + await RoleModel.updateRoleInfo(roleId, { quitGuildTime: quitGuildTime }); + + return resResult(STATUS.SUCCESS); + } + + // debug接口: 加入公会 + async debugJoinGuild(msg: guildInter & { magicWord: string, code: string }, session: BackendSession) { + const { code, magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + + const guild = await GuildModel.findByCode(code, serverId); + if (!guild) return resResult(STATUS.GUILD_NOT_FOUND); + + const { isMemberMax, isAuto, ceLimit, lv } = guild; + + let role = await RoleModel.findByRoleId(roleId); + if (role.guildCode) { + let oldCode = role.guildCode; + const userGuild = await UserGuildModel.quit(oldCode, roleId); + if (!userGuild) return resResult(STATUS.GUILD_QUIT_ERROR); + + role = await RoleModel.quitGuild(roleId, nowSeconds()); + if (!role) return resResult(STATUS.GUILD_QUIT_ERROR); + + const guild = await GuildModel.quit(oldCode, roleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER); + if (!guild) return resResult(STATUS.GUILD_QUIT_ERROR); + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) + + //删除排名信息 + await removeBossRank(oldCode, roleId); + await removeTrainRank(oldCode, roleId, guild.trainId); + // 添加动态 + await addGuildRecord(roleId, oldCode, GUILD_REC_TYPE.QUIT_GUILD, [roleName]); + await pushGuildMemberQuit(roleId, oldCode, guild, sid); + + setUserGuildSession(session, userGuild); + } + + const joinResult = await joinGuild(code, guild.name, lv, roleId, serverId, session); + if (joinResult.status == -1) { + return joinResult.resResult; + } + + // 添加动态 + await addGuildRecord(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]); + // 更新人数增加 + await pushGuildInfoUpdate(code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe }); + return resResult(STATUS.SUCCESS, { code }); + } +} + + diff --git a/game-server/app/servers/guild/handler/guildRefineHandler.ts b/game-server/app/servers/guild/handler/guildRefineHandler.ts index 926e9f99d..e23fd89e6 100644 --- a/game-server/app/servers/guild/handler/guildRefineHandler.ts +++ b/game-server/app/servers/guild/handler/guildRefineHandler.ts @@ -1,202 +1,203 @@ -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS, GUILD_OPERATE, TASK_TYPE, ITEM_CHANGE_REASON, ITID, CONSUME_TYPE } from '../../../consts'; -import { GuildRefineModel } from '../../../db/GuildRefine'; -import { gameData, getArmyDevelopConsumeById, getGoodById } from '../../../pubUtils/data'; -import { nowSeconds } from '../../../pubUtils/timeUtil'; -import { handleCost, addItems } from '../../../services/role/rewardService'; -import { GuildModel } from '../../../db/Guild'; -import { findIndex, findWhere } from 'underscore'; -import { lockData } from '../../../services/redLockService'; -import { ARMY } from '../../../pubUtils/dicParam'; -import { CURRENCY_BY_TYPE, CURRENCY_TYPE } from '../../../consts/constModules/itemConst'; -import { checkEquipProduceStructureLv, openGuildRefine, refreshRefinCnt } from '../../../services/guildRefineService'; -import { DATA_NAME } from '../../../consts/dataName'; -import { checkTask } from '../../../services/task/taskService'; -import { guildInter } from '../../../pubUtils/interface'; -import { DicArmyDevelopConsume } from '../../../pubUtils/dictionary/DicArmyDevelopConsume'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildRefineHandler(app); -} - -export class GuildRefineHandler { - constructor(private app: Application) { - - } - /** - * 获得科技树信息 - * @param msg - * @param session - */ - async getRefine(msg: guildInter & {}, session: BackendSession) { - const { myUserGuild: userGuild } = msg; - const { guildCode: code } = userGuild; - let guildRefine = await GuildRefineModel.getRefine(code); - if (!guildRefine) { - guildRefine = await openGuildRefine(code); - } - let { refineCnt } = refreshRefinCnt(userGuild); - return resResult(STATUS.SUCCESS, { scienceTrees: guildRefine.scienceTrees, refineCnt }); - } - /** - * 炼器 - * @param msg - * @param session - */ - async refine(msg: guildInter & { id: number, count: number }, session: BackendSession) { - let { id, count, myUserGuild: userGuild } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - - let dicGoods = gameData.goods.get(id); - if(!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicItid = ITID.get(dicGoods.itid); - if(!dicItid || dicItid.type != CONSUME_TYPE.DRAWING) return resResult(STATUS.GUILD_CANNOT_REFINE_THIS); - - let { guildCode: code } = userGuild; - - let guildRefine = await GuildRefineModel.getRefine(code); - if(!guildRefine) return resResult(STATUS.GUILD_PERSITION_TREE_NOT_LIGHT); - - let { scienceTrees } = guildRefine; - let dicDevelopConsume: DicArmyDevelopConsume; - for(let scienceTree of scienceTrees) { - if(scienceTree.endTime && scienceTree.endTime >= nowSeconds()) continue; // 没有炼完 - let _dicDevelopConsume = getArmyDevelopConsumeById(scienceTree.id); - if(_dicDevelopConsume.quality != dicGoods.quality) continue; // 品质错误 - if(!dicDevelopConsume || dicDevelopConsume.qualityLevel < _dicDevelopConsume.qualityLevel) { // 选择等级最高的 - dicDevelopConsume = _dicDevelopConsume; - } - } - if(!dicDevelopConsume) return resResult(STATUS.GUILD_CANNOT_REFINE_THIS); - - let { refineCnt, refRefineTime } = refreshRefinCnt(userGuild); - let curQualityCnt = refineCnt.find(cur => cur.quality == dicGoods.quality); - let myCnt = curQualityCnt?.count||0; - if(myCnt + count > dicDevelopConsume.max) return resResult(STATUS.GUILD_REFINE_CNT_MAX); - if(!curQualityCnt) { - refineCnt.push({ quality: dicGoods.quality, count }); - } else { - curQualityCnt.count += count; - } - - let result = await handleCost(roleId, sid, dicDevelopConsume.honourConsume.map(cur=> ({...cur, count: cur.count * count })), ITEM_CHANGE_REASON.REFINE_EQUIP); - if (!result) - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - await UserGuildModel.updateInfo(roleId, { refineCnt, refRefineTime }, {}); - - let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.REFINE_EQUIP); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_REFINE, { quality: dicGoods.quality, count }); - return resResult(STATUS.SUCCESS, { goods, refineCnt }); - } - /** - * 点亮科技树 - * @param msg - * @param session - */ - async lightUpTree(msg: guildInter & guildInter & { id: number }, session: BackendSession) { - let { id } = msg; - const serverId: number = session.get('serverId'); - const { myUserGuild: userGuild } = msg - - const { guildCode: code } = userGuild; - let { structure } = await GuildModel.findByCode(code, serverId); - let dicDevelopConsume = getArmyDevelopConsumeById(id); - if (!dicDevelopConsume) return resResult(STATUS.WRONG_PARMS); - - let res: any = await lockData(serverId, DATA_NAME.GUILD_REFINE, code);//加锁 - if (!!res.err) return resResult(STATUS.REDLOCK_ERR); - - if(!checkEquipProduceStructureLv(structure, id)) { - res.releaseCallback(); - return resResult(STATUS.GUILD_EQUIP_PRODUCE_LV_NOT_ENOUGH); - } - - let guildRefine = await GuildRefineModel.getRefine(code); - let nowTime = nowSeconds(); - - for (let scienceTree of guildRefine.scienceTrees) { - if (scienceTree.id == id) {//检查是否点亮过 - res.releaseCallback(); - return resResult(STATUS.GUILD_LIGHT_UP_THE_SCIENCETREE); - } - - if (scienceTree.endTime > nowTime) { - res.releaseCallback(); - return resResult(STATUS.GUILD_SCIENCETREE_IS_RUNNING);//检查是否有在进行的科技研发,若在研发,不允许研发其他科技树 - } - } - - for (let prePosition of dicDevelopConsume.prePositions) { - let preScieceTree = guildRefine.scienceTrees.find(cur => cur.id == prePosition); - if (!preScieceTree || preScieceTree.endTime > nowTime) { - res.releaseCallback(); - return resResult(STATUS.GUILD_PERSITION_TREE_NOT_LIGHT);//前置科技树未点亮 - } - } - //点亮消耗 - const costResult = await GuildModel.costFund(code, dicDevelopConsume.fundConsume); - if (!costResult) { - res.releaseCallback(); - return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); - } - let scienceTree = { id, endTime: nowTime + dicDevelopConsume.timeConsume, assistRoleIds: [] } - let { scienceTrees } = await GuildRefineModel.pushRefine(code, scienceTree); - res.releaseCallback(); - return resResult(STATUS.SUCCESS, { scienceTrees }); - } - /** - * 协助点亮科技树 - * @param msg - * @param session - */ - async assistRefine(msg: guildInter & { id: number }, session: BackendSession) { - let { id, myUserGuild: userGuild } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - - const { guildCode: code } = userGuild; - let res: any = await lockData(serverId, DATA_NAME.GUILD_ASSIST_REFINE, code);//加锁 - if (!!res.err) - return resResult(STATUS.REDLOCK_ERR); - let guildRefine = await GuildRefineModel.getRefine(code); - - let index = findIndex(guildRefine.scienceTrees, { id }); - if (index == -1) { - res.releaseCallback(); - return resResult(STATUS.WRONG_PARMS); - } - let scienceTree = guildRefine.scienceTrees[index]; - if (scienceTree.assistRoleIds.indexOf(roleId) != -1) { - res.releaseCallback(); - return resResult(STATUS.GUILD_IS_ASSISTED_SCIENCETREE); //玩家已经协助过 - } - if (scienceTree.assistRoleIds.length >= ARMY.ARMY_DEVELOPMENT_SPEEDTMES) { - res.releaseCallback(); - return resResult(STATUS.GUILD_REACH_MAX_ASSIST_COUNT); //协助的人数已经达到最大 - } - let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: ARMY.ARMY_DEVELOPMENT_SPEEDCOST }], ITEM_CHANGE_REASON.ASSIST_REFINE); - if (!result) { - res.releaseCallback(); - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - scienceTree.assistRoleIds.push(roleId); - scienceTree.endTime = scienceTree.endTime - ARMY.ARMY_DEVELOPMENT_SPEED * 60; - let { scienceTrees } = await GuildRefineModel.updateRefine(code, { scienceTrees: guildRefine.scienceTrees }) - res.releaseCallback(); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ASSIST_REFINE); - - return resResult(STATUS.SUCCESS, { scienceTrees }); - } -} \ No newline at end of file +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { UserGuildModel } from '@db/UserGuild'; +import { resResult } from '@pubUtils/util'; +import { STATUS, GUILD_OPERATE, TASK_TYPE, ITEM_CHANGE_REASON, ITID, CONSUME_TYPE } from '../../../consts'; +import { GuildRefineModel } from '@db/GuildRefine'; +import { gameData, getArmyDevelopConsumeById, getGoodById } from '@pubUtils/data'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { handleCost, addItems } from '../../../services/role/rewardService'; +import { GuildModel } from '@db/Guild'; +import { findIndex, findWhere } from 'underscore'; +import { lockData } from '../../../services/redLockService'; +import { ARMY } from '@pubUtils/dicParam'; +import { CURRENCY_BY_TYPE, CURRENCY_TYPE } from '@consts/constModules/itemConst'; +import { checkEquipProduceStructureLv, openGuildRefine, refreshRefinCnt } from '../../../services/guildRefineService'; +import { DATA_NAME } from '@consts/dataName'; +import { checkTask } from '../../../services/task/taskService'; +import { guildInter } from '@pubUtils/interface'; +import { DicArmyDevelopConsume } from '@pubUtils/dictionary/DicArmyDevelopConsume'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildRefineHandler(app); +} + +export class GuildRefineHandler { + constructor(private app: Application) { + + } + /** + * 获得科技树信息 + * @param msg + * @param session + */ + async getRefine(msg: guildInter & {}, session: BackendSession) { + const { myUserGuild: userGuild } = msg; + const { guildCode: code } = userGuild; + let guildRefine = await GuildRefineModel.getRefine(code); + if (!guildRefine) { + guildRefine = await openGuildRefine(code); + } + let { refineCnt } = refreshRefinCnt(userGuild); + return resResult(STATUS.SUCCESS, { scienceTrees: guildRefine.scienceTrees, refineCnt }); + } + /** + * 炼器 + * @param msg + * @param session + */ + async refine(msg: guildInter & { id: number, count: number }, session: BackendSession) { + let { id, count, myUserGuild: userGuild } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + + let dicGoods = gameData.goods.get(id); + if(!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicItid = ITID.get(dicGoods.itid); + if(!dicItid || dicItid.type != CONSUME_TYPE.DRAWING) return resResult(STATUS.GUILD_CANNOT_REFINE_THIS); + + let { guildCode: code } = userGuild; + + let guildRefine = await GuildRefineModel.getRefine(code); + if(!guildRefine) return resResult(STATUS.GUILD_PERSITION_TREE_NOT_LIGHT); + + let { scienceTrees } = guildRefine; + let dicDevelopConsume: DicArmyDevelopConsume; + for(let scienceTree of scienceTrees) { + if(scienceTree.endTime && scienceTree.endTime >= nowSeconds()) continue; // 没有炼完 + let _dicDevelopConsume = getArmyDevelopConsumeById(scienceTree.id); + if(_dicDevelopConsume.quality != dicGoods.quality) continue; // 品质错误 + if(!dicDevelopConsume || dicDevelopConsume.qualityLevel < _dicDevelopConsume.qualityLevel) { // 选择等级最高的 + dicDevelopConsume = _dicDevelopConsume; + } + } + if(!dicDevelopConsume) return resResult(STATUS.GUILD_CANNOT_REFINE_THIS); + + let { refineCnt, refRefineTime } = refreshRefinCnt(userGuild); + let curQualityCnt = refineCnt.find(cur => cur.quality == dicGoods.quality); + let myCnt = curQualityCnt?.count||0; + if(myCnt + count > dicDevelopConsume.max) return resResult(STATUS.GUILD_REFINE_CNT_MAX); + if(!curQualityCnt) { + refineCnt.push({ quality: dicGoods.quality, count }); + } else { + curQualityCnt.count += count; + } + + let result = await handleCost(roleId, sid, dicDevelopConsume.honourConsume.map(cur=> ({...cur, count: cur.count * count })), ITEM_CHANGE_REASON.REFINE_EQUIP); + if (!result) + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + await UserGuildModel.updateInfo(roleId, { refineCnt, refRefineTime }, {}); + + let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.REFINE_EQUIP); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_REFINE, { quality: dicGoods.quality, count }); + return resResult(STATUS.SUCCESS, { goods, refineCnt }); + } + /** + * 点亮科技树 + * @param msg + * @param session + */ + async lightUpTree(msg: guildInter & guildInter & { id: number }, session: BackendSession) { + let { id } = msg; + const serverId: number = session.get('serverId'); + const { myUserGuild: userGuild } = msg + + const { guildCode: code } = userGuild; + let { structure } = await GuildModel.findByCode(code, serverId); + let dicDevelopConsume = getArmyDevelopConsumeById(id); + if (!dicDevelopConsume) return resResult(STATUS.WRONG_PARMS); + + let res: any = await lockData(serverId, DATA_NAME.GUILD_REFINE, code);//加锁 + if (!!res.err) return resResult(STATUS.REDLOCK_ERR); + + if(!checkEquipProduceStructureLv(structure, id)) { + res.releaseCallback(); + return resResult(STATUS.GUILD_EQUIP_PRODUCE_LV_NOT_ENOUGH); + } + + let guildRefine = await GuildRefineModel.getRefine(code); + let nowTime = nowSeconds(); + + for (let scienceTree of guildRefine.scienceTrees) { + if (scienceTree.id == id) {//检查是否点亮过 + res.releaseCallback(); + return resResult(STATUS.GUILD_LIGHT_UP_THE_SCIENCETREE); + } + + if (scienceTree.endTime > nowTime) { + res.releaseCallback(); + return resResult(STATUS.GUILD_SCIENCETREE_IS_RUNNING);//检查是否有在进行的科技研发,若在研发,不允许研发其他科技树 + } + } + + for (let prePosition of dicDevelopConsume.prePositions) { + let preScieceTree = guildRefine.scienceTrees.find(cur => cur.id == prePosition); + if (!preScieceTree || preScieceTree.endTime > nowTime) { + res.releaseCallback(); + return resResult(STATUS.GUILD_PERSITION_TREE_NOT_LIGHT);//前置科技树未点亮 + } + } + //点亮消耗 + const costResult = await GuildModel.costFund(code, dicDevelopConsume.fundConsume); + if (!costResult) { + res.releaseCallback(); + return resResult(STATUS.GUILD_FUND_NOT_ENOUGH); + } + let scienceTree = { id, endTime: nowTime + dicDevelopConsume.timeConsume, assistRoleIds: [] } + let { scienceTrees } = await GuildRefineModel.pushRefine(code, scienceTree); + res.releaseCallback(); + return resResult(STATUS.SUCCESS, { scienceTrees }); + } + /** + * 协助点亮科技树 + * @param msg + * @param session + */ + async assistRefine(msg: guildInter & { id: number }, session: BackendSession) { + let { id, myUserGuild: userGuild } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + + const { guildCode: code } = userGuild; + let res: any = await lockData(serverId, DATA_NAME.GUILD_ASSIST_REFINE, code);//加锁 + if (!!res.err) + return resResult(STATUS.REDLOCK_ERR); + let guildRefine = await GuildRefineModel.getRefine(code); + + let index = findIndex(guildRefine.scienceTrees, { id }); + if (index == -1) { + res.releaseCallback(); + return resResult(STATUS.WRONG_PARMS); + } + let scienceTree = guildRefine.scienceTrees[index]; + if (scienceTree.assistRoleIds.indexOf(roleId) != -1) { + res.releaseCallback(); + return resResult(STATUS.GUILD_IS_ASSISTED_SCIENCETREE); //玩家已经协助过 + } + if (scienceTree.assistRoleIds.length >= ARMY.ARMY_DEVELOPMENT_SPEEDTMES) { + res.releaseCallback(); + return resResult(STATUS.GUILD_REACH_MAX_ASSIST_COUNT); //协助的人数已经达到最大 + } + let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: ARMY.ARMY_DEVELOPMENT_SPEEDCOST }], ITEM_CHANGE_REASON.ASSIST_REFINE); + if (!result) { + res.releaseCallback(); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + scienceTree.assistRoleIds.push(roleId); + scienceTree.endTime = scienceTree.endTime - ARMY.ARMY_DEVELOPMENT_SPEED * 60; + let { scienceTrees } = await GuildRefineModel.updateRefine(code, { scienceTrees: guildRefine.scienceTrees }) + res.releaseCallback(); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ASSIST_REFINE); + + return resResult(STATUS.SUCCESS, { scienceTrees }); + } +} + diff --git a/game-server/app/servers/guild/handler/guildTrainHandler.ts b/game-server/app/servers/guild/handler/guildTrainHandler.ts index 3c242c2a5..597cf99d6 100644 --- a/game-server/app/servers/guild/handler/guildTrainHandler.ts +++ b/game-server/app/servers/guild/handler/guildTrainHandler.ts @@ -1,523 +1,524 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { resResult, genCode, getRandSingleEelm } from '../../../pubUtils/util'; -import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, STATUS, TASK_TYPE, TRAIN_REWARD_TYPE } from '../../../consts'; -import { GuildTrainModel } from '../../../db/GuildTrain'; -import { BattleRecordModel } from '../../../db/BattleRecord'; -import { nowSeconds, getTimeFun, getZeroPoint } from '../../../pubUtils/timeUtil'; -import { refreshTrain, getGuildTrainInfo, unlockTrain, getGuildTrainRewards, getGuildTrainInstance, getTrainBoxRewardsResult, resetTrain, getTrainBoxRewardsResultWithoutAlreadyGeted, checkGuildTrainReward, transTrainReward } from '../../../services/guildTrainService'; -import { findIndex, findWhere } from 'underscore' -import { lockData } from '../../../services/redLockService'; -import { GUILD_REPORT_NUM, GUILD_POINT_WAYS } from '../../../consts/constModules/guildConst'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { GuildModel } from '../../../db/Guild'; -import { getArmyTrainJuDian, getTrainBaseByLv, gameData } from '../../../pubUtils/data'; -import { CURRENCY_BY_TYPE, CURRENCY_TYPE } from '../../../consts/constModules/itemConst'; -import { handleCost, addItems } from '../../../services/role/rewardService'; -import { ARMY } from '../../../pubUtils/dicParam'; -import { addActive } from '../../../services/guildService'; -import { GuildTrainReportModel } from '../../../db/GuildTrainReport'; -import { DATA_NAME } from '../../../consts/dataName'; -import { pushGuildTrainSucMsg } from '../../../services/chatService'; -import { checkTaskInGuildTrain } from '../../../services/task/taskService'; -import { guildInter, pvpEndParamInter, RewardInter } from '../../../pubUtils/interface'; -import { getGuildTrainGkInfo } from '../../../pubUtils/data'; -import { getBattleRecordParam } from '../../../services/normalBattleService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildTrainHandler(app); -} - -export class GuildTrainHandler { - constructor(private app: Application) { - - } - - //获得试炼的详情 - async getTrainInstance(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const { myUserGuild } = msg; - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - let guild = await GuildModel.findGuild(code, serverId, 'trainId trainLv code'); - let result = await getGuildTrainInstance(roleId, guild, userGuild); - return resResult(STATUS.SUCCESS, result); - } - //获得试炼战报 - async getTrainReports(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const { myUserGuild } = msg; - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - let trainIds = []; - let { trainId } = await GuildModel.findGuild(code, serverId, 'trainId'); - trainIds.push(trainId); - if (trainId > 1) - trainIds.push(trainId - 1); - let trainReports = await GuildTrainReportModel.findGuildTrainByTrainIds(code, trainIds); - let reports = []; - trainReports.map(({ reports: resReports, trainId: resTrainId }) => { - if (resTrainId != trainId) { - let lenNum = resReports.length; - resReports = resReports.splice(lenNum - GUILD_REPORT_NUM - 1, GUILD_REPORT_NUM);//获得上场的战报的信息与本次战报合并 - } - reports.push(...resReports); - }); - return resResult(STATUS.SUCCESS, { reports }); - } - - //获得试炼宝箱 - async getTrainBoxs(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const { myUserGuild } = msg; - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code, trainBoxRewards = []} = userGuild; - let alreadyGetTrainBoxReards: { [hid: number]: string[] } = {}; // {英雄id:[军团id]} - trainBoxRewards.forEach(item => { - if (typeof item != 'object' || !item.hid || !item.guildCode) { - return; - } - if (!alreadyGetTrainBoxReards[item.hid]) { - alreadyGetTrainBoxReards[item.hid] = []; - } - alreadyGetTrainBoxReards[item.hid].push(item.guildCode); - }); - let resTrainBoxs = await getTrainBoxRewardsResultWithoutAlreadyGeted(code, alreadyGetTrainBoxReards); - return resResult(STATUS.SUCCESS, { trainBoxRewards: resTrainBoxs }); - } - /** - * 挑战练兵副本 - * @param msg - * @param session - */ - async trainBattleStart(msg: guildInter & { hid: number, trainId: number, difficulty: number, battleId: number }, session: BackendSession) { - const { hid, difficulty, trainId, myUserGuild, battleId } = msg; - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = parseInt(session.get('serverId')); - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - if (userGuild.trainCount <= 0) - return resResult(STATUS.GUILD_TRAIN_BATTLE_COUNT_NOT_ENOUGH); - let { trainId: curTeainId, trainLv } = await GuildModel.findGuild(code, serverId, 'trainId trainLv'); - if (curTeainId !== trainId) - return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId, 'trainId isComplete trainInstances'); - if (!guildTrain && guildTrain.isComplete) - return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); - let { trainInstances } = getArmyTrainJuDian(trainId); - let instance = findWhere(trainInstances, { hid }); - if (!instance) - return resResult(STATUS.WRONG_PARMS); - let trainInstance = findWhere(guildTrain.trainInstances, { hid }); - if (!trainInstance) - return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); - if (trainInstance.progress >= instance.progress) { - return resResult(STATUS.GUILD_TRAIN_IS_COMPLETE); - } - const battleCode = genCode(8); // 关卡唯一值 - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { - roleId, roleName, battleId, - status: 0, - record: { heroes: [], trainId, hid, guildCode: code, difficulty, trainLv }, - } - }, true); - return resResult(STATUS.SUCCESS, { battleCode }); - } - /** - * 战斗结算 - * @param msg - * @param session - */ - async trainBattleEnd(msg: guildInter & { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - - const { battleCode, isSuccess, myUserGuild, damageRecords, round } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); - if (!battleRecord || battleRecord.status != 0 || roleId != battleRecord.roleId || battleRecord.record.guildCode != code) { - return resResult(STATUS.WRONG_PARMS); - } - let time = Math.floor(battleRecord.createdAt.getTime() / 1000); - if (userGuild.trainCount - 1 < 0) { - return resResult(STATUS.WRONG_PARMS); - } - - let todayRef = getTimeFun().getTimeWithHour(); // 今天的5点 - if (time < todayRef && nowSeconds() > todayRef) { - return resResult(STATUS.GUILD_TRAIN_IS_RESETED);//重置前进入战斗,重置后回调该接口 - } - if (time > getZeroPoint()) { // 刷新时间,如果是4点算前一天的5点 - userGuild = await UserGuildModel.updateInfo(roleId, {}, { trainCount: -1 });//扣除一次挑战次数 - } - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { status: isSuccess ? 1 : 2, ...getBattleRecordParam(damageRecords, round) } - }, true);//设置战斗状态 - - let { trainId, trainLv, hid, difficulty } = battleRecord.record; - let maxTrainId = gameData.lastGuildTrainIdOfLv.get(trainLv); - let res: any = await lockData(serverId, DATA_NAME.TRAIN, code + '_' + trainId);//加锁 - if (!!res.err) - return resResult(STATUS.REDLOCK_ERR); - try { - - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); - if (!guildTrain) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); - } - let trainInstance = findWhere(guildTrain.trainInstances, { hid }); - if (!trainInstance) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); - } - - let { trainInstances, soloRewardRatio } = getArmyTrainJuDian(trainId); - let dicWar = gameData.war.get(battleRecord.battleId); - if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let instance = findWhere(trainInstances, { hid }); - if (!instance) {//校验是否存在该关卡 - res.releaseCallback();//解锁 - return resResult(STATUS.WRONG_PARMS); - } - let score = isSuccess ? dicWar.winReward.get(TRAIN_REWARD_TYPE.SCORE) : dicWar.failReward.get(TRAIN_REWARD_TYPE.SCORE); - let item = isSuccess ? dicWar.winReward.get(TRAIN_REWARD_TYPE.ITEM) : dicWar.failReward.get(TRAIN_REWARD_TYPE.ITEM); - let addScore = Math.floor(score);//个人获得积分,也是压制进度 - //个人功勋奖励 - let goods = await addItems(roleId, roleName, sid, item, ITEM_CHANGE_REASON.TRAIN_BATTLE_END); - let { isComplete, ranks } = guildTrain; - let reports = []; - // let index = findIndex(ranks, { roleId }); - // if (index !== -1) { - // ranks[index].score += addScore;//更新原有的排名信息 - // } else { - // ranks.push({ score: addScore, roleId });//新增排名 - // } - let needLockNext = false; - let report = { roleName, trainId, hid, score: addScore, time: nowSeconds(), type: isSuccess ? 2 : 1, difficulty };//type 1:失败, 2:成功,3:表示系统战报即:被成功压制 - reports.push(report); - if (trainInstance.progress < instance.progress) { - if (trainInstance.progress + addScore >= instance.progress) { - //压制成功 - if (!isComplete) { - isComplete = true; - guildTrain.trainInstances.forEach(({ hid: otherHid, progress }) => { - if (hid != otherHid && progress != instance.progress) { - isComplete = false; - } - }); - if (isComplete) { //解锁下一关 - needLockNext = true; - } - } - let progress = instance.progress; - guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); - - //type 1:失败, 2:成功,3:表示系统战报即:被成功压制 - reports.push({ type: 3, time: nowSeconds(), score: addScore, roleName, trainId, hid, difficulty }); - pushGuildTrainSucMsg(roleId, roleName, code, hid); - - - if (needLockNext && maxTrainId > trainId) { - guildTrain = await unlockTrain(code, trainId + 1); - } - res.releaseCallback();//解锁 - } else { - //压制失败,更新排行榜进度等信息 - let progress = trainInstance.progress + addScore; - guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); - res.releaseCallback();//解锁 - } - } else { - // //玩家结算前已经完成进度,修改玩家的排名 - // guildTrain = await GuildTrainModel.updateGuildTrain(code, trainId, { ranks }); - res.releaseCallback();//解锁 - } - - await GuildTrainReportModel.pushGuildTrainReports(code, trainId, reports);//增加战报 - let { trainCount, trainRewards } = userGuild; - let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards);//战斗后更新练兵场信息 - result.battleGoods = goods; - result.createdAt = time; - await addActive(roleId, serverId, GUILD_POINT_WAYS.TRAIN); - - // 任务 - await checkTaskInGuildTrain(serverId, roleId, sid, battleRecord.battleId, isSuccess, isComplete); - - return resResult(STATUS.SUCCESS, result); - - } catch(e) { - res.releaseCallback();//解锁 - throw e; - } - } - - /** - * 练兵场扫荡 - * @param msg - * @param session - */ - async trainBattleSweep(msg: guildInter & { hid: number, difficulty: number, trainId: number, battleId: number }, session: BackendSession) { - - const { hid, difficulty, trainId, battleId, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - if (userGuild.trainCount - 1 < 0) { - return resResult(STATUS.WRONG_PARMS); - } - - let hasPassed = await BattleRecordModel.getBattleRecordByIdAndStatus(roleId, battleId, 1); - if(!hasPassed) return resResult(STATUS.GUILD_TRAIN_CANNOT_SWEEP); - - let { trainLv } = await GuildModel.findGuild(code, serverId, 'trainLv'); - let maxTrainId = gameData.lastGuildTrainIdOfLv.get(trainLv); - let res: any = await lockData(serverId, DATA_NAME.TRAIN, code + '_' + trainId);//加锁 - if (!!res.err) - return resResult(STATUS.REDLOCK_ERR); - - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); - if (!guildTrain) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); - } - let trainInstance = findWhere(guildTrain.trainInstances, { hid }); - if (!trainInstance) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); - } - - let { trainInstances } = getArmyTrainJuDian(trainId); - let dicWar = gameData.war.get(battleId); - if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let instance = findWhere(trainInstances, { hid }); - if (!instance) {//校验是否存在该关卡 - res.releaseCallback();//解锁 - return resResult(STATUS.WRONG_PARMS); - } - if (trainInstance.progress >= instance.progress) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_IS_COMPLETE); - } - - userGuild = await UserGuildModel.updateInfo(roleId, {}, { trainCount: -1 });//扣除一次挑战次数 - let score = dicWar.winReward.get(TRAIN_REWARD_TYPE.SCORE); - let item = dicWar.winReward.get(TRAIN_REWARD_TYPE.ITEM); - let addScore = Math.floor(score);//个人获得积分,也是压制进度 - //个人功勋奖励 - let goods = await addItems(roleId, roleName, sid, item, ITEM_CHANGE_REASON.TRAIN_BATTLE_END); - let { isComplete, ranks } = guildTrain; - let reports = []; - let needLockNext = false; - let report = { roleName, trainId, hid, score: addScore, time: nowSeconds(), type: 2, difficulty };//type 1:失败, 2:成功,3:表示系统战报即:被成功压制 - reports.push(report); - if (trainInstance.progress < instance.progress) { - if (trainInstance.progress + addScore >= instance.progress) { - //压制成功 - if (!isComplete) { - isComplete = true; - guildTrain.trainInstances.forEach(({ hid: otherHid, progress }) => { - if (hid != otherHid && progress != instance.progress) { - isComplete = false; - } - }); - if (isComplete) { //解锁下一关 - needLockNext = true; - } - } - let progress = instance.progress; - guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); - - //type 1:失败, 2:成功,3:表示系统战报即:被成功压制 - reports.push({ type: 3, time: nowSeconds(), score: addScore, roleName, trainId, hid, difficulty }); - pushGuildTrainSucMsg(roleId, roleName, code, hid); - - - if (needLockNext && maxTrainId > trainId) { - guildTrain = await unlockTrain(code, trainId + 1); - } - res.releaseCallback();//解锁 - } else { - //压制失败,更新排行榜进度等信息 - let progress = trainInstance.progress + addScore; - guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); - res.releaseCallback();//解锁 - } - } else { - // //玩家结算前已经完成进度,修改玩家的排名 - // guildTrain = await GuildTrainModel.updateGuildTrain(code, trainId, { ranks }); - res.releaseCallback();//解锁 - } - - await GuildTrainReportModel.pushGuildTrainReports(code, trainId, reports);//增加战报 - let { trainCount, trainRewards } = userGuild; - let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards);//战斗后更新练兵场信息 - result.goods = goods; - await addActive(roleId, serverId, GUILD_POINT_WAYS.TRAIN); - - // 任务 - await checkTaskInGuildTrain(serverId, roleId, sid, battleId, true, isComplete); - - return resResult(STATUS.SUCCESS, result); - - } - - /** - * 领取练兵场宝箱 hid:副本id,index:领取位置 - * @param msg - * @param session - */ - async getTrainInstanceBox(msg: guildInter & { trainId: number, hid: number, index: number }, session: BackendSession) { - let { trainId, hid, index, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const roleName: string = session.get('roleName'); - const sid = session.get('sid'); - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - let { trainLv } = await GuildModel.findGuild(code, serverId, 'trainLv'); - let res: any = await lockData(serverId, DATA_NAME.TRAIN_BOX, code + '_' + trainId + '_' + index);//加锁 - if (!!res.err) - return resResult(STATUS.REDLOCK_ERR); - - let { trainInstances } = getArmyTrainJuDian(trainId); - let trainInfo = getGuildTrainGkInfo(trainId, hid); - let { progress } = findWhere(trainInstances, { hid }); - // console.log('progress = ' + progress); - let guildTrain = await GuildTrainModel.findTrainInstanceBoxByIndex(code, trainId, hid, progress); - if (!guildTrain) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); - } - let trainInstance = findWhere(guildTrain.trainInstances, { hid }); - if (trainInstance.endTime < nowSeconds()) { - //宝箱失效 - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_BOX_IS_OVER_TIME); - } - let trainBox = findWhere(trainInstance.trainBoxs, { index }) - if (!!trainBox) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_BOX_INDEX_IS_GOT); - } - trainBox = findWhere(trainInstance.trainBoxs, { roleId }) - if (!!trainBox) { - res.releaseCallback();//解锁 - return resResult(STATUS.GUILD_TRAIN_BOX_IS_GOT); - } - let good = getRandSingleEelm(trainInfo.heroRewards); - let goods = await addItems(roleId, roleName, sid, [good], ITEM_CHANGE_REASON.TRAIN_BOX_REWARD); - - let resGuildTrain = await GuildTrainModel.receiveBoxByIndex(code, roleId, trainId, hid, index, good); - let resUserGuild = await UserGuildModel.receiveTrainBoxRewards(roleId, hid, resGuildTrain.guildCode); - res.releaseCallback();//解锁 - - if (!resGuildTrain || !resUserGuild) { - return resResult(STATUS.GUILD_GET_TRAIN_BOX_FAIL); - } - let result: any = getGuildTrainRewards(resGuildTrain); - - result.goods = goods; - return resResult(STATUS.SUCCESS, result); - } - /** - * 领取练兵试炼等级奖励 - * @param msg - * @param session - */ - async getTrainLvUpRewards(msg: guildInter & { trainId: number }, session: BackendSession) { - let { trainId, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const serverId: number = parseInt(session.get('serverId')); - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); - if (!guildTrain || !guildTrain.isComplete) - return resResult(STATUS.GUILD_TRAIN_IS_NOT_COMPLETE); - let { jinjieReward, trainLv } = getArmyTrainJuDian(trainId); - if (!checkGuildTrainReward(userGuild.trainRewards, trainId)) - return resResult(STATUS.GUILD_TRAIN_QUALITY_REWARD_IS_GOT); - userGuild = await UserGuildModel.receiveTrainRewards(roleId, trainId); - if (!userGuild) { - return resResult(STATUS.INTERNAL_ERR); - } - let goods = await addItems(roleId, roleName, sid, jinjieReward, ITEM_CHANGE_REASON.TRAIN_LV_REWARD); - return resResult(STATUS.SUCCESS, { trainRewards: transTrainReward(userGuild.trainRewards, trainLv), goods }); - } - - //购买挑战次数 - async purchaseTrainCount(msg: guildInter & { count: number }, session: BackendSession) { - let { count, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - const sid: string = session.get('sid'); - let userGuild = await refreshTrain(myUserGuild, roleId, serverId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - if (userGuild.buyTrainCount >= ARMY.ARMY_TRAIN_BUYTIMES) - return resResult(STATUS.GUILD_BUY_TRAIN_COUNT_REACH_MAX); - let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: ARMY.ARMY_TRAIN_TIMESCOST }], ITEM_CHANGE_REASON.TRAIN_BATTLE_BUY_CNT); - if (!result) - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let { trainCount, buyTrainCount } = await UserGuildModel.addTrainCount(roleId, count); - return resResult(STATUS.SUCCESS, { trainCount, buyTrainCount }); - } - - // debug接口: 添加挑战次数 - async debugAddTrainCount(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - const roleId: string = session.get('roleId'); - await UserGuildModel.addTrainCount(roleId, 1); - return resResult(STATUS.SUCCESS); - } - - // debug接口: 重置试炼场 - async debugResetTrainInstance(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - const guildCode: string = session.get('guildCode'); - const serverId: number = session.get('serverId'); - await GuildModel.updateInfo(guildCode, { resetTrainTimeDaily: new Date(Date.now() - 86400000)}) - await resetTrain(guildCode, serverId); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { resResult, genCode, getRandSingleEelm } from '@pubUtils/util'; +import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, STATUS, TASK_TYPE, TRAIN_REWARD_TYPE } from '../../../consts'; +import { GuildTrainModel } from '@db/GuildTrain'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { nowSeconds, getTimeFun, getZeroPoint } from '@pubUtils/timeUtil'; +import { refreshTrain, getGuildTrainInfo, unlockTrain, getGuildTrainRewards, getGuildTrainInstance, getTrainBoxRewardsResult, resetTrain, getTrainBoxRewardsResultWithoutAlreadyGeted, checkGuildTrainReward, transTrainReward } from '../../../services/guildTrainService'; +import { findIndex, findWhere } from 'underscore' +import { lockData } from '../../../services/redLockService'; +import { GUILD_REPORT_NUM, GUILD_POINT_WAYS } from '@consts/constModules/guildConst'; +import { UserGuildModel } from '@db/UserGuild'; +import { GuildModel } from '@db/Guild'; +import { getArmyTrainJuDian, getTrainBaseByLv, gameData } from '@pubUtils/data'; +import { CURRENCY_BY_TYPE, CURRENCY_TYPE } from '@consts/constModules/itemConst'; +import { handleCost, addItems } from '../../../services/role/rewardService'; +import { ARMY } from '@pubUtils/dicParam'; +import { addActive } from '../../../services/guildService'; +import { GuildTrainReportModel } from '@db/GuildTrainReport'; +import { DATA_NAME } from '@consts/dataName'; +import { pushGuildTrainSucMsg } from '../../../services/chatService'; +import { checkTaskInGuildTrain } from '../../../services/task/taskService'; +import { guildInter, pvpEndParamInter, RewardInter } from '@pubUtils/interface'; +import { getGuildTrainGkInfo } from '@pubUtils/data'; +import { getBattleRecordParam } from '../../../services/normalBattleService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildTrainHandler(app); +} + +export class GuildTrainHandler { + constructor(private app: Application) { + + } + + //获得试炼的详情 + async getTrainInstance(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const { myUserGuild } = msg; + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + let guild = await GuildModel.findGuild(code, serverId, 'trainId trainLv code'); + let result = await getGuildTrainInstance(roleId, guild, userGuild); + return resResult(STATUS.SUCCESS, result); + } + //获得试炼战报 + async getTrainReports(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const { myUserGuild } = msg; + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + let trainIds = []; + let { trainId } = await GuildModel.findGuild(code, serverId, 'trainId'); + trainIds.push(trainId); + if (trainId > 1) + trainIds.push(trainId - 1); + let trainReports = await GuildTrainReportModel.findGuildTrainByTrainIds(code, trainIds); + let reports = []; + trainReports.map(({ reports: resReports, trainId: resTrainId }) => { + if (resTrainId != trainId) { + let lenNum = resReports.length; + resReports = resReports.splice(lenNum - GUILD_REPORT_NUM - 1, GUILD_REPORT_NUM);//获得上场的战报的信息与本次战报合并 + } + reports.push(...resReports); + }); + return resResult(STATUS.SUCCESS, { reports }); + } + + //获得试炼宝箱 + async getTrainBoxs(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const { myUserGuild } = msg; + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code, trainBoxRewards = []} = userGuild; + let alreadyGetTrainBoxReards: { [hid: number]: string[] } = {}; // {英雄id:[军团id]} + trainBoxRewards.forEach(item => { + if (typeof item != 'object' || !item.hid || !item.guildCode) { + return; + } + if (!alreadyGetTrainBoxReards[item.hid]) { + alreadyGetTrainBoxReards[item.hid] = []; + } + alreadyGetTrainBoxReards[item.hid].push(item.guildCode); + }); + let resTrainBoxs = await getTrainBoxRewardsResultWithoutAlreadyGeted(code, alreadyGetTrainBoxReards); + return resResult(STATUS.SUCCESS, { trainBoxRewards: resTrainBoxs }); + } + /** + * 挑战练兵副本 + * @param msg + * @param session + */ + async trainBattleStart(msg: guildInter & { hid: number, trainId: number, difficulty: number, battleId: number }, session: BackendSession) { + const { hid, difficulty, trainId, myUserGuild, battleId } = msg; + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = parseInt(session.get('serverId')); + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + if (userGuild.trainCount <= 0) + return resResult(STATUS.GUILD_TRAIN_BATTLE_COUNT_NOT_ENOUGH); + let { trainId: curTeainId, trainLv } = await GuildModel.findGuild(code, serverId, 'trainId trainLv'); + if (curTeainId !== trainId) + return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId, 'trainId isComplete trainInstances'); + if (!guildTrain && guildTrain.isComplete) + return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); + let { trainInstances } = getArmyTrainJuDian(trainId); + let instance = findWhere(trainInstances, { hid }); + if (!instance) + return resResult(STATUS.WRONG_PARMS); + let trainInstance = findWhere(guildTrain.trainInstances, { hid }); + if (!trainInstance) + return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); + if (trainInstance.progress >= instance.progress) { + return resResult(STATUS.GUILD_TRAIN_IS_COMPLETE); + } + const battleCode = genCode(8); // 关卡唯一值 + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { + roleId, roleName, battleId, + status: 0, + record: { heroes: [], trainId, hid, guildCode: code, difficulty, trainLv }, + } + }, true); + return resResult(STATUS.SUCCESS, { battleCode }); + } + /** + * 战斗结算 + * @param msg + * @param session + */ + async trainBattleEnd(msg: guildInter & { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + + const { battleCode, isSuccess, myUserGuild, damageRecords, round } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); + if (!battleRecord || battleRecord.status != 0 || roleId != battleRecord.roleId || battleRecord.record.guildCode != code) { + return resResult(STATUS.WRONG_PARMS); + } + let time = Math.floor(battleRecord.createdAt.getTime() / 1000); + if (userGuild.trainCount - 1 < 0) { + return resResult(STATUS.WRONG_PARMS); + } + + let todayRef = getTimeFun().getTimeWithHour(); // 今天的5点 + if (time < todayRef && nowSeconds() > todayRef) { + return resResult(STATUS.GUILD_TRAIN_IS_RESETED);//重置前进入战斗,重置后回调该接口 + } + if (time > getZeroPoint()) { // 刷新时间,如果是4点算前一天的5点 + userGuild = await UserGuildModel.updateInfo(roleId, {}, { trainCount: -1 });//扣除一次挑战次数 + } + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { status: isSuccess ? 1 : 2, ...getBattleRecordParam(damageRecords, round) } + }, true);//设置战斗状态 + + let { trainId, trainLv, hid, difficulty } = battleRecord.record; + let maxTrainId = gameData.lastGuildTrainIdOfLv.get(trainLv); + let res: any = await lockData(serverId, DATA_NAME.TRAIN, code + '_' + trainId);//加锁 + if (!!res.err) + return resResult(STATUS.REDLOCK_ERR); + try { + + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); + if (!guildTrain) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); + } + let trainInstance = findWhere(guildTrain.trainInstances, { hid }); + if (!trainInstance) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); + } + + let { trainInstances, soloRewardRatio } = getArmyTrainJuDian(trainId); + let dicWar = gameData.war.get(battleRecord.battleId); + if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let instance = findWhere(trainInstances, { hid }); + if (!instance) {//校验是否存在该关卡 + res.releaseCallback();//解锁 + return resResult(STATUS.WRONG_PARMS); + } + let score = isSuccess ? dicWar.winReward.get(TRAIN_REWARD_TYPE.SCORE) : dicWar.failReward.get(TRAIN_REWARD_TYPE.SCORE); + let item = isSuccess ? dicWar.winReward.get(TRAIN_REWARD_TYPE.ITEM) : dicWar.failReward.get(TRAIN_REWARD_TYPE.ITEM); + let addScore = Math.floor(score);//个人获得积分,也是压制进度 + //个人功勋奖励 + let goods = await addItems(roleId, roleName, sid, item, ITEM_CHANGE_REASON.TRAIN_BATTLE_END); + let { isComplete, ranks } = guildTrain; + let reports = []; + // let index = findIndex(ranks, { roleId }); + // if (index !== -1) { + // ranks[index].score += addScore;//更新原有的排名信息 + // } else { + // ranks.push({ score: addScore, roleId });//新增排名 + // } + let needLockNext = false; + let report = { roleName, trainId, hid, score: addScore, time: nowSeconds(), type: isSuccess ? 2 : 1, difficulty };//type 1:失败, 2:成功,3:表示系统战报即:被成功压制 + reports.push(report); + if (trainInstance.progress < instance.progress) { + if (trainInstance.progress + addScore >= instance.progress) { + //压制成功 + if (!isComplete) { + isComplete = true; + guildTrain.trainInstances.forEach(({ hid: otherHid, progress }) => { + if (hid != otherHid && progress != instance.progress) { + isComplete = false; + } + }); + if (isComplete) { //解锁下一关 + needLockNext = true; + } + } + let progress = instance.progress; + guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); + + //type 1:失败, 2:成功,3:表示系统战报即:被成功压制 + reports.push({ type: 3, time: nowSeconds(), score: addScore, roleName, trainId, hid, difficulty }); + pushGuildTrainSucMsg(roleId, roleName, code, hid); + + + if (needLockNext && maxTrainId > trainId) { + guildTrain = await unlockTrain(code, trainId + 1); + } + res.releaseCallback();//解锁 + } else { + //压制失败,更新排行榜进度等信息 + let progress = trainInstance.progress + addScore; + guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); + res.releaseCallback();//解锁 + } + } else { + // //玩家结算前已经完成进度,修改玩家的排名 + // guildTrain = await GuildTrainModel.updateGuildTrain(code, trainId, { ranks }); + res.releaseCallback();//解锁 + } + + await GuildTrainReportModel.pushGuildTrainReports(code, trainId, reports);//增加战报 + let { trainCount, trainRewards } = userGuild; + let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards);//战斗后更新练兵场信息 + result.battleGoods = goods; + result.createdAt = time; + await addActive(roleId, serverId, GUILD_POINT_WAYS.TRAIN); + + // 任务 + await checkTaskInGuildTrain(serverId, roleId, sid, battleRecord.battleId, isSuccess, isComplete); + + return resResult(STATUS.SUCCESS, result); + + } catch(e) { + res.releaseCallback();//解锁 + throw e; + } + } + + /** + * 练兵场扫荡 + * @param msg + * @param session + */ + async trainBattleSweep(msg: guildInter & { hid: number, difficulty: number, trainId: number, battleId: number }, session: BackendSession) { + + const { hid, difficulty, trainId, battleId, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + if (userGuild.trainCount - 1 < 0) { + return resResult(STATUS.WRONG_PARMS); + } + + let hasPassed = await BattleRecordModel.getBattleRecordByIdAndStatus(roleId, battleId, 1); + if(!hasPassed) return resResult(STATUS.GUILD_TRAIN_CANNOT_SWEEP); + + let { trainLv } = await GuildModel.findGuild(code, serverId, 'trainLv'); + let maxTrainId = gameData.lastGuildTrainIdOfLv.get(trainLv); + let res: any = await lockData(serverId, DATA_NAME.TRAIN, code + '_' + trainId);//加锁 + if (!!res.err) + return resResult(STATUS.REDLOCK_ERR); + + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); + if (!guildTrain) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); + } + let trainInstance = findWhere(guildTrain.trainInstances, { hid }); + if (!trainInstance) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_LEVEL_IS_COMPLETE); + } + + let { trainInstances } = getArmyTrainJuDian(trainId); + let dicWar = gameData.war.get(battleId); + if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let instance = findWhere(trainInstances, { hid }); + if (!instance) {//校验是否存在该关卡 + res.releaseCallback();//解锁 + return resResult(STATUS.WRONG_PARMS); + } + if (trainInstance.progress >= instance.progress) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_IS_COMPLETE); + } + + userGuild = await UserGuildModel.updateInfo(roleId, {}, { trainCount: -1 });//扣除一次挑战次数 + let score = dicWar.winReward.get(TRAIN_REWARD_TYPE.SCORE); + let item = dicWar.winReward.get(TRAIN_REWARD_TYPE.ITEM); + let addScore = Math.floor(score);//个人获得积分,也是压制进度 + //个人功勋奖励 + let goods = await addItems(roleId, roleName, sid, item, ITEM_CHANGE_REASON.TRAIN_BATTLE_END); + let { isComplete, ranks } = guildTrain; + let reports = []; + let needLockNext = false; + let report = { roleName, trainId, hid, score: addScore, time: nowSeconds(), type: 2, difficulty };//type 1:失败, 2:成功,3:表示系统战报即:被成功压制 + reports.push(report); + if (trainInstance.progress < instance.progress) { + if (trainInstance.progress + addScore >= instance.progress) { + //压制成功 + if (!isComplete) { + isComplete = true; + guildTrain.trainInstances.forEach(({ hid: otherHid, progress }) => { + if (hid != otherHid && progress != instance.progress) { + isComplete = false; + } + }); + if (isComplete) { //解锁下一关 + needLockNext = true; + } + } + let progress = instance.progress; + guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); + + //type 1:失败, 2:成功,3:表示系统战报即:被成功压制 + reports.push({ type: 3, time: nowSeconds(), score: addScore, roleName, trainId, hid, difficulty }); + pushGuildTrainSucMsg(roleId, roleName, code, hid); + + + if (needLockNext && maxTrainId > trainId) { + guildTrain = await unlockTrain(code, trainId + 1); + } + res.releaseCallback();//解锁 + } else { + //压制失败,更新排行榜进度等信息 + let progress = trainInstance.progress + addScore; + guildTrain = await GuildTrainModel.updateGuildTrainProgress(code, trainId, hid, progress, ranks, isComplete); + res.releaseCallback();//解锁 + } + } else { + // //玩家结算前已经完成进度,修改玩家的排名 + // guildTrain = await GuildTrainModel.updateGuildTrain(code, trainId, { ranks }); + res.releaseCallback();//解锁 + } + + await GuildTrainReportModel.pushGuildTrainReports(code, trainId, reports);//增加战报 + let { trainCount, trainRewards } = userGuild; + let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards);//战斗后更新练兵场信息 + result.goods = goods; + await addActive(roleId, serverId, GUILD_POINT_WAYS.TRAIN); + + // 任务 + await checkTaskInGuildTrain(serverId, roleId, sid, battleId, true, isComplete); + + return resResult(STATUS.SUCCESS, result); + + } + + /** + * 领取练兵场宝箱 hid:副本id,index:领取位置 + * @param msg + * @param session + */ + async getTrainInstanceBox(msg: guildInter & { trainId: number, hid: number, index: number }, session: BackendSession) { + let { trainId, hid, index, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const roleName: string = session.get('roleName'); + const sid = session.get('sid'); + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + let { trainLv } = await GuildModel.findGuild(code, serverId, 'trainLv'); + let res: any = await lockData(serverId, DATA_NAME.TRAIN_BOX, code + '_' + trainId + '_' + index);//加锁 + if (!!res.err) + return resResult(STATUS.REDLOCK_ERR); + + let { trainInstances } = getArmyTrainJuDian(trainId); + let trainInfo = getGuildTrainGkInfo(trainId, hid); + let { progress } = findWhere(trainInstances, { hid }); + // console.log('progress = ' + progress); + let guildTrain = await GuildTrainModel.findTrainInstanceBoxByIndex(code, trainId, hid, progress); + if (!guildTrain) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_SCRIPT_NOT_OPENED); + } + let trainInstance = findWhere(guildTrain.trainInstances, { hid }); + if (trainInstance.endTime < nowSeconds()) { + //宝箱失效 + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_BOX_IS_OVER_TIME); + } + let trainBox = findWhere(trainInstance.trainBoxs, { index }) + if (!!trainBox) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_BOX_INDEX_IS_GOT); + } + trainBox = findWhere(trainInstance.trainBoxs, { roleId }) + if (!!trainBox) { + res.releaseCallback();//解锁 + return resResult(STATUS.GUILD_TRAIN_BOX_IS_GOT); + } + let good = getRandSingleEelm(trainInfo.heroRewards); + let goods = await addItems(roleId, roleName, sid, [good], ITEM_CHANGE_REASON.TRAIN_BOX_REWARD); + + let resGuildTrain = await GuildTrainModel.receiveBoxByIndex(code, roleId, trainId, hid, index, good); + let resUserGuild = await UserGuildModel.receiveTrainBoxRewards(roleId, hid, resGuildTrain.guildCode); + res.releaseCallback();//解锁 + + if (!resGuildTrain || !resUserGuild) { + return resResult(STATUS.GUILD_GET_TRAIN_BOX_FAIL); + } + let result: any = getGuildTrainRewards(resGuildTrain); + + result.goods = goods; + return resResult(STATUS.SUCCESS, result); + } + /** + * 领取练兵试炼等级奖励 + * @param msg + * @param session + */ + async getTrainLvUpRewards(msg: guildInter & { trainId: number }, session: BackendSession) { + let { trainId, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const serverId: number = parseInt(session.get('serverId')); + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); + if (!guildTrain || !guildTrain.isComplete) + return resResult(STATUS.GUILD_TRAIN_IS_NOT_COMPLETE); + let { jinjieReward, trainLv } = getArmyTrainJuDian(trainId); + if (!checkGuildTrainReward(userGuild.trainRewards, trainId)) + return resResult(STATUS.GUILD_TRAIN_QUALITY_REWARD_IS_GOT); + userGuild = await UserGuildModel.receiveTrainRewards(roleId, trainId); + if (!userGuild) { + return resResult(STATUS.INTERNAL_ERR); + } + let goods = await addItems(roleId, roleName, sid, jinjieReward, ITEM_CHANGE_REASON.TRAIN_LV_REWARD); + return resResult(STATUS.SUCCESS, { trainRewards: transTrainReward(userGuild.trainRewards, trainLv), goods }); + } + + //购买挑战次数 + async purchaseTrainCount(msg: guildInter & { count: number }, session: BackendSession) { + let { count, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + const sid: string = session.get('sid'); + let userGuild = await refreshTrain(myUserGuild, roleId, serverId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + if (userGuild.buyTrainCount >= ARMY.ARMY_TRAIN_BUYTIMES) + return resResult(STATUS.GUILD_BUY_TRAIN_COUNT_REACH_MAX); + let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: ARMY.ARMY_TRAIN_TIMESCOST }], ITEM_CHANGE_REASON.TRAIN_BATTLE_BUY_CNT); + if (!result) + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let { trainCount, buyTrainCount } = await UserGuildModel.addTrainCount(roleId, count); + return resResult(STATUS.SUCCESS, { trainCount, buyTrainCount }); + } + + // debug接口: 添加挑战次数 + async debugAddTrainCount(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + const roleId: string = session.get('roleId'); + await UserGuildModel.addTrainCount(roleId, 1); + return resResult(STATUS.SUCCESS); + } + + // debug接口: 重置试炼场 + async debugResetTrainInstance(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + const guildCode: string = session.get('guildCode'); + const serverId: number = session.get('serverId'); + await GuildModel.updateInfo(guildCode, { resetTrainTimeDaily: new Date(Date.now() - 86400000)}) + await resetTrain(guildCode, serverId); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/gvgBattleHandler.ts b/game-server/app/servers/guild/handler/gvgBattleHandler.ts index 1ec790b2a..ec3024dc0 100644 --- a/game-server/app/servers/guild/handler/gvgBattleHandler.ts +++ b/game-server/app/servers/guild/handler/gvgBattleHandler.ts @@ -1,958 +1,959 @@ -import { GVGRecModel, GVGRecType } from '../../../db/GVGRec'; -import { GVGAreaInMap, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, LeagueGood, MyTeamInfo, MyTeamSimpleInfo } from '../../../domain/gvgField/returnData'; -import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from '../../../db/GVGTeam'; -import { GVGUserDataModel } from '../../../db/GVGUserData'; -import { GVGCityModel, GVGCityType } from '../../../db/GVGCity'; -import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; -import { resResult, genCode, getRandSingleEelm } from "../../../pubUtils/util"; -import { GVGLeagueModel } from '../../../db/GVGLeague'; -import { getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService'; -import { redisAddBattleScore, battleEndSendMessage, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanksByCity, getBirthAreaOfCity, getGVGWarId, getOppHeroes, getTechKnifeHurt, getTechReviveMinus, initRobots, pushTeamMoveMessage, getAllGVGCitiesInfo, leaveCity, refreshTeams, checkEnterCityTime, generNewLineup, getBattleRank, checkSettleStatus, getSpineCnt, getPlayerRanksByCity, getPlayerSettleRanksByCity, checkGVGLineupWhenSave, sendWinStreakMessage, getNewLineup, sendAreaPointChange } from '../../../services/gvg/gvgBattleService'; -import { getGVGBattleData } from '../../../services/memoryCache/gvgBattleData'; -import { GVGBattleRecModel } from '../../../db/GVGBattleRec'; -import { getFightTimeByPeriod } from '../../../services/gvg/gvgFightService'; -import { gameData, getReviveGold } from '../../../pubUtils/data'; -import { getAllServerName } from '../../../services/redisService'; -import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; -import { SaveTeamParam, SaveTeamUpdateParam } from '../../../domain/gvgField/gvgDb'; -import { GVG_AREA_TYPE, GVG_ATTACK_TYPE, GVG_ITEM, GVG_PERIOD, GVG_POINT_TYPE, GVG_REC_TYPE, ITEM_CHANGE_REASON, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from '../../../consts'; -import { addRoleToAreaChannel, addRoleToAreaTeamChannel, addRoleToGVGCityChannel, leaveGVGAreaChannel, leaveGVGAreaTeamChannel, leaveGVGCityTeamChannel } from '../../../services/chatChannelService'; -import { nowSeconds } from '../../../pubUtils/timeUtil'; -import { GVGUserItemModel } from '../../../db/GVGUserItem'; -import { handleGVGCost } from '../../../services/gvg/gvgItemService'; -import { getGoldObject, handleCost } from '../../../services/role/rewardService'; -import { GVGCityAreaPointModel } from '../../../db/GVGCityAreaPoint'; -import { Rank } from '../../../services/rankService'; -import { LeagueRankInfo, RoleRankInfo } from '../../../domain/rank'; -import { addBattleEndRec } from '../../../services/gvg/gvgRecService'; -import { RoleModel } from '../../../db/Role'; -import { EXTERIOR, GVG } from '../../../pubUtils/dicParam'; -import { sendMessageToGuildWithSuc, sendMessageToGVGAreaByTeamWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; -import { checkLeagueAuth } from '../../../services/gvg/gvgTeamService'; -import { GVGLeaguePrepareModel } from '../../../db/GVGLeaguePrepare'; -import { gvgEndParamInter } from '../../../pubUtils/interface'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GVGBattleHandler(app); -} - -export class GVGBattleHandler { - channelService: ChannelService; - - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 获取我的编队信息 - async getTeams(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - let { configId } = getGVGConfig(); - const teams = await GVGTeamModel.findByRole(roleId, '-_id teamCode index head frame spine lineup combo confirmConfigId') - - return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team, configId)) }); - } - - // 保存队伍 - // index: 队伍索引位置 - // head: 头像 - // frame: 相框 - // spine: 形象 - // lineup: 阵容 - async saveTeam(msg: SaveTeamParam, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const { cityId, index, head, spine, frame, lineup, combo } = msg; - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let checkLineupResult = await checkGVGLineupWhenSave(roleId, index, lineup||[]); - if(checkLineupResult.code != 0) return resResult(checkLineupResult); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - let { leagueCode, name: leagueName } = myLeague; - let durability = gameData.gvgTeamDurability.get(index)||0; - - let groupKey = await getGroupKey(serverId); - let role = await RoleModel.findByRoleId(roleId, 'lv title'); - let updateParam: SaveTeamUpdateParam = { index, head, spine, frame, roleName, serverId, leagueCode, leagueName, lv: role.lv, title: role.title } - if(lineup) { - let hids: number[] = []; - for(let { actorId, subHid } of lineup) { - hids.push(actorId); - if(subHid) hids.push(subHid); - } - let { isOK, heroes } = await checkBattleHeroesByHid(roleId, hids); - if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - let { newLineup, newLineupCe } = await generNewLineup(roleId, heroes, lineup); - updateParam.lineup = newLineup; - updateParam.lineupCe = newLineupCe; - } - let originTeam = await GVGTeamModel.findByRoleAndIndex(roleId, index, 'cityId'); - if(!originTeam && cityId > 0) { - let city = await GVGCityModel.increaseTeam(configId, groupKey, cityId, roleId); - updateParam.cityId = cityId; - updateParam.areaId = getBirthAreaOfCity(city, leagueCode) - } - if(combo) updateParam.combo = combo; - const team = await GVGTeamModel.saveTeam(roleId, index, updateParam, { configId, groupKey, durability, maxDurability: durability }); - if (!team) { - return resResult(STATUS.GVG_SAVE_TEAM_FAILED); - } - - if(cityId > 0) { - let teamObj = getGVGBattleData(groupKey); - teamObj.enterCity(team); - } - return resResult(STATUS.SUCCESS, { curTeam: new MyTeamSimpleInfo(team, configId) }); - } - - // 确认我的编队信息 - async confirmTeam(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let groupKey = await getGroupKey(serverId); - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - let teams = await refreshTeams(configId, groupKey, roleId, myLeague, true); - - return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team, configId)) }); - } - - // 获取城池信息 - async getCity(msg: { cityId: number }, session: BackendSession) { - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const { cityId } = msg; - let { configId, period } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let groupKey = await getGroupKey(serverId); - let guardCity = await GVGCityModel.findByCityId(configId + 1, groupKey, cityId); - if(!guardCity) guardCity = await GVGCityModel.findByCityId(configId, groupKey, cityId); - const { guardLeague: leagueCode = '', guardLeagueName: name = '', guardLeagueIcon: icon = 0, players = [] } = guardCity||{}; - - let ourTeamCnt = 0, oppTeamCnt = 0; - for(let { leagueCode, teamCnt } of players) { - myLeague.leagueCode == leagueCode? (ourTeamCnt+= teamCnt): (oppTeamCnt += teamCnt); - } - - return resResult(STATUS.SUCCESS, { - cityId, - guardLeague: { leagueCode, name, icon }, - guardStartTime: startFightTime - GVG.GVG_GUARD_START_TIME, - startTime: startFightTime, - endTime: endFightTime, - ourTeamCnt, - oppTeamCnt, - }); - } - - // 进入城池之前的检查 - async checkMyTeam(msg: { cityId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { cityId } = msg; - let hasSettled = false, otherCityId = 0; - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let groupKey = await getGroupKey(serverId); - let teams = await refreshTeams(configId, groupKey, roleId, myLeague, false); - // 玩家队伍信息中城池id不一致,说明玩家已经进入了其他城池 - for(let { cityId: teamCityId } of teams) { - if(teamCityId > 0 && teamCityId != cityId) { - hasSettled = true; otherCityId = teamCityId; break; - } - } - return resResult(STATUS.SUCCESS, { hasSettled, cityId: otherCityId }); - } - - // 进入城池 - async enterCity(msg: { cityId: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { cityId } = msg; - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let groupKey = await getGroupKey(serverId); - let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - if(!checkEnterCityTime(city, myLeague.leagueCode)) return resResult(STATUS.GVG_NOT_ENTER_CITY_TIME); - - // 初始化本城池的守擂机器人 - await initRobots(configId, groupKey, city||{ cityId, guardLeague: '' }); - // 每赛季初自己的几支队伍恢复耐久、城市、顺便更新一下自己的玩家名、联军 - let teams = await refreshTeams(configId, groupKey, roleId, myLeague, true); - - if(await GVGTeamModel.checkLockTeam(roleId, cityId)) return resResult(STATUS.GVG_BATTLE_TEAM_LOCK_ENTERY_CITY); - let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - let originCityId = gvgUserData?.cityId||0; - // 检测是否已经在城池中,玩家不在这个城池中时进行处理 - if (originCityId != cityId) { - - if(gvgUserData?.cityId > 0) { // 如果leaveCity没有退出成功,玩家还遗留在上一座城中,做一下处理 - await leaveCity(true, roleId, serverId, guildCode, myLeague); - } - const roleTeamCnt = await GVGTeamModel.getTeamCntByRole(roleId); - city = await GVGCityModel.increasePlayer(configId, groupKey, cityId, roleId, myLeague.leagueCode, roleTeamCnt); - if(!city) return resResult(STATUS.GVG_BATTLE_CITY_FULL); - - gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, cityId); - } - let teamResult: MyTeamInfo[] = []; - for(let team of teams) { // 有可能多个编队有的在城池中(驻守),有点不在(新编) - let originCityId = team.cityId||0; - if(originCityId == cityId) { - teamResult.push(new MyTeamInfo(team)); - continue; - }; - let areaId = getBirthAreaOfCity(city, myLeague.leagueCode); - team = await GVGTeamModel.enterCity(team.teamCode, cityId, areaId, groupKey); - if(!team) continue; - // 更新内存队伍信息 - let teamObj = getGVGBattleData(groupKey); - teamObj.enterCity(team); - teamResult.push(new MyTeamInfo(team)) - } - - const { ranks, myRank } = await getBattleRanksByCity(configId, groupKey, cityId, myLeague); - const { ranks: memberRanks, myRank: myMemberRank } = await getPlayerRanksByCity(configId, groupKey, cityId, roleId); - const { ranks: memberSettleRanks, myRank: myMemberSettleRank } = await getPlayerSettleRanksByCity(configId, groupKey, cityId, roleId); - const recs = await GVGRecModel.findBattleRecByRole(configId, roleId, myLeague.leagueCode, 5); - await leaveGVGCityTeamChannel(roleId, sid); - await addRoleToGVGCityChannel(roleId, groupKey, cityId, sid); - - return resResult(STATUS.SUCCESS, { - cityId, - ranks, myRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank, - recs, - teams: teamResult, - }); - } - - // 离开城池 - async leaveCity(msg: { cityId: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { cityId } = msg; - let { configId, period } = getGVGPeriodData(); - - // 检测是否已经在城池中 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - if (!gvgUserData) { - return resResult(STATUS.GVG_USER_NOT_FOUND); - } - if (gvgUserData.cityId != cityId) { - return resResult(STATUS.GVG_USER_NOT_IN_CITY); - } - - // 更新玩家城池和队伍城池 - await leaveCity(false, roleId, serverId, guildCode, myLeague); - - await leaveGVGAreaChannel(roleId, sid); - await leaveGVGAreaTeamChannel(roleId, sid); - await leaveGVGCityTeamChannel(roleId, sid); - return resResult(STATUS.SUCCESS); - } - - // 获取区域上的队伍 - async getAreaTeams(msg: { cityId: number, areaIds: number[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { cityId, areaIds } = msg; - - if(!checkAreaIsInCity(cityId, areaIds)) return resResult(STATUS.GVG_AREA_NOT_IN_CITY); - - let groupKey = await getGroupKey(serverId); - let serverNames = await getAllServerName(); - - let teamObj = getGVGBattleData(groupKey); - let result: GVGTeamSpineInMap[] = []; - let spineCnt = await getSpineCnt(); - for(let areaId of areaIds) { - let teams = teamObj.findTeamsByArea(areaId, spineCnt); - for(let team of teams) { - result.push(new GVGTeamSpineInMap(team, serverNames)) - } - } - - return resResult(STATUS.SUCCESS, { cityId, spines: result }); - } - - // 加入频道 - async addAreaChannel(msg: { cityId: number, areaIds: number[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { areaIds } = msg; - let groupKey = await getGroupKey(serverId); - - await leaveGVGAreaChannel(roleId, sid); - await addRoleToAreaChannel(roleId, groupKey, areaIds, sid); - - return resResult(STATUS.SUCCESS); - } - - // 点击自己的编队获取区域列表 - async getAreaOfMyTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { cityId, teamCode } = msg; - - let groupKey = await getGroupKey(serverId); - let { configId } = getGVGPeriodData(); - - let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); - if(myTeam.cityId != cityId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); - - let teams = await GVGTeamModel.findByAreaId(configId, groupKey, cityId, myTeam.areaId); - let points: GVGTeamInListOnPoint[] = [], players: GVGTeamInList[] = []; - let pointIds = gameData.gvgPointByAreaId.get(myTeam.areaId)||[]; - for(let pointId of pointIds) { - let dicPoint = gameData.gvgAreaPoint.get(pointId); - let team = teams.find(cur => cur.pointId == pointId); - if(!team && dicPoint.type != GVG_POINT_TYPE.ROBOT) continue; - - let obj = new GVGTeamInListOnPoint(pointId, !!team, team); - points.push(obj); - } - for(let team of teams) { - if(team.pointId == 0) { - let obj = new GVGTeamInList(team); - players.push(obj); - } - } - - await leaveGVGAreaTeamChannel(roleId, sid); - await addRoleToAreaTeamChannel(roleId, groupKey, myTeam.areaId, sid); - - return resResult(STATUS.SUCCESS, { - cityId, areaId: myTeam.areaId, points, players - }); - } - - // 开始移动 - // areaId: 要移动的目标据点 id - async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { areaId, cityId, teamCode } = msg; - - let groupKey = await getGroupKey(serverId); - - let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - let checkResult = checkMoveStatus(team, cityId, areaId); - if(checkResult.code != 0) return resResult(checkResult); - - team = await GVGTeamModel.startMove(teamCode, areaId, team.areaId); - - // 更新内存数据 - let teamObj = getGVGBattleData(groupKey); - teamObj.move(teamCode, areaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime); - - await leaveGVGAreaTeamChannel(roleId, sid); - await addRoleToAreaTeamChannel(roleId, groupKey, areaId, sid); - await pushTeamMoveMessage(team); - return resResult(STATUS.SUCCESS, { areaId, cityId, stopMoveTime: team.stopMoveTime, moveCdTime: team.moveCdTime }); - } - - // 停止移动 - // areaId: 移动到的目标据点 id - async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const { areaId, cityId, teamCode } = msg; - - let groupKey = await getGroupKey(serverId); - - let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - if(!team) return resResult(STATUS.GVG_BATTLE_TEAM_NOT_FOUND); - if(team.cityId != cityId && team.areaId != areaId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); - - team = await GVGTeamModel.stopMove(teamCode, areaId); - // 更新内存数据 - let teamObj = getGVGBattleData(groupKey); - teamObj.move(teamCode, areaId, 0, team.startMoveTime, team.stopMoveTime); - - return resResult(STATUS.SUCCESS, { areaId, cityId, curTeam: new MyTeamInfo(team) }); - } - - // 队伍入驻积分点 - async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { cityId, areaId, pointId, teamCode } = msg; - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let groupKey = await getGroupKey(serverId); - - let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); - - let checkResult = checkSettleStatus(myTeam); - if(checkResult.code != 0) return resResult(checkResult); - - let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); - if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); - if(dicAreaPoint.type != GVG_POINT_TYPE.ROBOT) return resResult(STATUS.GVG_POINT_TYPE_ERR); - - let point = await GVGCityAreaPointModel.settlePoint(cityId, areaId, pointId, myTeam); - if(!point) return resResult(STATUS.GVG_POINT_HAS_SETTLED); - const curTeam = await GVGTeamModel.settlePoint(teamCode, pointId); - - let teamObj = getGVGBattleData(groupKey); - teamObj.teamSettle(roleId, teamCode, pointId); - - // addTeamSettleRec(curTeam); - await sendAreaPointChange(groupKey, curTeam.areaId, curTeam.cityId, pointId, myTeam.pointId, curTeam); - return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) }); - } - - // 队伍离开积分点 - async teamLeave(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { pointId, teamCode } = msg; - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let groupKey = await getGroupKey(serverId); - - let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); - - let checkResult = checkSettleStatus(myTeam); - if(checkResult.code != 0) return resResult(checkResult); - - let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); - if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); - - const curTeam = await GVGTeamModel.settlePoint(teamCode, 0); - await GVGCityAreaPointModel.leavePoint(configId, groupKey, teamCode); - let teamObj = getGVGBattleData(groupKey); - teamObj.teamSettle(roleId, teamCode, 0); - - await sendAreaPointChange(groupKey, curTeam.areaId, curTeam.cityId, pointId, myTeam.pointId, curTeam); - return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) }); - } - - // 队伍开始攻击 - // teamCode: 攻击方队伍 - // oppoTeamCode: 防守方队伍 - async battleStart(msg: { cityId: number, teamCode: string, oppoTeamCode: string, pointId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { teamCode, oppoTeamCode } = msg; - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - if(startFightTime > nowSeconds()) return resResult(STATUS.GVG_NOT_BATTLE_TIME); - if(endFightTime < nowSeconds()) return resResult(STATUS.GVG_BATTLE_IS_END); - - let groupKey = await getGroupKey(serverId); - - let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode); - let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam); - if(checkStatus.code != 0) return resResult(checkStatus); - - const warId = getGVGWarId(defenseTeam); - const battleRecord = await GVGBattleRecModel.createRec(configId, groupKey, warId, attackTeam, defenseTeam); - - attackTeam = await GVGTeamModel.battleStartLockAttack(teamCode); - defenseTeam = await GVGTeamModel.battleStartLockDefense(oppoTeamCode, teamCode); - // 内存处理 - let teamObj = getGVGBattleData(groupKey); - teamObj.setTime(attackTeam.teamCode, attackTeam); - teamObj.setTime(defenseTeam.teamCode, defenseTeam); - let heroes = getOppHeroes(warId, defenseTeam.isRobot, defenseTeam.lineup) - - return resResult(STATUS.SUCCESS, { battleCode: battleRecord.battleCode, warId, isRobot: defenseTeam.isRobot, heroes, combo: defenseTeam.combo, curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); - } - - // 队伍停止攻击 - async battleEnd(msg: { cityId: number, battleCode: string, isSuccess: boolean, myHeroes: gvgEndParamInter[], oppHeroes: gvgEndParamInter[] }, session: BackendSession) { - const serverId = session.get('serverId'); - const { cityId, battleCode, isSuccess, myHeroes = [], oppHeroes = [] } = msg; - - let { configId, period } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - if(startFightTime > nowSeconds()) return resResult(STATUS.GVG_NOT_BATTLE_TIME); - if(endFightTime < nowSeconds()) return resResult(STATUS.GVG_BATTLE_IS_END); - - const record = await GVGBattleRecModel.findByBattleCode(battleCode); - if(!record) return resResult(STATUS.GVG_BATTLEREC_NOT_FOUND); - if(record.battleEndTime > 0) return resResult(STATUS.GVG_BATTLEREC_HAS_SUMMIT); - let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(record.attackTeam.teamCode, record.defenseTeam.teamCode); - let attackOriginId = attackTeam.pointId; - if(defenseTeam.lockTeamCode != attackTeam.teamCode) return resResult(STATUS.GVG_LOCK_TIME_OUT) - - let groupKey = await getGroupKey(serverId); - let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); - if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); - - // 计算并更新两支队伍耐久 - let { win, fail } = gameData.gvgBattleDurabilityMinus; - attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(groupKey, configId, attackTeam.leagueCode), getNewLineup(attackTeam, myHeroes)); - defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, getBirthAreaOfCity(city, defenseTeam.leagueCode), GVG.GVG_DEFAULT_DEFENSE_CD, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode), getNewLineup(defenseTeam, oppHeroes)); - if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 - if(!attackTeam.curTeamBreak) { - let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode); - if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); - } else { - await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode); - } - } - if(attackTeam.curTeamBreak && attackTeam.originPointId) { - await GVGCityAreaPointModel.leavePoint(configId, groupKey, attackTeam.teamCode); - } - if(defenseTeam.curTeamBreak) { - let attackScore = calBattleScoreByCe(isSuccess, defenseTeam.lineupCe); - let attackCurTeamBreak = attackTeam.curTeamBreak; - attackTeam = await GVGTeamModel.addScore(attackTeam.teamCode, attackScore, 0); - attackTeam.curTeamBreak = attackCurTeamBreak; - await redisAddBattleScore(attackTeam, attackScore); - } - - // 更新内存 - let teamObj = getGVGBattleData(groupKey); - teamObj.battleEnd([attackTeam, defenseTeam]); - // 更新rec - let rec = await GVGBattleRecModel.battleEnd(battleCode, isSuccess, attackTeam, defenseTeam); - await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.PLAYER); - addBattleEndRec(rec); - // 连胜邮件 - sendWinStreakMessage(groupKey, cityId, attackTeam, defenseTeam, isSuccess); - - return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); - } - - // 使用道具 - // teamCode: 要使用道具的队伍 - async useItem(msg: { cityId: number, itemId: number, teamCode: string, oppoTeamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { cityId, itemId, teamCode, oppoTeamCode } = msg; - - if(itemId != GVG_ITEM.KNIFE) return resResult(STATUS.GVG_ITEM_CANNOT_USE); - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let groupKey = await getGroupKey(serverId); - - let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode); - let attackOriginId = attackTeam.pointId; - let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam); - if(checkStatus.code != 0) return resResult(checkStatus); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.KNIFE, count: 1 }], [], ITEM_CHANGE_REASON.GVG_USE_ITEM); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); - if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); - - let hurt = await getTechKnifeHurt(configId, attackTeam.leagueCode); - defenseTeam = await GVGTeamModel.battleEndDefense(oppoTeamCode, -hurt, getBirthAreaOfCity(city, defenseTeam.leagueCode), 0, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode)); - if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 - if(!attackTeam.curTeamBreak) { - let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode); - if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); - } else { - await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode); - } - - } - if(defenseTeam.curTeamBreak) { - let attackScore = calBattleScoreByCe(true, defenseTeam.lineupCe); - await redisAddBattleScore(attackTeam, attackScore); - } - - // 更新内存 - let teamObj = getGVGBattleData(groupKey); - teamObj.battleEnd([attackTeam, defenseTeam]); - - await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.KNIFE); - return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); - } - - // 复活队伍 - async reviveTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { teamCode } = msg; - let { configId, period } = getGVGPeriodData(); - let groupKey = await getGroupKey(serverId); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); - if(!team) return resResult(STATUS.GVG_TEAM_NOT_FOUND); - if(team.restartTime < nowSeconds()) return resResult(STATUS.GVG_TEAM_NOT_NEED_REVIVE); - - let userData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - let reviveCnt = userData?.reviveCnt||0; - - const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.REVIVE_COIN, 1); - if(hasItem) { - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.REVIVE_COIN, count: 1 }], [], ITEM_CHANGE_REASON.GVG_REVIVE); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - } else { - let gold = getReviveGold(reviveCnt + 1); - const costResult = await handleCost(roleId, sid, [getGoldObject(gold)], ITEM_CHANGE_REASON.GVG_REVIVE); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - userData = await GVGUserDataModel.addReviveCnt(configId, myLeague.leagueCode, roleId, 1); - reviveCnt = userData?.reviveCnt||0; - } - team = await GVGTeamModel.reviveTeam(teamCode); - - // 更新内存 - let teamObj = getGVGBattleData(groupKey); - teamObj.battleEnd([team]); - - // 更新成功返回队伍信息 - return resResult(STATUS.SUCCESS, { reviveCnt, curTeam: new MyTeamInfo(team) }); - } - - // 获取战报 - // type: 战报类型 - async getRecs(msg: { type: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const { type } = msg; - // 根据 type 获取战报 - let { configId, period } = getGVGPeriodData(); - let groupKey = await getGroupKey(serverId); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let recs: GVGRecType[] = []; - if(type == GVG_REC_TYPE.BATTLE_BY_CITY) { - recs = await GVGRecModel.findBattleRecByGroup(configId, groupKey); - } else if (type == GVG_REC_TYPE.BATTLE_BY_LEAGUE) { - recs = await GVGRecModel.findBattleRecByLeague(configId, myLeague.leagueCode); - } else if (type == GVG_REC_TYPE.BATTLE_BY_ROLE) { - recs = await GVGRecModel.findBattleRecByRole(configId, roleId, myLeague.leagueCode); - } - return resResult(STATUS.SUCCESS, { recs }); - } - - // 获取概况 - async getOverview(msg: {}, session: BackendSession) { - const serverId = session.get('serverId'); - - let { configId } = getGVGPeriodData(); - let groupKey = await getGroupKey(serverId); - let serverType = await getGVGServerType(serverId); - - const cities = await GVGCityModel.findByConfigAndGroup(configId, groupKey); - const points = await GVGCityAreaPointModel.findByConfig(configId, groupKey); - - let result: { cityId: number, guardLeagueName: string, areas: { areaId: number, points: { pointId: number, guardLeagueName: string }[] }[] }[] = []; - for(let [ cityId, { mapType, battleAreaIds }] of gameData.gvgCity) { - if(mapType != serverType) continue; - let city = cities.find(cur => cur.cityId == cityId); - let areas: { areaId: number, points: {pointId: number, guardLeagueName: string }[]}[] = []; - for(let areaId of battleAreaIds) { - let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; - let pointArrs: { pointId: number, guardLeagueName: string }[] = []; - for(let pointId of pointIds) { - let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); - if(!dicAreaPoint) continue; - let playerPoint = points.find(cur => cur.pointId == pointId); - pointArrs.push({ pointId, guardLeagueName: playerPoint? (playerPoint.leagueName||"无"): dicAreaPoint.name }); - } - if(pointArrs.length > 0) areas.push({ areaId, points: pointArrs }); - } - result.push({ cityId, guardLeagueName: city?.guardLeagueName||'', areas }); - } - - return resResult(STATUS.SUCCESS, { cities: result }); - } - - // 排行榜 - async getRanks(msg: {}, session: BackendSession) { - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const roleId = session.get('roleId'); - - let { configId } = getGVGPeriodData(); - let groupKey = await getGroupKey(serverId); - let serverType = await getGVGServerType(serverId); - let cities = await getAllGVGCitiesInfo(configId, groupKey, serverType); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { myRank: myLeagueRank, ranks: leagueRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }, { leagueCode: myLeague.leagueCode }); - let { myRank: myMemberRank, ranks: memberRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }, { roleId }); - let { myRank: myMemberSettleRank, ranks: memberSettleRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }, { roleId }); - - return resResult(STATUS.SUCCESS, { - cities, leagueRanks, myLeagueRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank - }) - } - - // 设置目标城池 - async setTargetCity(msg: { cityId: number, isTarget: boolean }, session: BackendSession) { - - const guildCode = session.get('guildCode'); - const roleId = session.get('roleId'); - const { cityId, isTarget } = msg; - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let dicCity = gameData.gvgCity.get(cityId); - if(!dicCity) return resResult(STATUS.GVG_CITY_NOT_FOUND); - - let targetCities: number[] = []; - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_TARGET_CITY); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - if(isTarget) { - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - targetCities = leaguePrepare?.targetCities||[]; - if(targetCities.indexOf(cityId) != -1) return resResult(STATUS.GVG_TARGET_CITY_HAS_SET); - if(targetCities.length >= 2) return resResult(STATUS.GVG_TARGET_CITY_CNT_MAX); - leaguePrepare = await GVGLeaguePrepareModel.setTargetCity(configId, myLeague.leagueCode, cityId); - targetCities = leaguePrepare?.targetCities||[]; - } else { - let leaguePrepare = await GVGLeaguePrepareModel.cancelTargetCity(configId, myLeague.leagueCode, cityId); - targetCities = leaguePrepare?.targetCities||[]; - } - // 发送消息 - for(let guildCode of myLeague.guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GVG_TARGET_CITY_UPDATE, { targetCities }); - } - - return resResult(STATUS.SUCCESS, { - configId, targetCities - }); - } - - // 设置管理信息 - async setNotice(msg: { notice: string }, session: BackendSession) { - - const guildCode = session.get('guildCode'); - const roleId = session.get('roleId'); - const { notice = '' } = msg; - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId, period } = getGVGPeriodData(); - if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_NOTICE); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - let leaguePrepare = await GVGLeaguePrepareModel.setNotice(configId, myLeague.leagueCode, notice); - if(!leaguePrepare) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - for(let guildCode of myLeague.guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GVG_NOTICE_UPDATE, { notice: leaguePrepare.notice }); - } - return resResult(STATUS.SUCCESS, { - configId, notice: leaguePrepare.notice - }); - } - - // enterCity里返回的那个ranks - async getRankByCity(msg: { cityId: number }, session: BackendSession) { - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const roleId = session.get('roleId'); - const { cityId } = msg; - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId } = getGVGPeriodData(); - const groupKey = await getGroupKey(serverId); - - const { ranks, myRank } = await getBattleRanksByCity(configId, groupKey, cityId, myLeague); - const { ranks: memberRanks, myRank: myMemberRank } = await getPlayerRanksByCity(configId, groupKey, cityId, roleId); - const { ranks: memberSettleRanks, myRank: myMemberSettleRank } = await getPlayerSettleRanksByCity(configId, groupKey, cityId, roleId); - return resResult(STATUS.SUCCESS, { - cityId, ranks, myRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank - }) - } - - // 获取我的编队信息 - async getOppTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { - let { teamCode } = msg; - const team = await GVGTeamModel.findByCode(teamCode) - if (!team) return resResult(STATUS.GVG_TEAM_NOT_FOUND); - const warId = getGVGWarId(team); - - return resResult(STATUS.SUCCESS, { warId, oppTeam: new MyTeamInfo(team) }); - } - - async debugStartSchedule() { - let { countdownTime } = getGVGPeriodData(); - pinus.app.rpc.guild.guildRemote.setPeriodTime.broadcast(nowSeconds(), countdownTime); - await pinus.app.rpc.systimer.systimerRemote.gvgBattleStartSchedule.broadcast(); - return resResult(STATUS.SUCCESS); - } - - async debugEndSchedule() { - pinus.app.rpc.guild.guildRemote.resetPeriodTime.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.gvgBattleEndSchedule.broadcast(); - return resResult(STATUS.SUCCESS); - } - - async debugAddRobots(msg: { cityId: number, teamCnt: number }, session: BackendSession) { - const serverId = session.get('serverId'); - const { cityId, teamCnt } = msg; - - const { configId } = getGVGConfig(); - const groupKey = await getGroupKey(serverId); - const teamObj = getGVGBattleData(groupKey); - const teams: any[] = []; - const areaIds = gameData.gvgCity.get(cityId)?.areaIds||[]; - for(let i = 0; i < teamCnt; i++) { - let areaId = getRandSingleEelm(areaIds); - teams.push({ configId, confirmConfigId: configId, title: 1, groupKey, roleId: 'test', roleName: 'test' + i, serverId, lv: 100, teamCode: genCode(8), index: 3, leagueCode: 'test', leagueName: 'test' + i, guildCode: 'test', areaId, cityId, pointId: 0, head: EXTERIOR.EXTERIOR_FACE, frame: EXTERIOR.EXTERIOR_FACECASE, spine: EXTERIOR.EXTERIOR_APPEARANCE, durability: 100, maxDurability: 100, restartTime: nowSeconds(), attackTime: nowSeconds(), lockTime: nowSeconds(), startMoveTime: nowSeconds(), stopMoveTime: nowSeconds(), moveCdTime: nowSeconds(), defenseTime: nowSeconds(), lineupCe: 100000 }) - } - await GVGTeamModel.insertMany(teams); - teamObj.enterCity(...teams); - - return resResult(STATUS.SUCCESS); - } - - private moveInterval: NodeJS.Timer; - private attackInterval: NodeJS.Timer; - async debugMoveRobots(msg: { cityId: number, frequency: number }, session: BackendSession) { - const serverId = session.get('serverId'); - const { cityId, frequency } = msg; - - const { configId } = getGVGConfig(); - const groupKey = await getGroupKey(serverId); - const teamObj = getGVGBattleData(groupKey); - const serverNames = await getAllServerName(); - - if(this.moveInterval) { - clearInterval(this.moveInterval); - } - - let fun = async () => { - let teams = teamObj.findTeamsByRole('test'); - for(let i = 0; i < teams.length; i++) { - let teamMem = teams[i]; - setTimeout(async () => { - let fromAreaId = teamMem.areaId; - let dicArea = gameData.gvgArea.get(fromAreaId); - // 更新内存数据 - let toAreaId = getRandSingleEelm(dicArea.relateArea); - let team = await GVGTeamModel.startMove(teamMem.teamCode, toAreaId, fromAreaId); - - // 更新内存数据 - let teamObj = getGVGBattleData(groupKey); - teamObj.move(teamMem.teamCode, toAreaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime); - await pushTeamMoveMessage(team); - }, i * 100); - } - - }; - await fun(); - this.moveInterval = setInterval(fun, frequency) - return resResult(STATUS.SUCCESS) - } - - async debugAttacks(msg: { cityId: number, frequency: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const { cityId, frequency } = msg; - - const { configId } = getGVGConfig(); - const groupKey = await getGroupKey(serverId); - const teamObj = getGVGBattleData(groupKey); - const serverNames = await getAllServerName(); - - if(this.attackInterval) { - clearInterval(this.attackInterval); - } - let spineCnt = await getSpineCnt(); - let fun = async () => { - for(let areaId of teamObj.findAreas()) { - let teams = teamObj.findTeamsByArea(areaId, spineCnt); - let areaTeams = teams.map(team => new GVGTeamInList(team as any)); - await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { - cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: areaTeams - }); - let myTeams = teams.filter(team => team.roleId == roleId).map(team => new GVGTeamInList(team as any)); - if(myTeams.length > 0) await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { - cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: myTeams - }, sid); - } - - }; - await fun(); - this.attackInterval = setInterval(fun, frequency) - return resResult(STATUS.SUCCESS) - } - - async debugStopMoveRobot(msg: { cityId: number }, session: BackendSession) { - if(this.moveInterval) { - clearInterval(this.moveInterval); - } - if(this.attackInterval) { - clearInterval(this.attackInterval); - } - - return resResult(STATUS.SUCCESS); - } -} +import { GVGRecModel, GVGRecType } from '@db/GVGRec'; +import { GVGAreaInMap, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, LeagueGood, MyTeamInfo, MyTeamSimpleInfo } from '@domain/gvgField/returnData'; +import { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from '@db/GVGTeam'; +import { GVGUserDataModel } from '@db/GVGUserData'; +import { GVGCityModel, GVGCityType } from '@db/GVGCity'; +import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; +import { resResult, genCode, getRandSingleEelm } from "@pubUtils/util"; +import { GVGLeagueModel } from '@db/GVGLeague'; +import { getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from '../../../services/gvg/gvgService'; +import { redisAddBattleScore, battleEndSendMessage, calBattleScoreByCe, checkAreaIsInCity, checkGVGBattleStart, checkMoveStatus, getBattleRanksByCity, getBirthAreaOfCity, getGVGWarId, getOppHeroes, getTechKnifeHurt, getTechReviveMinus, initRobots, pushTeamMoveMessage, getAllGVGCitiesInfo, leaveCity, refreshTeams, checkEnterCityTime, generNewLineup, getBattleRank, checkSettleStatus, getSpineCnt, getPlayerRanksByCity, getPlayerSettleRanksByCity, checkGVGLineupWhenSave, sendWinStreakMessage, getNewLineup, sendAreaPointChange } from '../../../services/gvg/gvgBattleService'; +import { getGVGBattleData } from '../../../services/memoryCache/gvgBattleData'; +import { GVGBattleRecModel } from '@db/GVGBattleRec'; +import { getFightTimeByPeriod } from '../../../services/gvg/gvgFightService'; +import { gameData, getReviveGold } from '@pubUtils/data'; +import { getAllServerName } from '../../../services/redisService'; +import { checkBattleHeroesByHid } from '../../../services/normalBattleService'; +import { SaveTeamParam, SaveTeamUpdateParam } from '@domain/gvgField/gvgDb'; +import { GVG_AREA_TYPE, GVG_ATTACK_TYPE, GVG_ITEM, GVG_PERIOD, GVG_POINT_TYPE, GVG_REC_TYPE, ITEM_CHANGE_REASON, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from '../../../consts'; +import { addRoleToAreaChannel, addRoleToAreaTeamChannel, addRoleToGVGCityChannel, leaveGVGAreaChannel, leaveGVGAreaTeamChannel, leaveGVGCityTeamChannel } from '../../../services/chatChannelService'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { GVGUserItemModel } from '@db/GVGUserItem'; +import { handleGVGCost } from '../../../services/gvg/gvgItemService'; +import { getGoldObject, handleCost } from '../../../services/role/rewardService'; +import { GVGCityAreaPointModel } from '@db/GVGCityAreaPoint'; +import { Rank } from '../../../services/rankService'; +import { LeagueRankInfo, RoleRankInfo } from '@domain/rank'; +import { addBattleEndRec } from '../../../services/gvg/gvgRecService'; +import { RoleModel } from '@db/Role'; +import { EXTERIOR, GVG } from '@pubUtils/dicParam'; +import { sendMessageToGuildWithSuc, sendMessageToGVGAreaByTeamWithSuc, sendMessageToUserWithSuc } from '../../../services/pushService'; +import { checkLeagueAuth } from '../../../services/gvg/gvgTeamService'; +import { GVGLeaguePrepareModel } from '@db/GVGLeaguePrepare'; +import { gvgEndParamInter } from '@pubUtils/interface'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGBattleHandler(app); +} + +export class GVGBattleHandler { + channelService: ChannelService; + + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 获取我的编队信息 + async getTeams(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + let { configId } = getGVGConfig(); + const teams = await GVGTeamModel.findByRole(roleId, '-_id teamCode index head frame spine lineup combo confirmConfigId') + + return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team, configId)) }); + } + + // 保存队伍 + // index: 队伍索引位置 + // head: 头像 + // frame: 相框 + // spine: 形象 + // lineup: 阵容 + async saveTeam(msg: SaveTeamParam, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const { cityId, index, head, spine, frame, lineup, combo } = msg; + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let checkLineupResult = await checkGVGLineupWhenSave(roleId, index, lineup||[]); + if(checkLineupResult.code != 0) return resResult(checkLineupResult); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + let { leagueCode, name: leagueName } = myLeague; + let durability = gameData.gvgTeamDurability.get(index)||0; + + let groupKey = await getGroupKey(serverId); + let role = await RoleModel.findByRoleId(roleId, 'lv title'); + let updateParam: SaveTeamUpdateParam = { index, head, spine, frame, roleName, serverId, leagueCode, leagueName, lv: role.lv, title: role.title } + if(lineup) { + let hids: number[] = []; + for(let { actorId, subHid } of lineup) { + hids.push(actorId); + if(subHid) hids.push(subHid); + } + let { isOK, heroes } = await checkBattleHeroesByHid(roleId, hids); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + let { newLineup, newLineupCe } = await generNewLineup(roleId, heroes, lineup); + updateParam.lineup = newLineup; + updateParam.lineupCe = newLineupCe; + } + let originTeam = await GVGTeamModel.findByRoleAndIndex(roleId, index, 'cityId'); + if(!originTeam && cityId > 0) { + let city = await GVGCityModel.increaseTeam(configId, groupKey, cityId, roleId); + updateParam.cityId = cityId; + updateParam.areaId = getBirthAreaOfCity(city, leagueCode) + } + if(combo) updateParam.combo = combo; + const team = await GVGTeamModel.saveTeam(roleId, index, updateParam, { configId, groupKey, durability, maxDurability: durability }); + if (!team) { + return resResult(STATUS.GVG_SAVE_TEAM_FAILED); + } + + if(cityId > 0) { + let teamObj = getGVGBattleData(groupKey); + teamObj.enterCity(team); + } + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamSimpleInfo(team, configId) }); + } + + // 确认我的编队信息 + async confirmTeam(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let groupKey = await getGroupKey(serverId); + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + let teams = await refreshTeams(configId, groupKey, roleId, myLeague, true); + + return resResult(STATUS.SUCCESS, { teams: teams.map(team => new MyTeamSimpleInfo(team, configId)) }); + } + + // 获取城池信息 + async getCity(msg: { cityId: number }, session: BackendSession) { + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const { cityId } = msg; + let { configId, period } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let groupKey = await getGroupKey(serverId); + let guardCity = await GVGCityModel.findByCityId(configId + 1, groupKey, cityId); + if(!guardCity) guardCity = await GVGCityModel.findByCityId(configId, groupKey, cityId); + const { guardLeague: leagueCode = '', guardLeagueName: name = '', guardLeagueIcon: icon = 0, players = [] } = guardCity||{}; + + let ourTeamCnt = 0, oppTeamCnt = 0; + for(let { leagueCode, teamCnt } of players) { + myLeague.leagueCode == leagueCode? (ourTeamCnt+= teamCnt): (oppTeamCnt += teamCnt); + } + + return resResult(STATUS.SUCCESS, { + cityId, + guardLeague: { leagueCode, name, icon }, + guardStartTime: startFightTime - GVG.GVG_GUARD_START_TIME, + startTime: startFightTime, + endTime: endFightTime, + ourTeamCnt, + oppTeamCnt, + }); + } + + // 进入城池之前的检查 + async checkMyTeam(msg: { cityId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { cityId } = msg; + let hasSettled = false, otherCityId = 0; + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let groupKey = await getGroupKey(serverId); + let teams = await refreshTeams(configId, groupKey, roleId, myLeague, false); + // 玩家队伍信息中城池id不一致,说明玩家已经进入了其他城池 + for(let { cityId: teamCityId } of teams) { + if(teamCityId > 0 && teamCityId != cityId) { + hasSettled = true; otherCityId = teamCityId; break; + } + } + return resResult(STATUS.SUCCESS, { hasSettled, cityId: otherCityId }); + } + + // 进入城池 + async enterCity(msg: { cityId: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { cityId } = msg; + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let groupKey = await getGroupKey(serverId); + let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + if(!checkEnterCityTime(city, myLeague.leagueCode)) return resResult(STATUS.GVG_NOT_ENTER_CITY_TIME); + + // 初始化本城池的守擂机器人 + await initRobots(configId, groupKey, city||{ cityId, guardLeague: '' }); + // 每赛季初自己的几支队伍恢复耐久、城市、顺便更新一下自己的玩家名、联军 + let teams = await refreshTeams(configId, groupKey, roleId, myLeague, true); + + if(await GVGTeamModel.checkLockTeam(roleId, cityId)) return resResult(STATUS.GVG_BATTLE_TEAM_LOCK_ENTERY_CITY); + let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + let originCityId = gvgUserData?.cityId||0; + // 检测是否已经在城池中,玩家不在这个城池中时进行处理 + if (originCityId != cityId) { + + if(gvgUserData?.cityId > 0) { // 如果leaveCity没有退出成功,玩家还遗留在上一座城中,做一下处理 + await leaveCity(true, roleId, serverId, guildCode, myLeague); + } + const roleTeamCnt = await GVGTeamModel.getTeamCntByRole(roleId); + city = await GVGCityModel.increasePlayer(configId, groupKey, cityId, roleId, myLeague.leagueCode, roleTeamCnt); + if(!city) return resResult(STATUS.GVG_BATTLE_CITY_FULL); + + gvgUserData = await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, cityId); + } + let teamResult: MyTeamInfo[] = []; + for(let team of teams) { // 有可能多个编队有的在城池中(驻守),有点不在(新编) + let originCityId = team.cityId||0; + if(originCityId == cityId) { + teamResult.push(new MyTeamInfo(team)); + continue; + }; + let areaId = getBirthAreaOfCity(city, myLeague.leagueCode); + team = await GVGTeamModel.enterCity(team.teamCode, cityId, areaId, groupKey); + if(!team) continue; + // 更新内存队伍信息 + let teamObj = getGVGBattleData(groupKey); + teamObj.enterCity(team); + teamResult.push(new MyTeamInfo(team)) + } + + const { ranks, myRank } = await getBattleRanksByCity(configId, groupKey, cityId, myLeague); + const { ranks: memberRanks, myRank: myMemberRank } = await getPlayerRanksByCity(configId, groupKey, cityId, roleId); + const { ranks: memberSettleRanks, myRank: myMemberSettleRank } = await getPlayerSettleRanksByCity(configId, groupKey, cityId, roleId); + const recs = await GVGRecModel.findBattleRecByRole(configId, roleId, myLeague.leagueCode, 5); + await leaveGVGCityTeamChannel(roleId, sid); + await addRoleToGVGCityChannel(roleId, groupKey, cityId, sid); + + return resResult(STATUS.SUCCESS, { + cityId, + ranks, myRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank, + recs, + teams: teamResult, + }); + } + + // 离开城池 + async leaveCity(msg: { cityId: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { cityId } = msg; + let { configId, period } = getGVGPeriodData(); + + // 检测是否已经在城池中 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + let gvgUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + if (!gvgUserData) { + return resResult(STATUS.GVG_USER_NOT_FOUND); + } + if (gvgUserData.cityId != cityId) { + return resResult(STATUS.GVG_USER_NOT_IN_CITY); + } + + // 更新玩家城池和队伍城池 + await leaveCity(false, roleId, serverId, guildCode, myLeague); + + await leaveGVGAreaChannel(roleId, sid); + await leaveGVGAreaTeamChannel(roleId, sid); + await leaveGVGCityTeamChannel(roleId, sid); + return resResult(STATUS.SUCCESS); + } + + // 获取区域上的队伍 + async getAreaTeams(msg: { cityId: number, areaIds: number[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { cityId, areaIds } = msg; + + if(!checkAreaIsInCity(cityId, areaIds)) return resResult(STATUS.GVG_AREA_NOT_IN_CITY); + + let groupKey = await getGroupKey(serverId); + let serverNames = await getAllServerName(); + + let teamObj = getGVGBattleData(groupKey); + let result: GVGTeamSpineInMap[] = []; + let spineCnt = await getSpineCnt(); + for(let areaId of areaIds) { + let teams = teamObj.findTeamsByArea(areaId, spineCnt); + for(let team of teams) { + result.push(new GVGTeamSpineInMap(team, serverNames)) + } + } + + return resResult(STATUS.SUCCESS, { cityId, spines: result }); + } + + // 加入频道 + async addAreaChannel(msg: { cityId: number, areaIds: number[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { areaIds } = msg; + let groupKey = await getGroupKey(serverId); + + await leaveGVGAreaChannel(roleId, sid); + await addRoleToAreaChannel(roleId, groupKey, areaIds, sid); + + return resResult(STATUS.SUCCESS); + } + + // 点击自己的编队获取区域列表 + async getAreaOfMyTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { cityId, teamCode } = msg; + + let groupKey = await getGroupKey(serverId); + let { configId } = getGVGPeriodData(); + + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + if(myTeam.cityId != cityId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); + + let teams = await GVGTeamModel.findByAreaId(configId, groupKey, cityId, myTeam.areaId); + let points: GVGTeamInListOnPoint[] = [], players: GVGTeamInList[] = []; + let pointIds = gameData.gvgPointByAreaId.get(myTeam.areaId)||[]; + for(let pointId of pointIds) { + let dicPoint = gameData.gvgAreaPoint.get(pointId); + let team = teams.find(cur => cur.pointId == pointId); + if(!team && dicPoint.type != GVG_POINT_TYPE.ROBOT) continue; + + let obj = new GVGTeamInListOnPoint(pointId, !!team, team); + points.push(obj); + } + for(let team of teams) { + if(team.pointId == 0) { + let obj = new GVGTeamInList(team); + players.push(obj); + } + } + + await leaveGVGAreaTeamChannel(roleId, sid); + await addRoleToAreaTeamChannel(roleId, groupKey, myTeam.areaId, sid); + + return resResult(STATUS.SUCCESS, { + cityId, areaId: myTeam.areaId, points, players + }); + } + + // 开始移动 + // areaId: 要移动的目标据点 id + async startMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { areaId, cityId, teamCode } = msg; + + let groupKey = await getGroupKey(serverId); + + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + let checkResult = checkMoveStatus(team, cityId, areaId); + if(checkResult.code != 0) return resResult(checkResult); + + team = await GVGTeamModel.startMove(teamCode, areaId, team.areaId); + + // 更新内存数据 + let teamObj = getGVGBattleData(groupKey); + teamObj.move(teamCode, areaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime); + + await leaveGVGAreaTeamChannel(roleId, sid); + await addRoleToAreaTeamChannel(roleId, groupKey, areaId, sid); + await pushTeamMoveMessage(team); + return resResult(STATUS.SUCCESS, { areaId, cityId, stopMoveTime: team.stopMoveTime, moveCdTime: team.moveCdTime }); + } + + // 停止移动 + // areaId: 移动到的目标据点 id + async stopMove(msg: { cityId: number, areaId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const { areaId, cityId, teamCode } = msg; + + let groupKey = await getGroupKey(serverId); + + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!team) return resResult(STATUS.GVG_BATTLE_TEAM_NOT_FOUND); + if(team.cityId != cityId && team.areaId != areaId) return resResult(STATUS.GVG_BATTLE_IS_NOT_IN_CITY); + + team = await GVGTeamModel.stopMove(teamCode, areaId); + // 更新内存数据 + let teamObj = getGVGBattleData(groupKey); + teamObj.move(teamCode, areaId, 0, team.startMoveTime, team.stopMoveTime); + + return resResult(STATUS.SUCCESS, { areaId, cityId, curTeam: new MyTeamInfo(team) }); + } + + // 队伍入驻积分点 + async teamSettle(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { cityId, areaId, pointId, teamCode } = msg; + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let groupKey = await getGroupKey(serverId); + + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + + let checkResult = checkSettleStatus(myTeam); + if(checkResult.code != 0) return resResult(checkResult); + + let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); + if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); + if(dicAreaPoint.type != GVG_POINT_TYPE.ROBOT) return resResult(STATUS.GVG_POINT_TYPE_ERR); + + let point = await GVGCityAreaPointModel.settlePoint(cityId, areaId, pointId, myTeam); + if(!point) return resResult(STATUS.GVG_POINT_HAS_SETTLED); + const curTeam = await GVGTeamModel.settlePoint(teamCode, pointId); + + let teamObj = getGVGBattleData(groupKey); + teamObj.teamSettle(roleId, teamCode, pointId); + + // addTeamSettleRec(curTeam); + await sendAreaPointChange(groupKey, curTeam.areaId, curTeam.cityId, pointId, myTeam.pointId, curTeam); + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) }); + } + + // 队伍离开积分点 + async teamLeave(msg: { cityId: number, areaId: number, pointId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { pointId, teamCode } = msg; + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let groupKey = await getGroupKey(serverId); + + let myTeam = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!myTeam) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + + let checkResult = checkSettleStatus(myTeam); + if(checkResult.code != 0) return resResult(checkResult); + + let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); + if(dicAreaPoint.areaId != myTeam.areaId) return resResult(STATUS.GVG_POINT_NOT_AREA); + + const curTeam = await GVGTeamModel.settlePoint(teamCode, 0); + await GVGCityAreaPointModel.leavePoint(configId, groupKey, teamCode); + let teamObj = getGVGBattleData(groupKey); + teamObj.teamSettle(roleId, teamCode, 0); + + await sendAreaPointChange(groupKey, curTeam.areaId, curTeam.cityId, pointId, myTeam.pointId, curTeam); + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(curTeam) }); + } + + // 队伍开始攻击 + // teamCode: 攻击方队伍 + // oppoTeamCode: 防守方队伍 + async battleStart(msg: { cityId: number, teamCode: string, oppoTeamCode: string, pointId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { teamCode, oppoTeamCode } = msg; + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + if(startFightTime > nowSeconds()) return resResult(STATUS.GVG_NOT_BATTLE_TIME); + if(endFightTime < nowSeconds()) return resResult(STATUS.GVG_BATTLE_IS_END); + + let groupKey = await getGroupKey(serverId); + + let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode); + let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam); + if(checkStatus.code != 0) return resResult(checkStatus); + + const warId = getGVGWarId(defenseTeam); + const battleRecord = await GVGBattleRecModel.createRec(configId, groupKey, warId, attackTeam, defenseTeam); + + attackTeam = await GVGTeamModel.battleStartLockAttack(teamCode); + defenseTeam = await GVGTeamModel.battleStartLockDefense(oppoTeamCode, teamCode); + // 内存处理 + let teamObj = getGVGBattleData(groupKey); + teamObj.setTime(attackTeam.teamCode, attackTeam); + teamObj.setTime(defenseTeam.teamCode, defenseTeam); + let heroes = getOppHeroes(warId, defenseTeam.isRobot, defenseTeam.lineup) + + return resResult(STATUS.SUCCESS, { battleCode: battleRecord.battleCode, warId, isRobot: defenseTeam.isRobot, heroes, combo: defenseTeam.combo, curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); + } + + // 队伍停止攻击 + async battleEnd(msg: { cityId: number, battleCode: string, isSuccess: boolean, myHeroes: gvgEndParamInter[], oppHeroes: gvgEndParamInter[] }, session: BackendSession) { + const serverId = session.get('serverId'); + const { cityId, battleCode, isSuccess, myHeroes = [], oppHeroes = [] } = msg; + + let { configId, period } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + if(startFightTime > nowSeconds()) return resResult(STATUS.GVG_NOT_BATTLE_TIME); + if(endFightTime < nowSeconds()) return resResult(STATUS.GVG_BATTLE_IS_END); + + const record = await GVGBattleRecModel.findByBattleCode(battleCode); + if(!record) return resResult(STATUS.GVG_BATTLEREC_NOT_FOUND); + if(record.battleEndTime > 0) return resResult(STATUS.GVG_BATTLEREC_HAS_SUMMIT); + let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(record.attackTeam.teamCode, record.defenseTeam.teamCode); + let attackOriginId = attackTeam.pointId; + if(defenseTeam.lockTeamCode != attackTeam.teamCode) return resResult(STATUS.GVG_LOCK_TIME_OUT) + + let groupKey = await getGroupKey(serverId); + let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); + if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); + + // 计算并更新两支队伍耐久 + let { win, fail } = gameData.gvgBattleDurabilityMinus; + attackTeam = await GVGTeamModel.battleEndAttack(attackTeam.teamCode, isSuccess? -win: -fail, getBirthAreaOfCity(city, attackTeam.leagueCode), await getTechReviveMinus(groupKey, configId, attackTeam.leagueCode), getNewLineup(attackTeam, myHeroes)); + defenseTeam = await GVGTeamModel.battleEndDefense(defenseTeam.teamCode, isSuccess? -fail: -win, getBirthAreaOfCity(city, defenseTeam.leagueCode), GVG.GVG_DEFAULT_DEFENSE_CD, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode), getNewLineup(defenseTeam, oppHeroes)); + if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 + if(!attackTeam.curTeamBreak) { + let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode); + if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + } else { + await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode); + } + } + if(attackTeam.curTeamBreak && attackTeam.originPointId) { + await GVGCityAreaPointModel.leavePoint(configId, groupKey, attackTeam.teamCode); + } + if(defenseTeam.curTeamBreak) { + let attackScore = calBattleScoreByCe(isSuccess, defenseTeam.lineupCe); + let attackCurTeamBreak = attackTeam.curTeamBreak; + attackTeam = await GVGTeamModel.addScore(attackTeam.teamCode, attackScore, 0); + attackTeam.curTeamBreak = attackCurTeamBreak; + await redisAddBattleScore(attackTeam, attackScore); + } + + // 更新内存 + let teamObj = getGVGBattleData(groupKey); + teamObj.battleEnd([attackTeam, defenseTeam]); + // 更新rec + let rec = await GVGBattleRecModel.battleEnd(battleCode, isSuccess, attackTeam, defenseTeam); + await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.PLAYER); + addBattleEndRec(rec); + // 连胜邮件 + sendWinStreakMessage(groupKey, cityId, attackTeam, defenseTeam, isSuccess); + + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); + } + + // 使用道具 + // teamCode: 要使用道具的队伍 + async useItem(msg: { cityId: number, itemId: number, teamCode: string, oppoTeamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { cityId, itemId, teamCode, oppoTeamCode } = msg; + + if(itemId != GVG_ITEM.KNIFE) return resResult(STATUS.GVG_ITEM_CANNOT_USE); + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let groupKey = await getGroupKey(serverId); + + let { attackTeam, defenseTeam } = await GVGTeamModel.findBattleTeams(teamCode, oppoTeamCode); + let attackOriginId = attackTeam.pointId; + let checkStatus = checkGVGBattleStart(roleId, attackTeam, defenseTeam); + if(checkStatus.code != 0) return resResult(checkStatus); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.KNIFE, count: 1 }], [], ITEM_CHANGE_REASON.GVG_USE_ITEM); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + let city = await GVGCityModel.findByCityId(configId, groupKey, cityId); + if (!city) return resResult(STATUS.GVG_CITY_NOT_FOUND); + + let hurt = await getTechKnifeHurt(configId, attackTeam.leagueCode); + defenseTeam = await GVGTeamModel.battleEndDefense(oppoTeamCode, -hurt, getBirthAreaOfCity(city, defenseTeam.leagueCode), 0, await getTechReviveMinus(groupKey, configId, defenseTeam.leagueCode)); + if(defenseTeam.curTeamBreak && defenseTeam.originPointId > 0 && !defenseTeam.isCatapult) { // 打败的对手原来占领着一个位置,现在这个位置是你的了 + if(!attackTeam.curTeamBreak) { + let settleResult = await GVGCityAreaPointModel.settlePoint(cityId, attackTeam.areaId, defenseTeam.originPointId, attackTeam, defenseTeam.isRobot? '': defenseTeam.teamCode); + if(settleResult) attackTeam = await GVGTeamModel.settlePoint(attackTeam.teamCode, defenseTeam.originPointId); + } else { + await GVGCityAreaPointModel.leavePoint(configId, groupKey, defenseTeam.teamCode); + } + + } + if(defenseTeam.curTeamBreak) { + let attackScore = calBattleScoreByCe(true, defenseTeam.lineupCe); + await redisAddBattleScore(attackTeam, attackScore); + } + + // 更新内存 + let teamObj = getGVGBattleData(groupKey); + teamObj.battleEnd([attackTeam, defenseTeam]); + + await battleEndSendMessage(groupKey, cityId, defenseTeam, {...attackTeam, originPointId: attackOriginId}, GVG_ATTACK_TYPE.KNIFE); + return resResult(STATUS.SUCCESS, { curTeam: new MyTeamInfo(attackTeam), oppTeam: new MyTeamInfo(defenseTeam) }); + } + + // 复活队伍 + async reviveTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { teamCode } = msg; + let { configId, period } = getGVGPeriodData(); + let groupKey = await getGroupKey(serverId); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let team = await GVGTeamModel.findMyTeamByCode(roleId, teamCode); + if(!team) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + if(team.restartTime < nowSeconds()) return resResult(STATUS.GVG_TEAM_NOT_NEED_REVIVE); + + let userData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + let reviveCnt = userData?.reviveCnt||0; + + const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.REVIVE_COIN, 1); + if(hasItem) { + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.REVIVE_COIN, count: 1 }], [], ITEM_CHANGE_REASON.GVG_REVIVE); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + } else { + let gold = getReviveGold(reviveCnt + 1); + const costResult = await handleCost(roleId, sid, [getGoldObject(gold)], ITEM_CHANGE_REASON.GVG_REVIVE); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + userData = await GVGUserDataModel.addReviveCnt(configId, myLeague.leagueCode, roleId, 1); + reviveCnt = userData?.reviveCnt||0; + } + team = await GVGTeamModel.reviveTeam(teamCode); + + // 更新内存 + let teamObj = getGVGBattleData(groupKey); + teamObj.battleEnd([team]); + + // 更新成功返回队伍信息 + return resResult(STATUS.SUCCESS, { reviveCnt, curTeam: new MyTeamInfo(team) }); + } + + // 获取战报 + // type: 战报类型 + async getRecs(msg: { type: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const { type } = msg; + // 根据 type 获取战报 + let { configId, period } = getGVGPeriodData(); + let groupKey = await getGroupKey(serverId); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let recs: GVGRecType[] = []; + if(type == GVG_REC_TYPE.BATTLE_BY_CITY) { + recs = await GVGRecModel.findBattleRecByGroup(configId, groupKey); + } else if (type == GVG_REC_TYPE.BATTLE_BY_LEAGUE) { + recs = await GVGRecModel.findBattleRecByLeague(configId, myLeague.leagueCode); + } else if (type == GVG_REC_TYPE.BATTLE_BY_ROLE) { + recs = await GVGRecModel.findBattleRecByRole(configId, roleId, myLeague.leagueCode); + } + return resResult(STATUS.SUCCESS, { recs }); + } + + // 获取概况 + async getOverview(msg: {}, session: BackendSession) { + const serverId = session.get('serverId'); + + let { configId } = getGVGPeriodData(); + let groupKey = await getGroupKey(serverId); + let serverType = await getGVGServerType(serverId); + + const cities = await GVGCityModel.findByConfigAndGroup(configId, groupKey); + const points = await GVGCityAreaPointModel.findByConfig(configId, groupKey); + + let result: { cityId: number, guardLeagueName: string, areas: { areaId: number, points: { pointId: number, guardLeagueName: string }[] }[] }[] = []; + for(let [ cityId, { mapType, battleAreaIds }] of gameData.gvgCity) { + if(mapType != serverType) continue; + let city = cities.find(cur => cur.cityId == cityId); + let areas: { areaId: number, points: {pointId: number, guardLeagueName: string }[]}[] = []; + for(let areaId of battleAreaIds) { + let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; + let pointArrs: { pointId: number, guardLeagueName: string }[] = []; + for(let pointId of pointIds) { + let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); + if(!dicAreaPoint) continue; + let playerPoint = points.find(cur => cur.pointId == pointId); + pointArrs.push({ pointId, guardLeagueName: playerPoint? (playerPoint.leagueName||"无"): dicAreaPoint.name }); + } + if(pointArrs.length > 0) areas.push({ areaId, points: pointArrs }); + } + result.push({ cityId, guardLeagueName: city?.guardLeagueName||'', areas }); + } + + return resResult(STATUS.SUCCESS, { cities: result }); + } + + // 排行榜 + async getRanks(msg: {}, session: BackendSession) { + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const roleId = session.get('roleId'); + + let { configId } = getGVGPeriodData(); + let groupKey = await getGroupKey(serverId); + let serverType = await getGVGServerType(serverId); + let cities = await getAllGVGCitiesInfo(configId, groupKey, serverType); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { myRank: myLeagueRank, ranks: leagueRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }, { leagueCode: myLeague.leagueCode }); + let { myRank: myMemberRank, ranks: memberRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }, { roleId }); + let { myRank: myMemberSettleRank, ranks: memberSettleRanks } = await getBattleRank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }, { roleId }); + + return resResult(STATUS.SUCCESS, { + cities, leagueRanks, myLeagueRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank + }) + } + + // 设置目标城池 + async setTargetCity(msg: { cityId: number, isTarget: boolean }, session: BackendSession) { + + const guildCode = session.get('guildCode'); + const roleId = session.get('roleId'); + const { cityId, isTarget } = msg; + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let dicCity = gameData.gvgCity.get(cityId); + if(!dicCity) return resResult(STATUS.GVG_CITY_NOT_FOUND); + + let targetCities: number[] = []; + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_TARGET_CITY); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + if(isTarget) { + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + targetCities = leaguePrepare?.targetCities||[]; + if(targetCities.indexOf(cityId) != -1) return resResult(STATUS.GVG_TARGET_CITY_HAS_SET); + if(targetCities.length >= 2) return resResult(STATUS.GVG_TARGET_CITY_CNT_MAX); + leaguePrepare = await GVGLeaguePrepareModel.setTargetCity(configId, myLeague.leagueCode, cityId); + targetCities = leaguePrepare?.targetCities||[]; + } else { + let leaguePrepare = await GVGLeaguePrepareModel.cancelTargetCity(configId, myLeague.leagueCode, cityId); + targetCities = leaguePrepare?.targetCities||[]; + } + // 发送消息 + for(let guildCode of myLeague.guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GVG_TARGET_CITY_UPDATE, { targetCities }); + } + + return resResult(STATUS.SUCCESS, { + configId, targetCities + }); + } + + // 设置管理信息 + async setNotice(msg: { notice: string }, session: BackendSession) { + + const guildCode = session.get('guildCode'); + const roleId = session.get('roleId'); + const { notice = '' } = msg; + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId, period } = getGVGPeriodData(); + if (period != GVG_PERIOD.BATTLE) return resResult(STATUS.GVG_NOT_BATTLE_PERIOD); + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_NOTICE); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + let leaguePrepare = await GVGLeaguePrepareModel.setNotice(configId, myLeague.leagueCode, notice); + if(!leaguePrepare) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + for(let guildCode of myLeague.guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GVG_NOTICE_UPDATE, { notice: leaguePrepare.notice }); + } + return resResult(STATUS.SUCCESS, { + configId, notice: leaguePrepare.notice + }); + } + + // enterCity里返回的那个ranks + async getRankByCity(msg: { cityId: number }, session: BackendSession) { + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const roleId = session.get('roleId'); + const { cityId } = msg; + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId } = getGVGPeriodData(); + const groupKey = await getGroupKey(serverId); + + const { ranks, myRank } = await getBattleRanksByCity(configId, groupKey, cityId, myLeague); + const { ranks: memberRanks, myRank: myMemberRank } = await getPlayerRanksByCity(configId, groupKey, cityId, roleId); + const { ranks: memberSettleRanks, myRank: myMemberSettleRank } = await getPlayerSettleRanksByCity(configId, groupKey, cityId, roleId); + return resResult(STATUS.SUCCESS, { + cityId, ranks, myRank, memberRanks, myMemberRank, memberSettleRanks, myMemberSettleRank + }) + } + + // 获取我的编队信息 + async getOppTeam(msg: { cityId: number, teamCode: string }, session: BackendSession) { + let { teamCode } = msg; + const team = await GVGTeamModel.findByCode(teamCode) + if (!team) return resResult(STATUS.GVG_TEAM_NOT_FOUND); + const warId = getGVGWarId(team); + + return resResult(STATUS.SUCCESS, { warId, oppTeam: new MyTeamInfo(team) }); + } + + async debugStartSchedule() { + let { countdownTime } = getGVGPeriodData(); + pinus.app.rpc.guild.guildRemote.setPeriodTime.broadcast(nowSeconds(), countdownTime); + await pinus.app.rpc.systimer.systimerRemote.gvgBattleStartSchedule.broadcast(); + return resResult(STATUS.SUCCESS); + } + + async debugEndSchedule() { + pinus.app.rpc.guild.guildRemote.resetPeriodTime.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.gvgBattleEndSchedule.broadcast(); + return resResult(STATUS.SUCCESS); + } + + async debugAddRobots(msg: { cityId: number, teamCnt: number }, session: BackendSession) { + const serverId = session.get('serverId'); + const { cityId, teamCnt } = msg; + + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + const teamObj = getGVGBattleData(groupKey); + const teams: any[] = []; + const areaIds = gameData.gvgCity.get(cityId)?.areaIds||[]; + for(let i = 0; i < teamCnt; i++) { + let areaId = getRandSingleEelm(areaIds); + teams.push({ configId, confirmConfigId: configId, title: 1, groupKey, roleId: 'test', roleName: 'test' + i, serverId, lv: 100, teamCode: genCode(8), index: 3, leagueCode: 'test', leagueName: 'test' + i, guildCode: 'test', areaId, cityId, pointId: 0, head: EXTERIOR.EXTERIOR_FACE, frame: EXTERIOR.EXTERIOR_FACECASE, spine: EXTERIOR.EXTERIOR_APPEARANCE, durability: 100, maxDurability: 100, restartTime: nowSeconds(), attackTime: nowSeconds(), lockTime: nowSeconds(), startMoveTime: nowSeconds(), stopMoveTime: nowSeconds(), moveCdTime: nowSeconds(), defenseTime: nowSeconds(), lineupCe: 100000 }) + } + await GVGTeamModel.insertMany(teams); + teamObj.enterCity(...teams); + + return resResult(STATUS.SUCCESS); + } + + private moveInterval: NodeJS.Timer; + private attackInterval: NodeJS.Timer; + async debugMoveRobots(msg: { cityId: number, frequency: number }, session: BackendSession) { + const serverId = session.get('serverId'); + const { cityId, frequency } = msg; + + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + const teamObj = getGVGBattleData(groupKey); + const serverNames = await getAllServerName(); + + if(this.moveInterval) { + clearInterval(this.moveInterval); + } + + let fun = async () => { + let teams = teamObj.findTeamsByRole('test'); + for(let i = 0; i < teams.length; i++) { + let teamMem = teams[i]; + setTimeout(async () => { + let fromAreaId = teamMem.areaId; + let dicArea = gameData.gvgArea.get(fromAreaId); + // 更新内存数据 + let toAreaId = getRandSingleEelm(dicArea.relateArea); + let team = await GVGTeamModel.startMove(teamMem.teamCode, toAreaId, fromAreaId); + + // 更新内存数据 + let teamObj = getGVGBattleData(groupKey); + teamObj.move(teamMem.teamCode, toAreaId, team.fromAreaId, team.startMoveTime, team.stopMoveTime); + await pushTeamMoveMessage(team); + }, i * 100); + } + + }; + await fun(); + this.moveInterval = setInterval(fun, frequency) + return resResult(STATUS.SUCCESS) + } + + async debugAttacks(msg: { cityId: number, frequency: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const { cityId, frequency } = msg; + + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + const teamObj = getGVGBattleData(groupKey); + const serverNames = await getAllServerName(); + + if(this.attackInterval) { + clearInterval(this.attackInterval); + } + let spineCnt = await getSpineCnt(); + let fun = async () => { + for(let areaId of teamObj.findAreas()) { + let teams = teamObj.findTeamsByArea(areaId, spineCnt); + let areaTeams = teams.map(team => new GVGTeamInList(team as any)); + await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { + cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: areaTeams + }); + let myTeams = teams.filter(team => team.roleId == roleId).map(team => new GVGTeamInList(team as any)); + if(myTeams.length > 0) await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { + cityId, areaId, attackType: GVG_ATTACK_TYPE.PLAYER, teams: myTeams + }, sid); + } + + }; + await fun(); + this.attackInterval = setInterval(fun, frequency) + return resResult(STATUS.SUCCESS) + } + + async debugStopMoveRobot(msg: { cityId: number }, session: BackendSession) { + if(this.moveInterval) { + clearInterval(this.moveInterval); + } + if(this.attackInterval) { + clearInterval(this.attackInterval); + } + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/gvgFightHandler.ts b/game-server/app/servers/guild/handler/gvgFightHandler.ts index a2c8d10c1..01114c86d 100644 --- a/game-server/app/servers/guild/handler/gvgFightHandler.ts +++ b/game-server/app/servers/guild/handler/gvgFightHandler.ts @@ -1,584 +1,585 @@ -import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; -import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, ITEM_CHANGE_REASON, REDIS_KEY, ROLE_SELECT, STATUS, TASK_TYPE, VESTIGE_OPP_STATUS, VESTIGE_STATUS, WAR_TYPE } from "../../../consts"; -import { BattleRecordModel } from "../../../db/BattleRecord"; -import { GVGLeagueModel } from "../../../db/GVGLeague"; -import { GVGUserDailyDataModel } from "../../../db/GVGUserDailyData"; -import { GVGUserItemModel } from "../../../db/GVGUserItem"; -import { GVGVestigeLeagueRankModel } from "../../../db/GVGVestigeLeagueRank"; -import { GVGVestigeLockModel } from "../../../db/GVGVestigeLock"; -import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank"; -import { GVGVestigeRecModel, GVGVestigeRecUpdate } from "../../../db/GVGVestigeRec"; -import { GVGVestigeSumRankModel } from "../../../db/GVGVestigeSumRank"; -import { HeroModel } from "../../../db/Hero"; -import { RoleModel } from "../../../db/Role"; -import { GVGVestigeOppLineup, VestigeRank } from "../../../domain/gvgField/returnData"; -import { RoleRankInfo } from "../../../domain/rank"; -import { getRemoteRplFilePath, getRemoteRplPrefix } from "../../../pubUtils/battleUtils"; -import { gameData } from "../../../pubUtils/data"; -import { GVG } from "../../../pubUtils/dicParam"; -import { RewardInter, pvpEndParamInter } from "../../../pubUtils/interface"; -import { parseGoodStr, resResult } from "../../../pubUtils/util"; -import { isHeroHidden } from "../../../services/dataService"; -import { calBreakGoods, checkHeroIsUsedInOtherVestige, checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackHeroInfo, generateAttackInfo, generateDefenseInfo, getDayKeyInfo, getMyVestigeRank, getOppDetailData, getOppPlayerByRanks, getVestigeRecStatus, getVestigeRank, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks, saveScoreToRank, updateMyVestigeRank, saveVestigeRankSchedule, calVestigeLeagueBoxRewards, checkFightTime, savePlayerRank, pushGvgFightIconShow } from "../../../services/gvg/gvgFightService"; -import { addGVGReward, combinePushItem, handleGVGCost } from "../../../services/gvg/gvgItemService"; -import { addGVGActive, getGVGActive } from "../../../services/gvg/gvgPrepareService"; -import { addVestigeBattleEndRec } from "../../../services/gvg/gvgRecService"; -import { getGroupKey, getGVGPeriodData, getMemberJoinLeagueTime } from "../../../services/gvg/gvgService"; -import { checkBattleHeroesByHid, getBattleRecordParam } from "../../../services/normalBattleService"; -import { Rank } from "../../../services/rankService"; -import { getAllServerName } from "../../../services/redisService"; -import { CheckMeterial } from "../../../services/role/checkMaterial"; -import { checkGVGTask } from "../../../services/task/taskService"; -import { Combo } from "../../../domain/battleField/pvp"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GVGProduceHandler(app); -} - -export class GVGProduceHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 遗迹页面 - async getVestige(msg: { vestigeId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const { vestigeId } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - if(!await checkVestige(serverId, vestigeId)) { - return resResult(STATUS.GVG_VESTIGE_ERR); - } - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const myUserDailyData = await GVGUserDailyDataModel.findByRole(configId, myLeague.leagueCode, roleId); - - let groupKey = await getGroupKey(serverId); - - let dicRankMap = gameData.gvgVestige.get(vestigeId); - if(!dicRankMap) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague); - if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { rank, lineup, oppRanks, refreshCnt, combo } = myVestigeRank; - - let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0); - let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks); - let usedHeroes = await getVestigeUsedHeroes(roleId, vestigeId); - - return resResult(STATUS.SUCCESS, { - vestigeId, - myRank: rank, - score: dicRankMap?.get(rank)?.score||0, - lineup, lineupCe, combo, - oppPlayers, - refreshCnt, - usedHeroes, - costGoldCnt: myUserDailyData?.costGoldCnt||0 - }) - } - - // 编辑阵容 - async saveLineup(msg: { vestigeId: number, lineup: [{ actorId: number, dataId: number, order: number, correspondingVar: number, subHid: number }], combo: Combo[] }, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const { vestigeId, lineup: heroes, combo } = msg; - - if(!await checkVestige(serverId, vestigeId)) { - return resResult(STATUS.GVG_VESTIGE_ERR); - } - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - let groupKey = await getGroupKey(serverId); - - let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); - if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - for(let { actorId } of heroes) { - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - } - let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); - if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - // 检查武将是否在其他遗迹中使用了 - if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED); - - let lineup = heroes.map(hero => { - let curHero = dbHeroes.find(cur => cur.hid == hero.actorId); - return { actorId: curHero.hid, dataId: hero.dataId, order: hero.order, subHid: hero.subHid, correspondingVar: hero.correspondingVar, ce: curHero.ce } - }); - let vestigeRank = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { lineup, combo, hasDefense: true }); - - return resResult(STATUS.SUCCESS, { - vestigeId, - lineup: vestigeRank.lineup, - combo: vestigeRank.combo, - lineupCe: vestigeRank.lineup.reduce((pre, cur) => pre + cur.ce, 0), - }); - } - - // 获取对手阵容消息 - async getOppLineup(msg: { vestigeId: number, roleId: string, rank: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - const guildCode = session.get('guildCode'); - - let { vestigeId, roleId: targetRoleId, rank } = msg; - - if(!await checkVestige(serverId, vestigeId)) { - return resResult(STATUS.GVG_VESTIGE_ERR); - } - let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名 - - const serverNames = await getAllServerName(); - - let isRobot = targetRoleId.startsWith('robot'); - let result = new GVGVestigeOppLineup(vestigeId); - result.setMyRank(myVestigeRank?.rank||0); - let dicGVGVestige = gameData.gvgVestige.get(vestigeId)?.get(rank); - if(!dicGVGVestige) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - if(isRobot) { - let dicWar = gameData.war.get(dicGVGVestige?.warId); - let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); - result.setRobot(dicGVGVestige, dicWarJson, serverNames[serverId]); - } else { - let hisVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId); - if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND); - - let role = await RoleModel.findByRoleId(hisVestigeRank.roleId, 'roleId roleName serverId guildName title lv heads head spines spine frames frame') - if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND); - - let hids = hisVestigeRank.lineup?.map(cur => cur.actorId)||[]; - let heroes = await HeroModel.findByHidRange(hids, targetRoleId, 'hid skinId quality star colorStar lv ce'); - const { leagueCode, name } = myLeague; - result.setPlayer(dicGVGVestige, role, heroes, serverNames, name, leagueCode); - } - return resResult(STATUS.SUCCESS, result); - } - - // 刷新对手 - async refreshOpp(msg: { vestigeId: number }, session: BackendSession) { - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let { vestigeId } = msg; - - if(!await checkVestige(serverId, vestigeId)) { - return resResult(STATUS.GVG_VESTIGE_ERR); - } - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - let groupKey = await getGroupKey(serverId); - - let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); - let refreshCnt = myVestigeRank.refreshCnt||0; - if(refreshCnt >= GVG.GVG_REFRESH_TIME) return resResult(STATUS.GVG_VESTIGE_REFESH_CNT_MAX); - - let oppRanks = refreshVestigeOppRanks(myVestigeRank.rank); - myVestigeRank = await GVGVestigeRankModel.refreshOpp(roleId, vestigeId, oppRanks ); - - let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, myVestigeRank.oppRanks); - - // 返回 - return resResult(STATUS.SUCCESS, { vestigeId, refreshCnt: myVestigeRank.refreshCnt, oppPlayers }); - } - - // 选择对手 - async chooseOpp(msg: { vestigeId: number, roleId: string, rank: number, myRank: number, costGold: boolean }, session: BackendSession) { - - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - let sid = session.get('sid'); - let { vestigeId, roleId: targetRoleId, rank, myRank, costGold } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - if(!checkFightTime()) return resResult(STATUS.GVG_VESTIGE_TIME_OUT); - - if(!await checkVestige(serverId, vestigeId)) { - return resResult(STATUS.GVG_VESTIGE_ERR); - } - let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); - if(!dicRank) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 检查对手排名/自己排名 - if(!checkVestigeRank(myRank, rank)) return resResult(STATUS.GVG_VESTIGE_RANK_ERR); - - let goldCost = parseGoodStr(GVG.GVG_VESTIGE_BUY_COST); - if(costGold) { - let check = new CheckMeterial(roleId); - let isEnough = await check.decrease(goldCost); - if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } else { - const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.FIGHT_COIN, 1); - if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - } - const groupKey = await getGroupKey(serverId); - - let status = await checkVestigeOppStatus(configId, groupKey, vestigeId, roleId, myRank, targetRoleId, rank); // 锁 - if(status != VESTIGE_OPP_STATUS.BATTLE) { - let oppRanks = refreshVestigeOppRanks(myRank); - let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks); - return resResult(STATUS.SUCCESS, { status, oppPlayers }); - } - - // 扣征战令 - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, costGold? []: [{ id: GVG_ITEM.FIGHT_COIN, count: 1 }], costGold? goldCost: [], ITEM_CHANGE_REASON.GVG_VESTIGE_START); - if(!costResult) { - await GVGVestigeLockModel.releaseLock(groupKey, vestigeId, rank); - return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - } - let userDailyData = await GVGUserDailyDataModel.incCostGoldCnt(configId, myLeague.leagueCode, roleId, costGold); - // 获取征战令对应奖励 - const leagueGoods = costGold? []: await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicRank.battleLeagueReward, dicRank.battleReward, ITEM_CHANGE_REASON.GVG_VESTIGE_START); - // 消耗征战令的获得活跃 - let active = costGold? await getGVGActive(myLeague.leagueCode, roleId): await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_FIGHT_COIN); - // 创建rec - const attackInfo = await generateAttackInfo(roleId, myLeague, myRank); - const defenseInfo = await generateDefenseInfo(targetRoleId, vestigeId, rank); - const rec = await GVGVestigeRecModel.createRec(configId, vestigeId, groupKey, dicRank.warId, attackInfo, defenseInfo, leagueGoods); - const oppDetail = await getOppDetailData(rec); - - checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_VESTIGE, { count: 1 }); - return resResult(STATUS.SUCCESS, { - active, - costGoldCnt: userDailyData?.costGoldCnt||0, - ...oppDetail - }); - } - - // 出战界面撤退 - async giveupCheck(msg: { battleCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let { battleCode } = msg; - // 更新ladderMatchRec - let rec = await GVGVestigeRecModel.giveup(roleId, battleCode); - if(rec && rec.defenseInfo) { - await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank); - } - - return resResult(STATUS.SUCCESS, { - status: 0, time: 0, - leagueGoods: rec.leagueGoods - }); - } - - // 获取对手具体战场数据 - async getOppData(msg: { battleCode: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let { battleCode } = msg; - - let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); - if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); - let status = getVestigeRecStatus(rec).status; - if(status == VESTIGE_STATUS.COMPLETE || status == VESTIGE_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE); - - let result = await getOppDetailData(rec); - return resResult(STATUS.SUCCESS, result); - } - - // 布完阵开始挑战 - async checkBattle(msg: { battleCode: string, heroes: { actorId: number, dataId: number, order: number, subHid: number }[], combo: Combo[] }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const { battleCode, heroes, combo } = msg; - - let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); - if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND); - if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.CHECK) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR); - const { vestigeId, defenseInfo: { oldRank: rank }, warId } = rec; - - for(let { actorId } of heroes) { - if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - } - let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); - if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - // 检查武将是否在其他遗迹中使用了 - if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED); - - // 更新锁 - const groupKey = await getGroupKey(serverId); - let lock = await GVGVestigeLockModel.checkBattleLock(groupKey, vestigeId, rank, roleId); - if(!lock) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR); - - // 向vestigerec保存阵容 - const info = await generateAttackHeroInfo(heroes, dbHeroes, combo); - rec = await GVGVestigeRecModel.startBattle(battleCode, info.heroes, info.ce); - - // 更新battleRecord - let warInfo = gameData.war.get(warId); - await BattleRecordModel.updateBattleRecordByCode(battleCode, { - $set: { roleId, roleName, battleId: warId, status: 0, warName: warInfo?.gk_name, warType: warInfo?.warType, } - }); - - return resResult(STATUS.SUCCESS, { - time: Math.floor(rec.battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN, - battleCode: rec.battleCode - }); - } - - // 挑战结算 - async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const { battleCode, isSuccess, damageRecords, round } = msg; - - let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); - if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND); - if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.BATTLE) return resResult(STATUS.GVG_VESTIGE_BATTLE_END_STATUS_ERR); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let historyData = await GVGVestigeRankModel.findByRole(rec.vestigeId, roleId); - let historyRank = historyData?.rank||0; - // 交换排名 - let { isChange, atkData, defData, oldAtkData, endTime } = await GVGVestigeRankModel.changeRank(isSuccess, rec.vestigeId, rec.attackInfo, rec.defenseInfo); - atkData = await updateMyVestigeRank(isChange, atkData, defData, historyRank, rec); - // 更新vestigeRec - if(isChange) { - rec = await GVGVestigeRecModel.battleEnd(battleCode, isSuccess, endTime, atkData?.rank, defData? defData.rank: oldAtkData?.rank); - } else { - rec = await GVGVestigeRecModel.battleEnd(battleCode, isSuccess, endTime); - } - // 更新锁 - await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank); - // 更新battleRecord - await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } }); - - // 取消突破排名奖励 - // let { rewards, leagueRewards } = calBreakGoods(rec.vestigeId, historyRank, atkData.rank); - // let breakGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewards, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_END); - - await saveScoreToRank(rec); - addVestigeBattleEndRec(rec); - if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushGvgFightIconShow(rec.defenseRoleId, battleCode); - - return resResult(STATUS.SUCCESS, { - vestigeId: rec.vestigeId, - battleCode: rec.battleCode, - leagueGoods: rec.leagueGoods, - rank: atkData.rank, - score: gameData.gvgVestige.get(rec.vestigeId)?.get(atkData.rank)?.score??0, - historyRank: atkData.historyRank, - ...getVestigeRecStatus(rec), - oppPlayers: await getOppPlayerByRanks(serverId, rec.groupKey, rec.vestigeId, atkData.oppRanks), - // breakGoods, - lineup: atkData.lineup, - lineupCe: atkData.lineup.reduce((pre, cur) => pre + cur.ce, 0), - }); - } - - // 获取战报信息 - async getRec(msg: { vestigeId: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let { vestigeId } = msg; - let list = await GVGVestigeRecModel.findRec(roleId, vestigeId); - let result: (GVGVestigeRecUpdate & {rplFileUrl: string})[] = []; - for(let rec of list) { - const { attackRoleId, battleCode, hasRpl, remoteUrl } = rec; - const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; - const obj = getVestigeRecStatus(rec); - if(obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl }); - } - return resResult(STATUS.SUCCESS, { - list: result, - rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) - }); - } - - // 征战中原简单小排行榜 - async getLeagueRank(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let groupKey = await getGroupKey(serverId); - let serverNames = await getAllServerName(); - - const { ranks: leagueRank, myRank: myLeagueRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, true, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }); - const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, true, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames); - - return resResult(STATUS.SUCCESS, { - leagueRank, myLeagueRank, memberRank, myMemberRank - }) - } - - // 联军详细排名 - async getLeagueDetailRank(msg: {}, session: BackendSession) { - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const roleId = session.get('roleId'); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let groupKey = await getGroupKey(serverId); - let serverNames = await getAllServerName(); - let { configId } = getGVGPeriodData(); - - const { ranks, myRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, false, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }, serverNames); - const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, false, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames); - - let yesterdayRank = await GVGVestigeLeagueRankModel.getYesterdayRank(myLeague.leagueCode); - let joinTime = await getMemberJoinLeagueTime(myLeague.leagueCode, roleId, myLeague); - let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId, joinTime); - let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); - let { canReceiveBox, boxPreview } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); - - return resResult(STATUS.SUCCESS, { - ranks, myRank, - memberRank, myMemberRank, - latestRank: yesterdayRank?.rank||0, - canReceiveBox, boxPreview - }) - } - - // 玩家排行 - async getPlayerRank(msg: { vestigeId: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - let { vestigeId } = msg; - let groupKey = await getGroupKey(serverId); - - let dicRankMap = gameData.gvgVestige.get(vestigeId); - let serverNames = await getAllServerName(); - let vestigeRanks = await GVGVestigeRankModel.findRankByVestige(groupKey, vestigeId); - let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER, { groupKey, vestigeId }); - let ranks: VestigeRank[] = [], myRank: VestigeRank; - for(let { roleId: targetRoleId, rank, lineup } of vestigeRanks) { - let param = await r.getParam(rank, targetRoleId, [rank]); - if(!param) { - let role = await RoleModel.findByRoleId(targetRoleId, ROLE_SELECT.RANK); - await r.generParamAndSet(REDIS_KEY.USER_INFO, { roleId: targetRoleId }, { role }); - param = await r.getParam(rank, targetRoleId, [rank]); - } - let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0); - let serverName = serverNames[param.serverId]; - let score = dicRankMap?.get(param.rank)?.score||0; - - let obj = new VestigeRank(); - obj.setByRankParam(param, serverName, lineupCe, score); - if(obj.roleId == roleId) myRank = obj; - ranks.push(obj); - } - if(!myRank) { - let obj = new VestigeRank(); - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK); - obj.setByRole(role, serverNames[serverId]); - myRank = obj; - } - return resResult(STATUS.SUCCESS, { - vestigeId, - ranks, myRank - }) - - } - - // 领取排行榜获得的每日奖励 - async receiveBox(msg: { }, session: BackendSession) { - const guildCode = session.get('guildCode'); - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId } = getGVGPeriodData(); - let joinTime = await getMemberJoinLeagueTime(myLeague.leagueCode, roleId, myLeague); - let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId, joinTime); - let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); - if(canReceiveLeagueRanks.length <= 0 && canReceivePlayerRanks.length <= 0) return resResult(STATUS.GVG_RECEIVE_NO_RANK_REWARD); - - let { leagueReward, rewards } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); - let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); - await GVGVestigeLeagueRankModel.receiveRanks(canReceiveLeagueRanks.map(cur => cur._id), roleId); - await GVGVestigeSumRankModel.receiveRanks(canReceivePlayerRanks.map(cur => cur._id)); - - return resResult(STATUS.SUCCESS, { - leagueGoods, - canReceiveRanks: false - }) - } - - async debugCalRec(msg: { battleCode: string }, session: BackendSession) { - let rec = await GVGVestigeRecModel.findByBattleCode(msg.battleCode); - await saveScoreToRank(rec); - return resResult(STATUS.SUCCESS); - } - - async debugSaveScore(msg: {}, session: BackendSession) { - await saveVestigeRankSchedule(); - return resResult(STATUS.SUCCESS); - } - - async debugSetMyRank(msg: { vestigeId: number, rank: number }, session: BackendSession) { - const { vestigeId, rank } = msg; - - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - - let groupKey = await getGroupKey(serverId); - let { configId } = getGVGPeriodData(); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague) - let myRank = myData?.rank||0; - - let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank); - if(targetData) { - myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank }); - targetData = await GVGVestigeRankModel.updateByRoleId(vestigeId, targetData.roleId, { rank: myRank, oldRank: rank }); - } else { - myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank }); - } - await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: rank, oldRank: myRank, roleId, leagueCode: myLeague.leagueCode }); - if(targetData) { - await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: targetData.rank, oldRank: rank, roleId: targetData.roleId, leagueCode: targetData.leagueCode }); - } - - return resResult(STATUS.SUCCESS); - } - - async debugSetMyOpp(msg: { vestigeId: number, oppRanks: number[] }, session: BackendSession) { - const { vestigeId, oppRanks } = msg; - let roleId = session.get('roleId'); - await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { oppRanks }); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; +import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, ITEM_CHANGE_REASON, REDIS_KEY, ROLE_SELECT, STATUS, TASK_TYPE, VESTIGE_OPP_STATUS, VESTIGE_STATUS, WAR_TYPE } from "../../../consts"; +import { BattleRecordModel } from "@db/BattleRecord"; +import { GVGLeagueModel } from "@db/GVGLeague"; +import { GVGUserDailyDataModel } from "@db/GVGUserDailyData"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { GVGVestigeLeagueRankModel } from "@db/GVGVestigeLeagueRank"; +import { GVGVestigeLockModel } from "@db/GVGVestigeLock"; +import { GVGVestigeRankModel } from "@db/GVGVestigeRank"; +import { GVGVestigeRecModel, GVGVestigeRecUpdate } from "@db/GVGVestigeRec"; +import { GVGVestigeSumRankModel } from "@db/GVGVestigeSumRank"; +import { HeroModel } from "@db/Hero"; +import { RoleModel } from "@db/Role"; +import { GVGVestigeOppLineup, VestigeRank } from "@domain/gvgField/returnData"; +import { RoleRankInfo } from "@domain/rank"; +import { getRemoteRplFilePath, getRemoteRplPrefix } from "@pubUtils/battleUtils"; +import { gameData } from "@pubUtils/data"; +import { GVG } from "@pubUtils/dicParam"; +import { RewardInter, pvpEndParamInter } from "@pubUtils/interface"; +import { parseGoodStr, resResult } from "@pubUtils/util"; +import { isHeroHidden } from "../../../services/dataService"; +import { calBreakGoods, checkHeroIsUsedInOtherVestige, checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackHeroInfo, generateAttackInfo, generateDefenseInfo, getDayKeyInfo, getMyVestigeRank, getOppDetailData, getOppPlayerByRanks, getVestigeRecStatus, getVestigeRank, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks, saveScoreToRank, updateMyVestigeRank, saveVestigeRankSchedule, calVestigeLeagueBoxRewards, checkFightTime, savePlayerRank, pushGvgFightIconShow } from "../../../services/gvg/gvgFightService"; +import { addGVGReward, combinePushItem, handleGVGCost } from "../../../services/gvg/gvgItemService"; +import { addGVGActive, getGVGActive } from "../../../services/gvg/gvgPrepareService"; +import { addVestigeBattleEndRec } from "../../../services/gvg/gvgRecService"; +import { getGroupKey, getGVGPeriodData, getMemberJoinLeagueTime } from "../../../services/gvg/gvgService"; +import { checkBattleHeroesByHid, getBattleRecordParam } from "../../../services/normalBattleService"; +import { Rank } from "../../../services/rankService"; +import { getAllServerName } from "../../../services/redisService"; +import { CheckMeterial } from "../../../services/role/checkMaterial"; +import { checkGVGTask } from "../../../services/task/taskService"; +import { Combo } from "@domain/battleField/pvp"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGProduceHandler(app); +} + +export class GVGProduceHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 遗迹页面 + async getVestige(msg: { vestigeId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const { vestigeId } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + if(!await checkVestige(serverId, vestigeId)) { + return resResult(STATUS.GVG_VESTIGE_ERR); + } + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const myUserDailyData = await GVGUserDailyDataModel.findByRole(configId, myLeague.leagueCode, roleId); + + let groupKey = await getGroupKey(serverId); + + let dicRankMap = gameData.gvgVestige.get(vestigeId); + if(!dicRankMap) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague); + if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { rank, lineup, oppRanks, refreshCnt, combo } = myVestigeRank; + + let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0); + let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks); + let usedHeroes = await getVestigeUsedHeroes(roleId, vestigeId); + + return resResult(STATUS.SUCCESS, { + vestigeId, + myRank: rank, + score: dicRankMap?.get(rank)?.score||0, + lineup, lineupCe, combo, + oppPlayers, + refreshCnt, + usedHeroes, + costGoldCnt: myUserDailyData?.costGoldCnt||0 + }) + } + + // 编辑阵容 + async saveLineup(msg: { vestigeId: number, lineup: [{ actorId: number, dataId: number, order: number, correspondingVar: number, subHid: number }], combo: Combo[] }, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const { vestigeId, lineup: heroes, combo } = msg; + + if(!await checkVestige(serverId, vestigeId)) { + return resResult(STATUS.GVG_VESTIGE_ERR); + } + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + let groupKey = await getGroupKey(serverId); + + let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); + if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + for(let { actorId } of heroes) { + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + } + let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + // 检查武将是否在其他遗迹中使用了 + if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED); + + let lineup = heroes.map(hero => { + let curHero = dbHeroes.find(cur => cur.hid == hero.actorId); + return { actorId: curHero.hid, dataId: hero.dataId, order: hero.order, subHid: hero.subHid, correspondingVar: hero.correspondingVar, ce: curHero.ce } + }); + let vestigeRank = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { lineup, combo, hasDefense: true }); + + return resResult(STATUS.SUCCESS, { + vestigeId, + lineup: vestigeRank.lineup, + combo: vestigeRank.combo, + lineupCe: vestigeRank.lineup.reduce((pre, cur) => pre + cur.ce, 0), + }); + } + + // 获取对手阵容消息 + async getOppLineup(msg: { vestigeId: number, roleId: string, rank: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let { vestigeId, roleId: targetRoleId, rank } = msg; + + if(!await checkVestige(serverId, vestigeId)) { + return resResult(STATUS.GVG_VESTIGE_ERR); + } + let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名 + + const serverNames = await getAllServerName(); + + let isRobot = targetRoleId.startsWith('robot'); + let result = new GVGVestigeOppLineup(vestigeId); + result.setMyRank(myVestigeRank?.rank||0); + let dicGVGVestige = gameData.gvgVestige.get(vestigeId)?.get(rank); + if(!dicGVGVestige) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + if(isRobot) { + let dicWar = gameData.war.get(dicGVGVestige?.warId); + let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); + result.setRobot(dicGVGVestige, dicWarJson, serverNames[serverId]); + } else { + let hisVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId); + if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND); + + let role = await RoleModel.findByRoleId(hisVestigeRank.roleId, 'roleId roleName serverId guildName title lv heads head spines spine frames frame') + if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND); + + let hids = hisVestigeRank.lineup?.map(cur => cur.actorId)||[]; + let heroes = await HeroModel.findByHidRange(hids, targetRoleId, 'hid skinId quality star colorStar lv ce'); + const { leagueCode, name } = myLeague; + result.setPlayer(dicGVGVestige, role, heroes, serverNames, name, leagueCode); + } + return resResult(STATUS.SUCCESS, result); + } + + // 刷新对手 + async refreshOpp(msg: { vestigeId: number }, session: BackendSession) { + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let { vestigeId } = msg; + + if(!await checkVestige(serverId, vestigeId)) { + return resResult(STATUS.GVG_VESTIGE_ERR); + } + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + let groupKey = await getGroupKey(serverId); + + let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); + let refreshCnt = myVestigeRank.refreshCnt||0; + if(refreshCnt >= GVG.GVG_REFRESH_TIME) return resResult(STATUS.GVG_VESTIGE_REFESH_CNT_MAX); + + let oppRanks = refreshVestigeOppRanks(myVestigeRank.rank); + myVestigeRank = await GVGVestigeRankModel.refreshOpp(roleId, vestigeId, oppRanks ); + + let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, myVestigeRank.oppRanks); + + // 返回 + return resResult(STATUS.SUCCESS, { vestigeId, refreshCnt: myVestigeRank.refreshCnt, oppPlayers }); + } + + // 选择对手 + async chooseOpp(msg: { vestigeId: number, roleId: string, rank: number, myRank: number, costGold: boolean }, session: BackendSession) { + + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + let sid = session.get('sid'); + let { vestigeId, roleId: targetRoleId, rank, myRank, costGold } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + if(!checkFightTime()) return resResult(STATUS.GVG_VESTIGE_TIME_OUT); + + if(!await checkVestige(serverId, vestigeId)) { + return resResult(STATUS.GVG_VESTIGE_ERR); + } + let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); + if(!dicRank) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 检查对手排名/自己排名 + if(!checkVestigeRank(myRank, rank)) return resResult(STATUS.GVG_VESTIGE_RANK_ERR); + + let goldCost = parseGoodStr(GVG.GVG_VESTIGE_BUY_COST); + if(costGold) { + let check = new CheckMeterial(roleId); + let isEnough = await check.decrease(goldCost); + if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } else { + const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.FIGHT_COIN, 1); + if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + } + const groupKey = await getGroupKey(serverId); + + let status = await checkVestigeOppStatus(configId, groupKey, vestigeId, roleId, myRank, targetRoleId, rank); // 锁 + if(status != VESTIGE_OPP_STATUS.BATTLE) { + let oppRanks = refreshVestigeOppRanks(myRank); + let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks); + return resResult(STATUS.SUCCESS, { status, oppPlayers }); + } + + // 扣征战令 + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, costGold? []: [{ id: GVG_ITEM.FIGHT_COIN, count: 1 }], costGold? goldCost: [], ITEM_CHANGE_REASON.GVG_VESTIGE_START); + if(!costResult) { + await GVGVestigeLockModel.releaseLock(groupKey, vestigeId, rank); + return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + } + let userDailyData = await GVGUserDailyDataModel.incCostGoldCnt(configId, myLeague.leagueCode, roleId, costGold); + // 获取征战令对应奖励 + const leagueGoods = costGold? []: await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicRank.battleLeagueReward, dicRank.battleReward, ITEM_CHANGE_REASON.GVG_VESTIGE_START); + // 消耗征战令的获得活跃 + let active = costGold? await getGVGActive(myLeague.leagueCode, roleId): await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_FIGHT_COIN); + // 创建rec + const attackInfo = await generateAttackInfo(roleId, myLeague, myRank); + const defenseInfo = await generateDefenseInfo(targetRoleId, vestigeId, rank); + const rec = await GVGVestigeRecModel.createRec(configId, vestigeId, groupKey, dicRank.warId, attackInfo, defenseInfo, leagueGoods); + const oppDetail = await getOppDetailData(rec); + + checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_VESTIGE, { count: 1 }); + return resResult(STATUS.SUCCESS, { + active, + costGoldCnt: userDailyData?.costGoldCnt||0, + ...oppDetail + }); + } + + // 出战界面撤退 + async giveupCheck(msg: { battleCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let { battleCode } = msg; + // 更新ladderMatchRec + let rec = await GVGVestigeRecModel.giveup(roleId, battleCode); + if(rec && rec.defenseInfo) { + await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank); + } + + return resResult(STATUS.SUCCESS, { + status: 0, time: 0, + leagueGoods: rec.leagueGoods + }); + } + + // 获取对手具体战场数据 + async getOppData(msg: { battleCode: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let { battleCode } = msg; + + let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); + if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND); + let status = getVestigeRecStatus(rec).status; + if(status == VESTIGE_STATUS.COMPLETE || status == VESTIGE_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE); + + let result = await getOppDetailData(rec); + return resResult(STATUS.SUCCESS, result); + } + + // 布完阵开始挑战 + async checkBattle(msg: { battleCode: string, heroes: { actorId: number, dataId: number, order: number, subHid: number }[], combo: Combo[] }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const { battleCode, heroes, combo } = msg; + + let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); + if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND); + if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.CHECK) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR); + const { vestigeId, defenseInfo: { oldRank: rank }, warId } = rec; + + for(let { actorId } of heroes) { + if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + } + let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId)); + if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + // 检查武将是否在其他遗迹中使用了 + if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED); + + // 更新锁 + const groupKey = await getGroupKey(serverId); + let lock = await GVGVestigeLockModel.checkBattleLock(groupKey, vestigeId, rank, roleId); + if(!lock) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR); + + // 向vestigerec保存阵容 + const info = await generateAttackHeroInfo(heroes, dbHeroes, combo); + rec = await GVGVestigeRecModel.startBattle(battleCode, info.heroes, info.ce); + + // 更新battleRecord + let warInfo = gameData.war.get(warId); + await BattleRecordModel.updateBattleRecordByCode(battleCode, { + $set: { roleId, roleName, battleId: warId, status: 0, warName: warInfo?.gk_name, warType: warInfo?.warType, } + }); + + return resResult(STATUS.SUCCESS, { + time: Math.floor(rec.battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN, + battleCode: rec.battleCode + }); + } + + // 挑战结算 + async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const { battleCode, isSuccess, damageRecords, round } = msg; + + let rec = await GVGVestigeRecModel.findByBattleCode(battleCode); + if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND); + if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.BATTLE) return resResult(STATUS.GVG_VESTIGE_BATTLE_END_STATUS_ERR); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let historyData = await GVGVestigeRankModel.findByRole(rec.vestigeId, roleId); + let historyRank = historyData?.rank||0; + // 交换排名 + let { isChange, atkData, defData, oldAtkData, endTime } = await GVGVestigeRankModel.changeRank(isSuccess, rec.vestigeId, rec.attackInfo, rec.defenseInfo); + atkData = await updateMyVestigeRank(isChange, atkData, defData, historyRank, rec); + // 更新vestigeRec + if(isChange) { + rec = await GVGVestigeRecModel.battleEnd(battleCode, isSuccess, endTime, atkData?.rank, defData? defData.rank: oldAtkData?.rank); + } else { + rec = await GVGVestigeRecModel.battleEnd(battleCode, isSuccess, endTime); + } + // 更新锁 + await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank); + // 更新battleRecord + await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } }); + + // 取消突破排名奖励 + // let { rewards, leagueRewards } = calBreakGoods(rec.vestigeId, historyRank, atkData.rank); + // let breakGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewards, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_END); + + await saveScoreToRank(rec); + addVestigeBattleEndRec(rec); + if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushGvgFightIconShow(rec.defenseRoleId, battleCode); + + return resResult(STATUS.SUCCESS, { + vestigeId: rec.vestigeId, + battleCode: rec.battleCode, + leagueGoods: rec.leagueGoods, + rank: atkData.rank, + score: gameData.gvgVestige.get(rec.vestigeId)?.get(atkData.rank)?.score??0, + historyRank: atkData.historyRank, + ...getVestigeRecStatus(rec), + oppPlayers: await getOppPlayerByRanks(serverId, rec.groupKey, rec.vestigeId, atkData.oppRanks), + // breakGoods, + lineup: atkData.lineup, + lineupCe: atkData.lineup.reduce((pre, cur) => pre + cur.ce, 0), + }); + } + + // 获取战报信息 + async getRec(msg: { vestigeId: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let { vestigeId } = msg; + let list = await GVGVestigeRecModel.findRec(roleId, vestigeId); + let result: (GVGVestigeRecUpdate & {rplFileUrl: string})[] = []; + for(let rec of list) { + const { attackRoleId, battleCode, hasRpl, remoteUrl } = rec; + const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; + const obj = getVestigeRecStatus(rec); + if(obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl }); + } + return resResult(STATUS.SUCCESS, { + list: result, + rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) + }); + } + + // 征战中原简单小排行榜 + async getLeagueRank(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let groupKey = await getGroupKey(serverId); + let serverNames = await getAllServerName(); + + const { ranks: leagueRank, myRank: myLeagueRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, true, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }); + const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, true, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames); + + return resResult(STATUS.SUCCESS, { + leagueRank, myLeagueRank, memberRank, myMemberRank + }) + } + + // 联军详细排名 + async getLeagueDetailRank(msg: {}, session: BackendSession) { + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const roleId = session.get('roleId'); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let groupKey = await getGroupKey(serverId); + let serverNames = await getAllServerName(); + let { configId } = getGVGPeriodData(); + + const { ranks, myRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, false, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }, serverNames); + const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, false, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames); + + let yesterdayRank = await GVGVestigeLeagueRankModel.getYesterdayRank(myLeague.leagueCode); + let joinTime = await getMemberJoinLeagueTime(myLeague.leagueCode, roleId, myLeague); + let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId, joinTime); + let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); + let { canReceiveBox, boxPreview } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); + + return resResult(STATUS.SUCCESS, { + ranks, myRank, + memberRank, myMemberRank, + latestRank: yesterdayRank?.rank||0, + canReceiveBox, boxPreview + }) + } + + // 玩家排行 + async getPlayerRank(msg: { vestigeId: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + let { vestigeId } = msg; + let groupKey = await getGroupKey(serverId); + + let dicRankMap = gameData.gvgVestige.get(vestigeId); + let serverNames = await getAllServerName(); + let vestigeRanks = await GVGVestigeRankModel.findRankByVestige(groupKey, vestigeId); + let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER, { groupKey, vestigeId }); + let ranks: VestigeRank[] = [], myRank: VestigeRank; + for(let { roleId: targetRoleId, rank, lineup } of vestigeRanks) { + let param = await r.getParam(rank, targetRoleId, [rank]); + if(!param) { + let role = await RoleModel.findByRoleId(targetRoleId, ROLE_SELECT.RANK); + await r.generParamAndSet(REDIS_KEY.USER_INFO, { roleId: targetRoleId }, { role }); + param = await r.getParam(rank, targetRoleId, [rank]); + } + let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0); + let serverName = serverNames[param.serverId]; + let score = dicRankMap?.get(param.rank)?.score||0; + + let obj = new VestigeRank(); + obj.setByRankParam(param, serverName, lineupCe, score); + if(obj.roleId == roleId) myRank = obj; + ranks.push(obj); + } + if(!myRank) { + let obj = new VestigeRank(); + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK); + obj.setByRole(role, serverNames[serverId]); + myRank = obj; + } + return resResult(STATUS.SUCCESS, { + vestigeId, + ranks, myRank + }) + + } + + // 领取排行榜获得的每日奖励 + async receiveBox(msg: { }, session: BackendSession) { + const guildCode = session.get('guildCode'); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId } = getGVGPeriodData(); + let joinTime = await getMemberJoinLeagueTime(myLeague.leagueCode, roleId, myLeague); + let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId, joinTime); + let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); + if(canReceiveLeagueRanks.length <= 0 && canReceivePlayerRanks.length <= 0) return resResult(STATUS.GVG_RECEIVE_NO_RANK_REWARD); + + let { leagueReward, rewards } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); + let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); + await GVGVestigeLeagueRankModel.receiveRanks(canReceiveLeagueRanks.map(cur => cur._id), roleId); + await GVGVestigeSumRankModel.receiveRanks(canReceivePlayerRanks.map(cur => cur._id)); + + return resResult(STATUS.SUCCESS, { + leagueGoods, + canReceiveRanks: false + }) + } + + async debugCalRec(msg: { battleCode: string }, session: BackendSession) { + let rec = await GVGVestigeRecModel.findByBattleCode(msg.battleCode); + await saveScoreToRank(rec); + return resResult(STATUS.SUCCESS); + } + + async debugSaveScore(msg: {}, session: BackendSession) { + await saveVestigeRankSchedule(); + return resResult(STATUS.SUCCESS); + } + + async debugSetMyRank(msg: { vestigeId: number, rank: number }, session: BackendSession) { + const { vestigeId, rank } = msg; + + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + + let groupKey = await getGroupKey(serverId); + let { configId } = getGVGPeriodData(); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague) + let myRank = myData?.rank||0; + + let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank); + if(targetData) { + myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank }); + targetData = await GVGVestigeRankModel.updateByRoleId(vestigeId, targetData.roleId, { rank: myRank, oldRank: rank }); + } else { + myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank }); + } + await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: rank, oldRank: myRank, roleId, leagueCode: myLeague.leagueCode }); + if(targetData) { + await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: targetData.rank, oldRank: rank, roleId: targetData.roleId, leagueCode: targetData.leagueCode }); + } + + return resResult(STATUS.SUCCESS); + } + + async debugSetMyOpp(msg: { vestigeId: number, oppRanks: number[] }, session: BackendSession) { + const { vestigeId, oppRanks } = msg; + let roleId = session.get('roleId'); + await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { oppRanks }); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/gvgHandler.ts b/game-server/app/servers/guild/handler/gvgHandler.ts index fae15dfb9..ba566005a 100644 --- a/game-server/app/servers/guild/handler/gvgHandler.ts +++ b/game-server/app/servers/guild/handler/gvgHandler.ts @@ -1,647 +1,648 @@ -import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; -import { GVG_ITEM, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS, GVG_REC_TYPE, TASK_TYPE, GVG_TECH_TYPE, PUSH_ROUTE } from "../../../consts"; -import { GVGLeagueModel } from "../../../db/GVGLeague"; -import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare"; -import { GuardCityInfoPage, GVGMainData, LeagueContributeInfo, LeagueMemberContributeInfo, LeagueRankInInfoPage } from "../../../domain/gvgField/returnData"; -import { getRandEelm, resResult } from "../../../pubUtils/util"; -import { calLeagueCe, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType, getServerTypeByTime } from "../../../services/gvg/gvgService"; -import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, checkLeagueAuth, getMyAuth } from "../../../services/gvg/gvgTeamService"; -import { getAllServerName } from "../../../services/redisService"; -import { Contribute, GVGUserDataModel } from "../../../db/GVGUserData"; -import { GVGUserItemModel } from "../../../db/GVGUserItem"; -import { GVGUserTaskModel } from "../../../db/GVGUserTask"; -import { GVG } from "../../../pubUtils/dicParam"; -import { RoleModel } from "../../../db/Role"; -import { addGVGTechActive, calFighterContribute, calProducerContribute, checkPreTech, checkTechIsIng, checkTechProgress, getDailyLoginReward, getMyContribute, pushTechChange, pushTechRollback, sendUngotBoxReward } from "../../../services/gvg/gvgPrepareService"; -import { GVGUserDailyDataModel } from "../../../db/GVGUserDailyData"; -import { gameData } from "../../../pubUtils/data"; -import { lockLeagueData } from "../../../services/redLockService"; -import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService"; -import { RewardInter } from "../../../pubUtils/interface"; -import { getGVGCities, getGVGCitiesInfo } from "../../../services/gvg/gvgBattleService"; -import { GVGRecModel } from "../../../db/GVGRec"; -import { checkGVGTask } from "../../../services/task/taskService"; -import { getFightTimeByPeriod, getMyVestiges, getVestiges } from "../../../services/gvg/gvgFightService"; -import { getSeconds } from "../../../pubUtils/timeUtil"; -import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank"; -import { addTechActivateMessage, addTechUnlockMessage } from "../../../services/gvg/gvgRecService"; -import { GuildModel } from "../../../db/Guild"; -import { GVGCityModel } from "../../../db/GVGCity"; -import { GVGRoleDataModel } from "../../../db/GVGRoleData"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GVGHandler(app); -} - -export class GVGHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 测试 - async getData(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - - let { configId, period, countdownTime } = getGVGPeriodData(); - let serverType = await getGVGServerType(serverId); - if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE); - - let data = new GVGMainData(configId, period, countdownTime, serverType); - - let serverNames = await getAllServerName(); - let league = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!league) { - league = await autoCreateLeague(guildCode); - } - if(league) { - data.setLeague(league, serverNames); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, league.leagueCode); - data.setLeagueParpare(leaguePrepare); - - let userData = await GVGUserDataModel.findByRole(configId, league.leagueCode, roleId); - let roleData = await GVGRoleDataModel.findByRole(configId, roleId); - let items = await GVGUserItemModel.findByRole(configId, league.leagueCode, roleId); - let tasks = await GVGUserTaskModel.findByRole(configId, league.leagueCode, roleId); - data.setPlayerInfo(userData, roleData, getMyAuth(league, roleId), await checkCanPrepare(roleId), checkCanChooseJob(userData?.job, leaguePrepare), items, tasks); - - let dailyReward = await getDailyLoginReward(roleId, roleName, sid, league.leagueCode, userData?.job); - if(dailyReward) data.setFistLogin(dailyReward.reward); - - data.setLeagueCe(await calLeagueCe(league)); - - let cities = await getGVGCities(league); - data.setCities(cities); - } - - return resResult(STATUS.SUCCESS, data) - } - - async getMap(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - - // if(!await checkCanPrepare(roleId)) return resResult(STATUS.GVG_CANNOT_PREPARE); // TODO 临时去拦截 - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId, period, countdownTime } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - - let groupKey = await getGroupKey(serverId); - let cities = await getGVGCitiesInfo(configId, groupKey, myLeague); - let vestiges = await getMyVestiges(serverId, roleId); - - await sendUngotBoxReward(configId, myLeague.leagueCode, roleId, sid); - - return resResult(STATUS.SUCCESS, { - configId, period, countdownTime, startFightTime, endFightTime, - targetCities: leaguePrepare?.targetCities||[], - notice: leaguePrepare?.notice||'', - cities, - vestiges - }); - } - - // 获取动态 - async getRec(msg: {}, session: BackendSession) { - const guildCode = session.get('guildCode'); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const recs = await GVGRecModel.findByLeague(myLeague.leagueCode, GVG_REC_TYPE.PREPARE); - return resResult(STATUS.SUCCESS, { recs }); - } - - // 选择职能 - async chooseJob(msg: { job: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const { job } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 是否已经选过 - let myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - if(myUserData && myUserData.job) return resResult(STATUS.GVG_HAS_CHOOSE_JOB); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!leaguePrepare) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - // 是否超过人数 - let limit = Math.ceil(leaguePrepare.maxMemberCnt * GVG.GVG_ROLE_TOTAL_RATIO); - let cnt = job == LEAGUE_JOB.FIGHTER? leaguePrepare.fighterCnt: leaguePrepare.producerCnt; - if(cnt >= Math.ceil(limit * GVG.GVG_ROLE_RATIO / 2)) { - return resResult(STATUS.SUCCESS, { - isSuccess: false, - leagueCode: myLeague.leagueCode, - job: myUserData.job, - producerCnt: leaguePrepare.producerCnt, - fighterCnt: leaguePrepare.fighterCnt, - }); - } - - // 更新userData - myUserData = await GVGUserDataModel.chooseJob(configId, myLeague.leagueCode, roleId, job); - // 更新prepare - leaguePrepare = await GVGLeaguePrepareModel.chooseJob(configId, myLeague.leagueCode, job); - let dailyReward = await getDailyLoginReward(roleId, roleName, sid, myLeague.leagueCode, myUserData?.job); - - return resResult(STATUS.SUCCESS, { - isSuccess: true, - leagueCode: myLeague.leagueCode, - job: myUserData.job, - producerCnt: leaguePrepare.producerCnt, - fighterCnt: leaguePrepare.fighterCnt, - leagueGoods: dailyReward? dailyReward.reward: [] - }); - } - - // 查看贡献 - async getContribute(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const members = myLeague.members||[]; - const roleIds = members.map(member => member.roleId); - const roles = await RoleModel.findByRoleIds(roleIds); - const serverNames = await getAllServerName(); - - const myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - const { contribute = new Contribute(), box = [] } = myUserData||{}; - const userDatas = await GVGUserDataModel.findByRoles(configId, myLeague.leagueCode, roleIds); - - const result: LeagueContributeInfo[] = []; - for(let curJob of [LEAGUE_JOB.PRODUCER, LEAGUE_JOB.FIGHTER]) { - const memberResult: LeagueMemberContributeInfo[] = []; - for(let member of members) { - let role = roles.find(role => role.roleId == member.roleId); - if(!role) continue; - let userData = userDatas.find(userData => userData.roleId == member.roleId); - let obj = new LeagueMemberContributeInfo(role, serverNames); - obj.setAuth(member.auth); - obj.setByUserData(userData); - if(curJob == LEAGUE_JOB.PRODUCER && calProducerContribute(obj) > 0) memberResult.push(obj); - if(curJob == LEAGUE_JOB.FIGHTER && obj.score > 0) memberResult.push(obj); - } - - memberResult.sort((a, b) => { - return curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(b) - calProducerContribute(a): calFighterContribute(b) - calFighterContribute(a); - }); - for(let i = 0; i < memberResult.length; i++) { - memberResult[i].setRank(i + 1); - } - let sumContribute = curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); - let boxReceived = box.filter(boxId => { - let dicBox = gameData.gvgContributeBox.get(boxId); - return dicBox.job == curJob; - }); - let disObj = new LeagueContributeInfo(curJob, sumContribute, boxReceived); - disObj.setMembers(memberResult); - result.push(disObj) - } - - const userDailyData = await GVGUserDailyDataModel.findByRole(configId, myLeague.leagueCode, roleId); - const myRanks = await GVGVestigeRankModel.findAllByRole(roleId); - - return resResult(STATUS.SUCCESS, { - myContribute: getMyContribute(userDailyData, myRanks), - list: result - }); - } - - // 领取宝箱 - async receiveBox(msg: { boxId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - - const { boxId } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let dicBox = gameData.gvgContributeBox.get(boxId); - if(!dicBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); - let { contribute = new Contribute(), box = [] } = myUserData||{}; - - if(box.indexOf(boxId) != -1) return resResult(STATUS.GVG_BOX_HAS_RECEIVED) - let sumContribute = dicBox.job == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); - if(sumContribute < dicBox.boxPoint) return resResult(STATUS.GVG_BOX_POINT_NOT_ENOUGH); - - const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicBox.boxLeagueReward, dicBox.boxReward, ITEM_CHANGE_REASON.GVG_RECEIVE_BOX); - myUserData = await GVGUserDataModel.receiveBox(configId, myLeague.leagueCode, roleId, boxId); - - return resResult(STATUS.SUCCESS, { - sumContribute, - receivedBox: myUserData.box, - leagueGoods - }); - } - - // 领取升级奖励 - async receiveLvReward(msg: { lv: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - - const { lv } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let dicGVGLeagueLv = gameData.gvgLeagueLv.get(lv); - if(!dicGVGLeagueLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - - if(!leaguePrepare || leaguePrepare.lv < lv + 1) return resResult(STATUS.GVG_LV_NOT_ENOUGH); - - let myUserData = await GVGRoleDataModel.findByRole(configId, roleId); - let { receivedLv } = myUserData||{}; - if(lv != 1 && receivedLv + 1 != lv) return resResult(STATUS.GVG_LV_REWARD_NOT_REACH); - if(receivedLv >= lv) return resResult(STATUS.GVG_LV_REWARD_HAS_RECEIVED); - - const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [], dicGVGLeagueLv.reward, ITEM_CHANGE_REASON.GVG_RECEIVE_LV); - myUserData = await GVGRoleDataModel.receiveLv(configId, roleId, lv); - - return resResult(STATUS.SUCCESS, { - receivedLv: myUserData.receivedLv, - leagueGoods - }); - } - - // 领取任务奖励 - async receiveTask(msg: { taskId: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const guildCode: string = session.get('guildCode'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { taskId } = msg; - - let dicGVGTask = gameData.gvgTask.get(taskId); - if(!dicGVGTask) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let { configId } = getGVGConfig(); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 检查 - let rec = await GVGUserTaskModel.findByTaskId(configId, myLeague.leagueCode, roleId, taskId); - if(!rec || rec.count < dicGVGTask.condition) return resResult(STATUS.GVG_TASK_NOT_ENOUGH); - if(rec.status == 2) return resResult(STATUS.GVG_TASK_HAS_RECEIVED); - - rec = await GVGUserTaskModel.receiveTask(configId, myLeague.leagueCode, roleId, taskId); - let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicGVGTask.leagueReward, dicGVGTask.reward, ITEM_CHANGE_REASON.GVG_RECEIVE_TASK); - - return resResult(STATUS.SUCCESS, { - curTask: { - id: rec.id, - status: rec.status - }, - leagueGoods - }); - } - - // 千机阁数据 - async getTech(msg: {}, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - - return resResult(STATUS.SUCCESS, { - activeTech: leaguePrepare?.activeTech||[], - queue: leaguePrepare?.techQueue||[] - }); - } - - // 千机阁解锁 - async unlockTech(msg: { techId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const { techId } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - const dicTech = gameData.gvgTech.get(techId); - if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.UNLOCK_TECH); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 并发锁 - let res: any = await lockLeagueData(DATA_NAME.LEAGUE_TECH, myLeague.leagueCode);//加锁 - if (!!res.err) return resResult(STATUS.REDLOCK_ERR); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - - if(checkTechIsIng(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_HAS_UNLOCKED); - } - - if(!checkPreTech(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_PRE_POSITION_NOT_UNLOCK); - } - - leaguePrepare = await GVGLeaguePrepareModel.unlockTech(configId, myLeague.leagueCode, techId, dicTech.consume); - if(!leaguePrepare) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_QUEUECNT_MAX); - } - - res.releaseCallback(); - addTechUnlockMessage(roleId, roleName, myLeague, techId); - - // 推送千机阁解锁消息 - let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId); - await pushTechChange(myLeague.guildCodes, false, techId, curQueue.progress, curQueue.maxProgress); - - return resResult(STATUS.SUCCESS, { - queue: leaguePrepare?.techQueue||[] - }); - } - - // 千机阁解锁 - async rollbackTech(msg: { techId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const { techId } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.UNLOCK_TECH); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - let dicTech = gameData.gvgTech.get(techId); - if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); - // 并发锁 - let res: any = await lockLeagueData(DATA_NAME.LEAGUE_TECH, myLeague.leagueCode);//加锁 - if (!!res.err) return resResult(STATUS.REDLOCK_ERR); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - - let techIds: number[] = [], preTechId = techId; - // 如果有后置节点,那么后置节点也需要解锁 - for(let { id, progress } of (leaguePrepare?.techQueue||[]) ) { - if(id == techId) { - if(progress > 0) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_HAS_PROGRESS); - } - techIds.push(id) - } else { - let dicCurTech = gameData.gvgTech.get(id); - if(dicCurTech.prepositionId.find(arr => arr.indexOf(preTechId) != -1)) { - if(progress > 0) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_HAS_PROGRESS); - } - techIds.push(id); - preTechId = id; - } - } - } - - leaguePrepare = await GVGLeaguePrepareModel.rollbackTech(configId, myLeague.leagueCode, techIds); - if(!leaguePrepare) { - res.releaseCallback(); - return resResult(STATUS.GVG_TECH_QUEUECNT_MAX); - } - - res.releaseCallback(); - - // 推送千机阁解锁消息 - await pushTechRollback(myLeague.guildCodes, techIds); - - return resResult(STATUS.SUCCESS, { - queue: leaguePrepare?.techQueue||[] - }); - } - - // 千机阁激活 - async activate(msg: { techId: number, battleFeats: number }, session: BackendSession) { - const serverId = session.get('serverId'); - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - const { techId, battleFeats } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - const dicTech = gameData.gvgTech.get(techId); - if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ACTIVATE_TECH); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!checkTechIsIng(techId, [], leaguePrepare?.techQueue||[])) { - return resResult(STATUS.GVG_TECH_NOT_QUEUE); - } - if(!leaguePrepare || leaguePrepare.lv < dicTech.levelLimit) { - return resResult(STATUS.GVG_TECH_LV_NOT_ENOUGH); - } - - // 扣战功 - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.BATTLE_FEAT, count: battleFeats }], [], ITEM_CHANGE_REASON.GVG_ACTIVE_TECH); - if(!costResult) return resResult(STATUS.GVG_BATTLE_FEAT_NOT_ENOUGH); - - leaguePrepare = await GVGLeaguePrepareModel.addProgress(configId, myLeague.leagueCode, techId, battleFeats); - if(!leaguePrepare) { - return resResult(STATUS.GVG_TECH_NOT_QUEUE); - } - let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId); - if(curQueue.progress >= curQueue.maxProgress) { - leaguePrepare = await GVGLeaguePrepareModel.activate(configId, myLeague.leagueCode, techId); - // 发放连弩 - if(dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) { - let members = myLeague.members||[]; - let randMembers = getRandEelm(members, dicTech.param[0]); - for(let { roleId } of randMembers) { - await addGVGReward(roleId, '', myLeague.leagueCode, null, [{ id: GVG_ITEM.KNIFE, count: dicTech.param[1] }], [], ITEM_CHANGE_REASON.GVG_TECH_SEND_KNIFE); - } - } - addTechActivateMessage(roleId, roleName, myLeague, techId); - } - - // 添加 活跃 - let active = await addGVGTechActive(myLeague.leagueCode, roleId); - checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_TECH, { count: 1 }); - - // 推送千机阁激活消息 - await pushTechChange(myLeague.guildCodes, true, techId, curQueue.progress, curQueue.maxProgress); - - return resResult(STATUS.SUCCESS, { - active, - activeTech: leaguePrepare?.activeTech||[], - queue: leaguePrepare?.techQueue||[] - }); - } - - // 情报页面:联军排名 - async getLeagueRankInfo(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const { configId } = getGVGConfig(); - const groupKey = await getGroupKey(serverId); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const prepares = await GVGLeaguePrepareModel.getLvRank(configId, groupKey); - const leagues = await GVGLeagueModel.findByCodes(prepares.map(cur => cur.leagueCode)); - const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); - const cities = await GVGCityModel.findGuardCity(configId, groupKey); - - let ranks: LeagueRankInInfoPage[] = [], myRank: LeagueRankInInfoPage = undefined; - prepares.forEach((prepare, index) => { - let league = leagues.find(cur => cur.leagueCode == prepare.leagueCode); - if(!league) return; - let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); - let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); - let guardCities = cities.filter(cur => cur.guardLeague == league.leagueCode).map(cur => cur.cityId); - let data = new LeagueRankInInfoPage(index + 1, league, prepare, leagueCe, guardCities); - ranks.push(data); - }); - ranks.sort((a, b) => { - if(a.lv == b.lv) return b.leagueCe - a.leagueCe; - return b.lv - a.lv; - }); - ranks.forEach((rank, index) => { - rank.rank = index + 1; - if(myLeague.leagueCode == rank.leagueCode) myRank = rank; - }); - - if(!myRank) { - let myGuilds = await GuildModel.findByCodes(myLeague.guildCodes); - let leagueCe = myGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); - let guardCities = cities.filter(cur => cur.guardLeague == myLeague.leagueCode).map(cur => cur.cityId); - myRank = new LeagueRankInInfoPage(0, myLeague, null, leagueCe, guardCities); - } - - return resResult(STATUS.SUCCESS, { - ranks, myRank - }) - } - - // 情报页面:城池占领 - async getGuardCityInfo(msg: {}, session: BackendSession) { - - const serverId = session.get('serverId'); - - const { configId } = getGVGConfig(); - const groupKey = await getGroupKey(serverId); - - const cities = await GVGCityModel.findGuardCity(configId, groupKey); - const leagueCodes = cities.map(cur => cur.guardLeague); - const leagues = await GVGLeagueModel.findByCodes(leagueCodes); - const prepares = await GVGLeaguePrepareModel.findByLeagueCodes(configId, leagueCodes); - const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); - - const result: GuardCityInfoPage[] = []; - for(let { cityId, guardLeague: guardLeagueCode } of cities) { - let league = leagues.find(cur => cur.leagueCode == guardLeagueCode); - if(!league) continue; - let prepare = prepares.find(cur => cur.leagueCode == guardLeagueCode); - let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); - let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); - - let data = new GuardCityInfoPage(cityId); - data.setGuardLeague(league, prepare, leagueCe); - result.push(data); - } - - return resResult(STATUS.SUCCESS, { - cities: result - }) - } - - // 获取道具 - async debugAddLeagueItem(msg: { id: number, count: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const { id, count } = msg; - let dicGVGItem = gameData.gvgItem.get(id); - if(!dicGVGItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [{ id, count }], [], ITEM_CHANGE_REASON.DEBUG); - - return resResult(STATUS.SUCCESS, { leagueGoods }); - } - - async debugHandleCost(msg: { items: RewardInter[], leagueItems: RewardInter[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - const { items, leagueItems } = msg; - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const result = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.DEBUG); - return resResult(STATUS.SUCCESS, { result }); - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus"; +import { GVG_ITEM, DATA_NAME, GVG_ACTIVE_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, LEAGUE_MANAGE_TYPE, STATUS, GVG_REC_TYPE, TASK_TYPE, GVG_TECH_TYPE, PUSH_ROUTE } from "../../../consts"; +import { GVGLeagueModel } from "@db/GVGLeague"; +import { GVGLeaguePrepareModel } from "@db/GVGLeaguePrepare"; +import { GuardCityInfoPage, GVGMainData, LeagueContributeInfo, LeagueMemberContributeInfo, LeagueRankInInfoPage } from "@domain/gvgField/returnData"; +import { getRandEelm, resResult } from "@pubUtils/util"; +import { calLeagueCe, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType, getServerTypeByTime } from "../../../services/gvg/gvgService"; +import { autoCreateLeague, checkCanChooseJob, checkCanPrepare, checkLeagueAuth, getMyAuth } from "../../../services/gvg/gvgTeamService"; +import { getAllServerName } from "../../../services/redisService"; +import { Contribute, GVGUserDataModel } from "@db/GVGUserData"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { GVGUserTaskModel } from "@db/GVGUserTask"; +import { GVG } from "@pubUtils/dicParam"; +import { RoleModel } from "@db/Role"; +import { addGVGTechActive, calFighterContribute, calProducerContribute, checkPreTech, checkTechIsIng, checkTechProgress, getDailyLoginReward, getMyContribute, pushTechChange, pushTechRollback, sendUngotBoxReward } from "../../../services/gvg/gvgPrepareService"; +import { GVGUserDailyDataModel } from "@db/GVGUserDailyData"; +import { gameData } from "@pubUtils/data"; +import { lockLeagueData } from "../../../services/redLockService"; +import { addGVGReward, handleGVGCost } from "../../../services/gvg/gvgItemService"; +import { RewardInter } from "@pubUtils/interface"; +import { getGVGCities, getGVGCitiesInfo } from "../../../services/gvg/gvgBattleService"; +import { GVGRecModel } from "@db/GVGRec"; +import { checkGVGTask } from "../../../services/task/taskService"; +import { getFightTimeByPeriod, getMyVestiges, getVestiges } from "../../../services/gvg/gvgFightService"; +import { getSeconds } from "@pubUtils/timeUtil"; +import { GVGVestigeRankModel } from "@db/GVGVestigeRank"; +import { addTechActivateMessage, addTechUnlockMessage } from "../../../services/gvg/gvgRecService"; +import { GuildModel } from "@db/Guild"; +import { GVGCityModel } from "@db/GVGCity"; +import { GVGRoleDataModel } from "@db/GVGRoleData"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGHandler(app); +} + +export class GVGHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 测试 + async getData(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + let { configId, period, countdownTime } = getGVGPeriodData(); + let serverType = await getGVGServerType(serverId); + if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE); + + let data = new GVGMainData(configId, period, countdownTime, serverType); + + let serverNames = await getAllServerName(); + let league = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!league) { + league = await autoCreateLeague(guildCode); + } + if(league) { + data.setLeague(league, serverNames); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, league.leagueCode); + data.setLeagueParpare(leaguePrepare); + + let userData = await GVGUserDataModel.findByRole(configId, league.leagueCode, roleId); + let roleData = await GVGRoleDataModel.findByRole(configId, roleId); + let items = await GVGUserItemModel.findByRole(configId, league.leagueCode, roleId); + let tasks = await GVGUserTaskModel.findByRole(configId, league.leagueCode, roleId); + data.setPlayerInfo(userData, roleData, getMyAuth(league, roleId), await checkCanPrepare(roleId), checkCanChooseJob(userData?.job, leaguePrepare), items, tasks); + + let dailyReward = await getDailyLoginReward(roleId, roleName, sid, league.leagueCode, userData?.job); + if(dailyReward) data.setFistLogin(dailyReward.reward); + + data.setLeagueCe(await calLeagueCe(league)); + + let cities = await getGVGCities(league); + data.setCities(cities); + } + + return resResult(STATUS.SUCCESS, data) + } + + async getMap(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + // if(!await checkCanPrepare(roleId)) return resResult(STATUS.GVG_CANNOT_PREPARE); // TODO 临时去拦截 + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId, period, countdownTime } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + + let groupKey = await getGroupKey(serverId); + let cities = await getGVGCitiesInfo(configId, groupKey, myLeague); + let vestiges = await getMyVestiges(serverId, roleId); + + await sendUngotBoxReward(configId, myLeague.leagueCode, roleId, sid); + + return resResult(STATUS.SUCCESS, { + configId, period, countdownTime, startFightTime, endFightTime, + targetCities: leaguePrepare?.targetCities||[], + notice: leaguePrepare?.notice||'', + cities, + vestiges + }); + } + + // 获取动态 + async getRec(msg: {}, session: BackendSession) { + const guildCode = session.get('guildCode'); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const recs = await GVGRecModel.findByLeague(myLeague.leagueCode, GVG_REC_TYPE.PREPARE); + return resResult(STATUS.SUCCESS, { recs }); + } + + // 选择职能 + async chooseJob(msg: { job: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const { job } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 是否已经选过 + let myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + if(myUserData && myUserData.job) return resResult(STATUS.GVG_HAS_CHOOSE_JOB); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + if(!leaguePrepare) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + // 是否超过人数 + let limit = Math.ceil(leaguePrepare.maxMemberCnt * GVG.GVG_ROLE_TOTAL_RATIO); + let cnt = job == LEAGUE_JOB.FIGHTER? leaguePrepare.fighterCnt: leaguePrepare.producerCnt; + if(cnt >= Math.ceil(limit * GVG.GVG_ROLE_RATIO / 2)) { + return resResult(STATUS.SUCCESS, { + isSuccess: false, + leagueCode: myLeague.leagueCode, + job: myUserData.job, + producerCnt: leaguePrepare.producerCnt, + fighterCnt: leaguePrepare.fighterCnt, + }); + } + + // 更新userData + myUserData = await GVGUserDataModel.chooseJob(configId, myLeague.leagueCode, roleId, job); + // 更新prepare + leaguePrepare = await GVGLeaguePrepareModel.chooseJob(configId, myLeague.leagueCode, job); + let dailyReward = await getDailyLoginReward(roleId, roleName, sid, myLeague.leagueCode, myUserData?.job); + + return resResult(STATUS.SUCCESS, { + isSuccess: true, + leagueCode: myLeague.leagueCode, + job: myUserData.job, + producerCnt: leaguePrepare.producerCnt, + fighterCnt: leaguePrepare.fighterCnt, + leagueGoods: dailyReward? dailyReward.reward: [] + }); + } + + // 查看贡献 + async getContribute(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const members = myLeague.members||[]; + const roleIds = members.map(member => member.roleId); + const roles = await RoleModel.findByRoleIds(roleIds); + const serverNames = await getAllServerName(); + + const myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + const { contribute = new Contribute(), box = [] } = myUserData||{}; + const userDatas = await GVGUserDataModel.findByRoles(configId, myLeague.leagueCode, roleIds); + + const result: LeagueContributeInfo[] = []; + for(let curJob of [LEAGUE_JOB.PRODUCER, LEAGUE_JOB.FIGHTER]) { + const memberResult: LeagueMemberContributeInfo[] = []; + for(let member of members) { + let role = roles.find(role => role.roleId == member.roleId); + if(!role) continue; + let userData = userDatas.find(userData => userData.roleId == member.roleId); + let obj = new LeagueMemberContributeInfo(role, serverNames); + obj.setAuth(member.auth); + obj.setByUserData(userData); + if(curJob == LEAGUE_JOB.PRODUCER && calProducerContribute(obj) > 0) memberResult.push(obj); + if(curJob == LEAGUE_JOB.FIGHTER && obj.score > 0) memberResult.push(obj); + } + + memberResult.sort((a, b) => { + return curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(b) - calProducerContribute(a): calFighterContribute(b) - calFighterContribute(a); + }); + for(let i = 0; i < memberResult.length; i++) { + memberResult[i].setRank(i + 1); + } + let sumContribute = curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); + let boxReceived = box.filter(boxId => { + let dicBox = gameData.gvgContributeBox.get(boxId); + return dicBox.job == curJob; + }); + let disObj = new LeagueContributeInfo(curJob, sumContribute, boxReceived); + disObj.setMembers(memberResult); + result.push(disObj) + } + + const userDailyData = await GVGUserDailyDataModel.findByRole(configId, myLeague.leagueCode, roleId); + const myRanks = await GVGVestigeRankModel.findAllByRole(roleId); + + return resResult(STATUS.SUCCESS, { + myContribute: getMyContribute(userDailyData, myRanks), + list: result + }); + } + + // 领取宝箱 + async receiveBox(msg: { boxId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + + const { boxId } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let dicBox = gameData.gvgContributeBox.get(boxId); + if(!dicBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let myUserData = await GVGUserDataModel.findByRole(configId, myLeague.leagueCode, roleId); + let { contribute = new Contribute(), box = [] } = myUserData||{}; + + if(box.indexOf(boxId) != -1) return resResult(STATUS.GVG_BOX_HAS_RECEIVED) + let sumContribute = dicBox.job == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); + if(sumContribute < dicBox.boxPoint) return resResult(STATUS.GVG_BOX_POINT_NOT_ENOUGH); + + const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicBox.boxLeagueReward, dicBox.boxReward, ITEM_CHANGE_REASON.GVG_RECEIVE_BOX); + myUserData = await GVGUserDataModel.receiveBox(configId, myLeague.leagueCode, roleId, boxId); + + return resResult(STATUS.SUCCESS, { + sumContribute, + receivedBox: myUserData.box, + leagueGoods + }); + } + + // 领取升级奖励 + async receiveLvReward(msg: { lv: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + + const { lv } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let dicGVGLeagueLv = gameData.gvgLeagueLv.get(lv); + if(!dicGVGLeagueLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + + if(!leaguePrepare || leaguePrepare.lv < lv + 1) return resResult(STATUS.GVG_LV_NOT_ENOUGH); + + let myUserData = await GVGRoleDataModel.findByRole(configId, roleId); + let { receivedLv } = myUserData||{}; + if(lv != 1 && receivedLv + 1 != lv) return resResult(STATUS.GVG_LV_REWARD_NOT_REACH); + if(receivedLv >= lv) return resResult(STATUS.GVG_LV_REWARD_HAS_RECEIVED); + + const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [], dicGVGLeagueLv.reward, ITEM_CHANGE_REASON.GVG_RECEIVE_LV); + myUserData = await GVGRoleDataModel.receiveLv(configId, roleId, lv); + + return resResult(STATUS.SUCCESS, { + receivedLv: myUserData.receivedLv, + leagueGoods + }); + } + + // 领取任务奖励 + async receiveTask(msg: { taskId: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const guildCode: string = session.get('guildCode'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { taskId } = msg; + + let dicGVGTask = gameData.gvgTask.get(taskId); + if(!dicGVGTask) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let { configId } = getGVGConfig(); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 检查 + let rec = await GVGUserTaskModel.findByTaskId(configId, myLeague.leagueCode, roleId, taskId); + if(!rec || rec.count < dicGVGTask.condition) return resResult(STATUS.GVG_TASK_NOT_ENOUGH); + if(rec.status == 2) return resResult(STATUS.GVG_TASK_HAS_RECEIVED); + + rec = await GVGUserTaskModel.receiveTask(configId, myLeague.leagueCode, roleId, taskId); + let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicGVGTask.leagueReward, dicGVGTask.reward, ITEM_CHANGE_REASON.GVG_RECEIVE_TASK); + + return resResult(STATUS.SUCCESS, { + curTask: { + id: rec.id, + status: rec.status + }, + leagueGoods + }); + } + + // 千机阁数据 + async getTech(msg: {}, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + + return resResult(STATUS.SUCCESS, { + activeTech: leaguePrepare?.activeTech||[], + queue: leaguePrepare?.techQueue||[] + }); + } + + // 千机阁解锁 + async unlockTech(msg: { techId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const { techId } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + const dicTech = gameData.gvgTech.get(techId); + if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.UNLOCK_TECH); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 并发锁 + let res: any = await lockLeagueData(DATA_NAME.LEAGUE_TECH, myLeague.leagueCode);//加锁 + if (!!res.err) return resResult(STATUS.REDLOCK_ERR); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + + if(checkTechIsIng(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_HAS_UNLOCKED); + } + + if(!checkPreTech(techId, leaguePrepare?.activeTech||[], leaguePrepare?.techQueue||[])) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_PRE_POSITION_NOT_UNLOCK); + } + + leaguePrepare = await GVGLeaguePrepareModel.unlockTech(configId, myLeague.leagueCode, techId, dicTech.consume); + if(!leaguePrepare) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_QUEUECNT_MAX); + } + + res.releaseCallback(); + addTechUnlockMessage(roleId, roleName, myLeague, techId); + + // 推送千机阁解锁消息 + let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId); + await pushTechChange(myLeague.guildCodes, false, techId, curQueue.progress, curQueue.maxProgress); + + return resResult(STATUS.SUCCESS, { + queue: leaguePrepare?.techQueue||[] + }); + } + + // 千机阁解锁 + async rollbackTech(msg: { techId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const { techId } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.UNLOCK_TECH); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + let dicTech = gameData.gvgTech.get(techId); + if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // 并发锁 + let res: any = await lockLeagueData(DATA_NAME.LEAGUE_TECH, myLeague.leagueCode);//加锁 + if (!!res.err) return resResult(STATUS.REDLOCK_ERR); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + + let techIds: number[] = [], preTechId = techId; + // 如果有后置节点,那么后置节点也需要解锁 + for(let { id, progress } of (leaguePrepare?.techQueue||[]) ) { + if(id == techId) { + if(progress > 0) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_HAS_PROGRESS); + } + techIds.push(id) + } else { + let dicCurTech = gameData.gvgTech.get(id); + if(dicCurTech.prepositionId.find(arr => arr.indexOf(preTechId) != -1)) { + if(progress > 0) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_HAS_PROGRESS); + } + techIds.push(id); + preTechId = id; + } + } + } + + leaguePrepare = await GVGLeaguePrepareModel.rollbackTech(configId, myLeague.leagueCode, techIds); + if(!leaguePrepare) { + res.releaseCallback(); + return resResult(STATUS.GVG_TECH_QUEUECNT_MAX); + } + + res.releaseCallback(); + + // 推送千机阁解锁消息 + await pushTechRollback(myLeague.guildCodes, techIds); + + return resResult(STATUS.SUCCESS, { + queue: leaguePrepare?.techQueue||[] + }); + } + + // 千机阁激活 + async activate(msg: { techId: number, battleFeats: number }, session: BackendSession) { + const serverId = session.get('serverId'); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + const { techId, battleFeats } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + const dicTech = gameData.gvgTech.get(techId); + if(!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ACTIVATE_TECH); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + if(!checkTechIsIng(techId, [], leaguePrepare?.techQueue||[])) { + return resResult(STATUS.GVG_TECH_NOT_QUEUE); + } + if(!leaguePrepare || leaguePrepare.lv < dicTech.levelLimit) { + return resResult(STATUS.GVG_TECH_LV_NOT_ENOUGH); + } + + // 扣战功 + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.BATTLE_FEAT, count: battleFeats }], [], ITEM_CHANGE_REASON.GVG_ACTIVE_TECH); + if(!costResult) return resResult(STATUS.GVG_BATTLE_FEAT_NOT_ENOUGH); + + leaguePrepare = await GVGLeaguePrepareModel.addProgress(configId, myLeague.leagueCode, techId, battleFeats); + if(!leaguePrepare) { + return resResult(STATUS.GVG_TECH_NOT_QUEUE); + } + let curQueue = leaguePrepare.techQueue.find(cur => cur.id == techId); + if(curQueue.progress >= curQueue.maxProgress) { + leaguePrepare = await GVGLeaguePrepareModel.activate(configId, myLeague.leagueCode, techId); + // 发放连弩 + if(dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) { + let members = myLeague.members||[]; + let randMembers = getRandEelm(members, dicTech.param[0]); + for(let { roleId } of randMembers) { + await addGVGReward(roleId, '', myLeague.leagueCode, null, [{ id: GVG_ITEM.KNIFE, count: dicTech.param[1] }], [], ITEM_CHANGE_REASON.GVG_TECH_SEND_KNIFE); + } + } + addTechActivateMessage(roleId, roleName, myLeague, techId); + } + + // 添加 活跃 + let active = await addGVGTechActive(myLeague.leagueCode, roleId); + checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_TECH, { count: 1 }); + + // 推送千机阁激活消息 + await pushTechChange(myLeague.guildCodes, true, techId, curQueue.progress, curQueue.maxProgress); + + return resResult(STATUS.SUCCESS, { + active, + activeTech: leaguePrepare?.activeTech||[], + queue: leaguePrepare?.techQueue||[] + }); + } + + // 情报页面:联军排名 + async getLeagueRankInfo(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const prepares = await GVGLeaguePrepareModel.getLvRank(configId, groupKey); + const leagues = await GVGLeagueModel.findByCodes(prepares.map(cur => cur.leagueCode)); + const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); + const cities = await GVGCityModel.findGuardCity(configId, groupKey); + + let ranks: LeagueRankInInfoPage[] = [], myRank: LeagueRankInInfoPage = undefined; + prepares.forEach((prepare, index) => { + let league = leagues.find(cur => cur.leagueCode == prepare.leagueCode); + if(!league) return; + let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); + let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + let guardCities = cities.filter(cur => cur.guardLeague == league.leagueCode).map(cur => cur.cityId); + let data = new LeagueRankInInfoPage(index + 1, league, prepare, leagueCe, guardCities); + ranks.push(data); + }); + ranks.sort((a, b) => { + if(a.lv == b.lv) return b.leagueCe - a.leagueCe; + return b.lv - a.lv; + }); + ranks.forEach((rank, index) => { + rank.rank = index + 1; + if(myLeague.leagueCode == rank.leagueCode) myRank = rank; + }); + + if(!myRank) { + let myGuilds = await GuildModel.findByCodes(myLeague.guildCodes); + let leagueCe = myGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + let guardCities = cities.filter(cur => cur.guardLeague == myLeague.leagueCode).map(cur => cur.cityId); + myRank = new LeagueRankInInfoPage(0, myLeague, null, leagueCe, guardCities); + } + + return resResult(STATUS.SUCCESS, { + ranks, myRank + }) + } + + // 情报页面:城池占领 + async getGuardCityInfo(msg: {}, session: BackendSession) { + + const serverId = session.get('serverId'); + + const { configId } = getGVGConfig(); + const groupKey = await getGroupKey(serverId); + + const cities = await GVGCityModel.findGuardCity(configId, groupKey); + const leagueCodes = cities.map(cur => cur.guardLeague); + const leagues = await GVGLeagueModel.findByCodes(leagueCodes); + const prepares = await GVGLeaguePrepareModel.findByLeagueCodes(configId, leagueCodes); + const guilds = await GuildModel.findByCodesWithoutPopulate(leagues.reduce((pre, cur) => [...pre, ...cur.guildCodes], [])); + + const result: GuardCityInfoPage[] = []; + for(let { cityId, guardLeague: guardLeagueCode } of cities) { + let league = leagues.find(cur => cur.leagueCode == guardLeagueCode); + if(!league) continue; + let prepare = prepares.find(cur => cur.leagueCode == guardLeagueCode); + let leagueGuilds = guilds.filter(cur => cur.leagueCode == league.leagueCode); + let leagueCe = leagueGuilds.reduce((pre, cur) => pre + cur.guildCe, 0); + + let data = new GuardCityInfoPage(cityId); + data.setGuardLeague(league, prepare, leagueCe); + result.push(data); + } + + return resResult(STATUS.SUCCESS, { + cities: result + }) + } + + // 获取道具 + async debugAddLeagueItem(msg: { id: number, count: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const { id, count } = msg; + let dicGVGItem = gameData.gvgItem.get(id); + if(!dicGVGItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [{ id, count }], [], ITEM_CHANGE_REASON.DEBUG); + + return resResult(STATUS.SUCCESS, { leagueGoods }); + } + + async debugHandleCost(msg: { items: RewardInter[], leagueItems: RewardInter[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + const { items, leagueItems } = msg; + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const result = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.DEBUG); + return resResult(STATUS.SUCCESS, { result }); + } +} + diff --git a/game-server/app/servers/guild/handler/gvgManageHandler.ts b/game-server/app/servers/guild/handler/gvgManageHandler.ts index c91ca3436..8d7cdb5ff 100644 --- a/game-server/app/servers/guild/handler/gvgManageHandler.ts +++ b/game-server/app/servers/guild/handler/gvgManageHandler.ts @@ -1,690 +1,691 @@ -import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; -import { CHANNEL_PREFIX, GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, MAIL_TYPE, MSG_SOURCE, MSG_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from "../../../consts"; -import { resResult } from "../../../pubUtils/util"; -import { GuildModel, GuildType } from "../../../db/Guild"; -import { GVGLeagueModel, GVGLeagueType } from "../../../db/GVGLeague"; -import { GVGLeagueApplyModel } from "../../../db/GVGLeagueApply"; -import { calLeagueCe, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from "../../../services/gvg/gvgService"; -import { checkCanManage, checkGuildLeader, checkLeagueAuth, createLeague, getLeagueApplyData, getLeagueInviteData, getMyAuth, joinGuildToLeague, updateGVGBattleLeagueInfo } from "../../../services/gvg/gvgTeamService"; -import { LeagueGuildInfo, LeagueListInfo, LeagueMemberListInfo, LeagueSimpleInfo } from "../../../domain/gvgField/returnData"; -import { getAllServerName, getServerName, isRoleOnline, updateUserInfo } from "../../../services/redisService"; -import { GVG } from "../../../pubUtils/dicParam"; -import { RoleModel, RoleType } from "../../../db/Role"; -import { GVGUserDataModel } from "../../../db/GVGUserData"; -import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../../../services/pushService"; -import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare"; -import { createGroupMsg, pushGroupMsgToRoom } from "../../../services/chatService"; -import { sendMailByContent, sendMailToGuildByContent, sendMailToLeagueByContent } from "../../../services/mailService"; -import { getGVGCities } from "../../../services/gvg/gvgBattleService"; -import { addLeagueRenameRecord, changeNoticeMessage, guildQuitLeagueRecord } from "../../../services/gvg/gvgRecService"; -import { LeagueLeader } from "../../../domain/rank"; -import GVGCity from "../../../db/GVGCity"; -import { getGVGGroupIdOfServer, getGVGServersOfSameGroup } from "../../../services/serverService"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GVGManageHandler(app); -} - -export class GVGManageHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 创建新联军 - async createLeague(msg: { name: string, icon: number, notice: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const { name, icon, notice = '' } = msg; - - const checkNameResult = await GVGLeagueModel.checkName(name); - if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP); - - let { period } = getGVGPeriodData(); - if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); - - const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); - const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); - if(checkGuildResult.code != 0) return checkGuildResult; - - const league = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(league) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); - - const newLeague = await createLeague(guild, { name, icon, notice }); - await GVGLeagueApplyModel.deleteByGuild(guildCode); - - return resResult(STATUS.SUCCESS, { - leagueCode: newLeague.leagueCode, - hasLeague: true - } ); - } - - // 获取联军列表 - async getLeagues(msg: { page: number, name: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { page = 1, name } = msg; - - let serverType = await getGVGServerType(serverId); - if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE); - - const serverNames = await getAllServerName(); - let serverIds = await getGVGServersOfSameGroup(serverType, serverId); - const leagues = await GVGLeagueModel.findByCondition(serverType, serverIds, page, name); - const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode); - let result: LeagueListInfo[] = []; - for(let league of leagues) { - let data = new LeagueListInfo(league, serverNames); - let hasApply = !!applies.find(cur => cur.leagueCode == league.leagueCode); - data.setHasApply(hasApply); - data.setLeagueCe(await calLeagueCe(league)); - result.push(data); - } - return resResult(STATUS.SUCCESS, { - leagues: result - } ); - } - - // 未加入成员查看联军信息 - async getLeagueInfo(msg: { leagueCode: string }, session: BackendSession) { - const { leagueCode } = msg; - const guildCode = session.get('guildCode'); - - const serverNames = await getAllServerName(); - const league = await GVGLeagueModel.findByCode(leagueCode); - let result = new LeagueSimpleInfo(league, serverNames) - let hasApply = await GVGLeagueApplyModel.checkApply(leagueCode, guildCode, GVG_APPLY_TYPE.APPLY); - result.setHasApply(hasApply); - - let { configId } = getGVGConfig(); - // TODO 占领城池 - const cities = await getGVGCities(league); - result.setCities(cities); - result.setLeagueCe(await calLeagueCe(league)); - - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); - if(leaguePrepare) result.setLv(leaguePrepare.lv); - - return resResult(STATUS.SUCCESS, { - league: result - } ); - } - - // 申请加入联军 - async applyLeague(msg: { leagueCodes: string[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { leagueCodes } = msg; - - // 检查时间 - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); - const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); - if(checkGuildResult.code != 0) return checkGuildResult; - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); - - const serverNames = await getAllServerName(); - const leagues = await GVGLeagueModel.findByCodes(leagueCodes); - - let result: LeagueListInfo[] = []; - for(let league of leagues) { - if(league.guildCnt > GVG.GVG_LEAGUE_COMPOSE) continue; - - await GVGLeagueApplyModel.createApply(league, guild, GVG_APPLY_TYPE.APPLY); - let data = new LeagueListInfo(league, serverNames); - data.setHasApply(true); - data.setLeagueCe(await calLeagueCe(league)); - result.push(data); - let leader = league.leader; - await sendMessageToUserWithSuc(leader.roleId, PUSH_ROUTE.LEAGUE_APPLY, { guildCode }); - } - - // 返回 - return resResult(STATUS.SUCCESS, { leagues: result }); - } - - // 获取申请列表 - async getApplies(msg: {}, session: BackendSession) { - const guildCode = session.get('guildCode'); - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const serverNames = await getAllServerName(); - const applies = await GVGLeagueApplyModel.findApplyFromLeague(myLeague.leagueCode); - const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode); - - let result = applies.map(apply => getLeagueApplyData(apply, serverNames, invitations)); - - // 返回 - return resResult(STATUS.SUCCESS, { guilds: result }); - } - - // 处理申请 - async handleApply(msg: { guildCode: string, isReceive: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { guildCode: targetGuildCode, isReceive } = msg; - - // 检查时间 - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.HANDLE_APPLY); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - if(isReceive) { - let result = await joinGuildToLeague(myLeague, targetGuildCode); - if(result.code == 0) { - myLeague = result.data; - await GVGLeagueApplyModel.deleteByGuild(targetGuildCode); - } else { - await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode); - return result; - } - } else { // 不同意,删除申请 - await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode); - } - - // 返回 - return resResult(STATUS.SUCCESS, { - guildCnt: myLeague.guildCnt, - memberCnt: myLeague.memberCnt, - leagueCe: await calLeagueCe(myLeague), - }); - } - - // 获取可以邀请的军团 - async getInviteGuilds(msg: { page: number, name: string }, session: BackendSession) { - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { page, name } = msg; - - // 检查时间 - const serverType = await getGVGServerType(serverId); - const checkResult = await checkCanManage(serverId, serverType); - if(checkResult.code != 0) return checkResult; - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode); - const serverIds = await getGVGServersOfSameGroup(serverType, serverId); - const serverNames = await getAllServerName(); - const guilds = await GuildModel.findGuildsForGVG(page, name, serverIds); - let result = guilds.map(guild => { - let data = new LeagueGuildInfo(guild, serverNames); - let hasInvited = !!invitations.find(cur => cur.guildCode == guild.code); - data.setHasInvited(hasInvited); - return data - }); - - // 返回 - return resResult(STATUS.SUCCESS, { - guilds: result - }); - } - - // 邀请加入联军 - async inviteGuild(msg: { guildCodes: string[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - const { guildCodes } = msg; - - // 必须跨服玩法 - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 权限 - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.INVITE); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - const guilds = await GuildModel.findByCodes(guildCodes); - const serverNames = await getAllServerName(); - - let result: LeagueGuildInfo[] = []; - for(let guild of guilds) { - await GVGLeagueApplyModel.createApply(myLeague, guild, GVG_APPLY_TYPE.INVITE); - let data = new LeagueGuildInfo(guild, serverNames); - data.setHasInvited(true); - result.push(data); - const leader = guild.leader; - await sendMessageToUserWithSuc(leader.roleId, PUSH_ROUTE.LEAGUE_INVITE, { leagueCode: myLeague.leagueCode }); - } - - // 返回 - return resResult(STATUS.SUCCESS, { guilds: result }); - } - - // 获取邀请我们军团的联军 - async getLeagueInvitations(msg: {}, session: BackendSession) { - const guildCode = session.get('guildCode'); - - const serverNames = await getAllServerName(); - const invitations = await GVGLeagueApplyModel.findInviteFromGuild(guildCode); - const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode); - - let result: LeagueListInfo[] = []; - for(let invitation of invitations) { - let obj = await getLeagueInviteData(invitation, serverNames, applies); - result.push(obj); - } - - // 返回 - return resResult(STATUS.SUCCESS, { leagues: result }); - } - - // 处理邀请 - async handleInvitation(msg: { leagueCode: string, isReceive: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { leagueCode: targetLeagueCode, isReceive } = msg; - - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - // 军团权限 - const checkGuildResult = await checkGuildLeader(guildCode, roleId); - if(checkGuildResult.code != 0) return checkGuildResult; - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); - - const league = await GVGLeagueModel.findByCode(targetLeagueCode); - if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let hasLeague = false; - if(isReceive) { - let result = await joinGuildToLeague(league, guildCode); - if(result.code == 0) { - hasLeague = true; - await GVGLeagueApplyModel.deleteByGuild(guildCode); - } else { - await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode); - return result; - } - } else { // 不同意,删除申请 - await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode); - } - - // 返回 - return resResult(STATUS.SUCCESS, { - leagueCode: targetLeagueCode, - isReceive, - hasLeague - }); - } - - // 获取组成的所有军团列表 - async getGuilds(msg: { leagueCode: string }, session: BackendSession) { - - const { leagueCode: targetLeagueCode } = msg; - const league = await GVGLeagueModel.findByCode(targetLeagueCode); - if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId } = getGVGConfig(); - const guilds = await GuildModel.findByCodes(league.guildCodes); - const members = league.members||[]; - let roleIds = members.map(member => member.roleId); - const serverNames = await getAllServerName(); - const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); - const result = guilds.map(guild => { - let obj = new LeagueGuildInfo(guild, serverNames); - let active = userdatas.reduce((pre, userdata) => { - let member = members.find(cur => cur.roleId == userdata.roleId); - if(member && member.guildCode == guild.code) { - return pre + (userdata.active||0); - } - return pre; - }, 0); - obj.setActive(active); - return obj; - }); - - // 返回 - return resResult(STATUS.SUCCESS, { - guilds: result - }); - } - - // 获取组成的所有玩家列表 - async getMembers(msg: { leagueCode: string }, session: BackendSession) { - - const { leagueCode: targetLeagueCode } = msg; - const league = await GVGLeagueModel.findByCode(targetLeagueCode); - if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let { configId } = getGVGConfig(); - - const members = league.members||[]; - let roleIds = members.map(member => member.roleId); - const roles = await RoleModel.findByRoleIds(roleIds); - const serverNames = await getAllServerName(); - const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); - const result: LeagueMemberListInfo[] = []; - for(let role of roles) { - let obj = new LeagueMemberListInfo(role, serverNames); - let userdata = userdatas.find(userdata => userdata.roleId == role.roleId); - if(userdata) obj.setByUserData(userdata); - let member = members.find(cur => cur.roleId == role.roleId); - if(member) obj.setAuth(member.auth); - let isOnline = await isRoleOnline(role.roleId); - obj.setOnline(!!isOnline); - result.push(obj); - } - - // 返回 - return resResult(STATUS.SUCCESS, { - members: result - }); - } - - // 踢掉某个军团 - async kick(msg: { guildCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { guildCode: targetGuildCode } = msg; - - // 不能踢自己的军团 - if(guildCode == targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD); - - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.KICK); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 更新对方军团信息 - const guild = await GuildModel.quitFromLeague(targetGuildCode, myLeague.leagueCode, '+members'); - if(!guild) return resResult(STATUS.GUILD_HAS_QUIT); - // 更新联军信息 - myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild); - - // 发送消息 - await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode }); - guildQuitLeagueRecord(myLeague.leagueCode, guild.name); - await sendMailToGuildByContent(MAIL_TYPE.LEAGUE_KICK, targetGuildCode, { params: [ myLeague.name ] }); - - // 返回 - return resResult(STATUS.SUCCESS, { - guildCnt: myLeague.guildCnt, - memberCnt: myLeague.memberCnt, - leagueCe: await calLeagueCe(myLeague), - }); - } - - // 军团退出 - async quit(msg: { guildCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { guildCode: targetGuildCode } = msg; - // 检查是否是自己军团 - if(guildCode != targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD); - - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - // 只能团长退出 - let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); - const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); - if(checkGuildResult.code != 0) return checkGuildResult; - - // 联军盟主不能退出 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.QUIT); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 更新对方军团信息 - guild = await GuildModel.quitFromLeague(guild.code, myLeague.leagueCode, '+members'); - // 更新联军信息 - myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild); - // 发送消息 - await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode }); - guildQuitLeagueRecord(myLeague.leagueCode, guild.name); - - // 返回 - return resResult(STATUS.SUCCESS, { - hasLeague: !!guild.leagueCode - }); - } - - // 解散联军 - async dismiss(msg: { leagueCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { leagueCode: targetLeagueCode } = msg; - const { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); - const groupKey = await getGroupKey(serverId); - - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR); - - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.DISSMISS); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 更新对方军团信息 - await GuildModel.dissmissLeague(targetLeagueCode); - // 更新联军信息 - await GVGLeagueModel.dismiss(myLeague.leagueCode); - await GVGLeagueApplyModel.deleteByLeague(myLeague.leagueCode); - // 发送消息 - for(let guildCode of myLeague.guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_DISSMISS, { leagueCode: myLeague.leagueCode }); - await sendMailToGuildByContent(MAIL_TYPE.LEAGUE_DISSMISS, guildCode, { params: [ myLeague.name ]}); - } - await GVGCity.leagueDismiss(configId, groupKey, targetLeagueCode); - - // 返回 - return resResult(STATUS.SUCCESS, { - hasLeague: false - }); - } - - // 获取可转让的人的列表 - async getCandidate(msg: { leagueCode: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { leagueCode: targetLeagueCode } = msg; - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR); - - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - let { configId } = getGVGConfig(); - - const members = myLeague.members||[]; - const candidates = members.filter(cur => cur.auth == LEAGUE_AUTH.SUB_LEADER); - let roleIds = candidates.map(member => member.roleId); - const roles = await RoleModel.findByRoleIds(roleIds); - const serverNames = await getAllServerName(); - const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); - const result = roles.map(role => { - let obj = new LeagueMemberListInfo(role, serverNames); - let userdata = userdatas.find(userdata => userdata.roleId == role.roleId); - if(userdata) obj.setByUserData(userdata); - let member = members.find(cur => cur.roleId == role.roleId); - if(member) obj.setAuth(member.auth); - return obj; - }); - - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, targetLeagueCode); - const { producerCnt, fighterCnt } = leaguePrepare||{ producerCnt: 0, fighterCnt: 0 } - - // 返回 - return resResult(STATUS.SUCCESS, { - producerCnt, fighterCnt, - members: result - }); - } - - // 获取可转让的人的列表 - async abdicate(msg: { roleId: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { roleId: targetRoleId } = msg; - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - const checkHisAuth = await checkLeagueAuth(targetRoleId, myLeague, LEAGUE_MANAGE_TYPE.BE_ABDICATED); - if(!checkHisAuth) return resResult(STATUS.GVG_HE_HAS_NO_AUTH); - - const targetRole = await RoleModel.findByRoleId(targetRoleId, '_id roleName serverId guildName roleId'); - let targetRoleServerName = await getServerName(targetRole.serverId); - - // 修改联军数据 members,leader - myLeague = await GVGLeagueModel.abdicate(myLeague.leagueCode, roleId, targetRoleId, targetRole._id); - // 推送 - await sendMessageToUserWithSuc(targetRoleId, PUSH_ROUTE.LEAGUE_ABDICATE, { leagueCode: myLeague.leagueCode }); - await sendMailByContent(MAIL_TYPE.LEAGUE_ABDICATE, roleId, { params: [ myLeague.name ] }); - await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'leader', value: new LeagueLeader(targetRole) }]); - - let myAuth = getMyAuth(myLeague, roleId); - // 返回 - return resResult(STATUS.SUCCESS, { - auth: myAuth, - leader: { - name: targetRole.roleName, - serverId: targetRole.serverId, - serverName: targetRoleServerName - }, - }); - } - - // 设置联军信息 - async setLeagueInfo(msg: { leagueCode: string, name: string, notice: string, icon: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const serverId = session.get('serverId'); - - const { leagueCode: targetLeagueCode, name, notice, icon } = msg; - - // 检查名字是否重 - if(name != undefined) { - const checkNameResult = await GVGLeagueModel.checkName(name); - if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP); - } - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.WRONG_PARMS); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_INFO); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 修改联军数据 - myLeague = await GVGLeagueModel.setInfo(targetLeagueCode, name, notice, icon); - if(name != undefined) { - await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'name', value: name }]); - addLeagueRenameRecord(myLeague.leagueCode, name); - } - if(icon != undefined) { - await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'icon', value: icon }]); - } - if(notice != undefined) { - await changeNoticeMessage(roleId, roleName, myLeague, notice); - } - await updateGVGBattleLeagueInfo(serverId, myLeague.leagueCode, { leagueName: name, icon }) - - // 返回 - return resResult(STATUS.SUCCESS, { - leagueCode: myLeague.leagueCode, - name: myLeague.name, - notice: myLeague.notice, - icon: myLeague.icon, - }); - } - - // 团长发送消息给军团内所有成员的邮箱 - async sendMail(msg: { content: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const { content } = msg; - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SEND_MAIL); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - let auth = getMyAuth(myLeague, roleId); - - //下发邮件 - await sendMailToLeagueByContent(MAIL_TYPE.LEAGUE_MAIL, myLeague.leagueCode, { sendName: `${auth == 1? "盟主": "副盟主"}:${roleName}`, params: [content] }, myLeague); - - return resResult(STATUS.SUCCESS, { isSuccess: true }); - } - - // 团长发送世界频道 - async recruit(msg: { content: string }, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - const { content } = msg; - // 检查时间 - const checkResult = await checkCanManage(serverId); - if(checkResult.code != 0) return checkResult; - - // 权限 - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.RERUIT); - if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); - - // 发送战区频道消息 - const groupId = await getGVGGroupIdOfServer(serverId); - let channelId = `${groupId}`; - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GVG, channelId, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_RECURIT, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, info: content }), '', ''); - if (!msgData) return resResult(STATUS.WRONG_PARMS); - await pushGroupMsgToRoom(msgData); - - return resResult(STATUS.SUCCESS, { isSuccess: true }); - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; +import { CHANNEL_PREFIX, GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, MAIL_TYPE, MSG_SOURCE, MSG_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from "../../../consts"; +import { resResult } from "@pubUtils/util"; +import { GuildModel, GuildType } from "@db/Guild"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import { GVGLeagueApplyModel } from "@db/GVGLeagueApply"; +import { calLeagueCe, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from "../../../services/gvg/gvgService"; +import { checkCanManage, checkGuildLeader, checkLeagueAuth, createLeague, getLeagueApplyData, getLeagueInviteData, getMyAuth, joinGuildToLeague, updateGVGBattleLeagueInfo } from "../../../services/gvg/gvgTeamService"; +import { LeagueGuildInfo, LeagueListInfo, LeagueMemberListInfo, LeagueSimpleInfo } from "@domain/gvgField/returnData"; +import { getAllServerName, getServerName, isRoleOnline, updateUserInfo } from "../../../services/redisService"; +import { GVG } from "@pubUtils/dicParam"; +import { RoleModel, RoleType } from "@db/Role"; +import { GVGUserDataModel } from "@db/GVGUserData"; +import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../../../services/pushService"; +import { GVGLeaguePrepareModel } from "@db/GVGLeaguePrepare"; +import { createGroupMsg, pushGroupMsgToRoom } from "../../../services/chatService"; +import { sendMailByContent, sendMailToGuildByContent, sendMailToLeagueByContent } from "../../../services/mailService"; +import { getGVGCities } from "../../../services/gvg/gvgBattleService"; +import { addLeagueRenameRecord, changeNoticeMessage, guildQuitLeagueRecord } from "../../../services/gvg/gvgRecService"; +import { LeagueLeader } from "@domain/rank"; +import GVGCity from "@db/GVGCity"; +import { getGVGGroupIdOfServer, getGVGServersOfSameGroup } from "../../../services/serverService"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGManageHandler(app); +} + +export class GVGManageHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 创建新联军 + async createLeague(msg: { name: string, icon: number, notice: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const { name, icon, notice = '' } = msg; + + const checkNameResult = await GVGLeagueModel.checkName(name); + if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP); + + let { period } = getGVGPeriodData(); + if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); + + const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); + const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); + if(checkGuildResult.code != 0) return checkGuildResult; + + const league = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(league) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); + + const newLeague = await createLeague(guild, { name, icon, notice }); + await GVGLeagueApplyModel.deleteByGuild(guildCode); + + return resResult(STATUS.SUCCESS, { + leagueCode: newLeague.leagueCode, + hasLeague: true + } ); + } + + // 获取联军列表 + async getLeagues(msg: { page: number, name: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { page = 1, name } = msg; + + let serverType = await getGVGServerType(serverId); + if(serverType == GVG_SERVER_TYPE.NO) return resResult(STATUS.GVG_NO_SERVER_TYPE); + + const serverNames = await getAllServerName(); + let serverIds = await getGVGServersOfSameGroup(serverType, serverId); + const leagues = await GVGLeagueModel.findByCondition(serverType, serverIds, page, name); + const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode); + let result: LeagueListInfo[] = []; + for(let league of leagues) { + let data = new LeagueListInfo(league, serverNames); + let hasApply = !!applies.find(cur => cur.leagueCode == league.leagueCode); + data.setHasApply(hasApply); + data.setLeagueCe(await calLeagueCe(league)); + result.push(data); + } + return resResult(STATUS.SUCCESS, { + leagues: result + } ); + } + + // 未加入成员查看联军信息 + async getLeagueInfo(msg: { leagueCode: string }, session: BackendSession) { + const { leagueCode } = msg; + const guildCode = session.get('guildCode'); + + const serverNames = await getAllServerName(); + const league = await GVGLeagueModel.findByCode(leagueCode); + let result = new LeagueSimpleInfo(league, serverNames) + let hasApply = await GVGLeagueApplyModel.checkApply(leagueCode, guildCode, GVG_APPLY_TYPE.APPLY); + result.setHasApply(hasApply); + + let { configId } = getGVGConfig(); + // TODO 占领城池 + const cities = await getGVGCities(league); + result.setCities(cities); + result.setLeagueCe(await calLeagueCe(league)); + + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + if(leaguePrepare) result.setLv(leaguePrepare.lv); + + return resResult(STATUS.SUCCESS, { + league: result + } ); + } + + // 申请加入联军 + async applyLeague(msg: { leagueCodes: string[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { leagueCodes } = msg; + + // 检查时间 + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + const guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); + const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); + if(checkGuildResult.code != 0) return checkGuildResult; + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); + + const serverNames = await getAllServerName(); + const leagues = await GVGLeagueModel.findByCodes(leagueCodes); + + let result: LeagueListInfo[] = []; + for(let league of leagues) { + if(league.guildCnt > GVG.GVG_LEAGUE_COMPOSE) continue; + + await GVGLeagueApplyModel.createApply(league, guild, GVG_APPLY_TYPE.APPLY); + let data = new LeagueListInfo(league, serverNames); + data.setHasApply(true); + data.setLeagueCe(await calLeagueCe(league)); + result.push(data); + let leader = league.leader; + await sendMessageToUserWithSuc(leader.roleId, PUSH_ROUTE.LEAGUE_APPLY, { guildCode }); + } + + // 返回 + return resResult(STATUS.SUCCESS, { leagues: result }); + } + + // 获取申请列表 + async getApplies(msg: {}, session: BackendSession) { + const guildCode = session.get('guildCode'); + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const serverNames = await getAllServerName(); + const applies = await GVGLeagueApplyModel.findApplyFromLeague(myLeague.leagueCode); + const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode); + + let result = applies.map(apply => getLeagueApplyData(apply, serverNames, invitations)); + + // 返回 + return resResult(STATUS.SUCCESS, { guilds: result }); + } + + // 处理申请 + async handleApply(msg: { guildCode: string, isReceive: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { guildCode: targetGuildCode, isReceive } = msg; + + // 检查时间 + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.HANDLE_APPLY); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + if(isReceive) { + let result = await joinGuildToLeague(myLeague, targetGuildCode); + if(result.code == 0) { + myLeague = result.data; + await GVGLeagueApplyModel.deleteByGuild(targetGuildCode); + } else { + await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode); + return result; + } + } else { // 不同意,删除申请 + await GVGLeagueApplyModel.deleteApply(targetGuildCode, myLeague.leagueCode); + } + + // 返回 + return resResult(STATUS.SUCCESS, { + guildCnt: myLeague.guildCnt, + memberCnt: myLeague.memberCnt, + leagueCe: await calLeagueCe(myLeague), + }); + } + + // 获取可以邀请的军团 + async getInviteGuilds(msg: { page: number, name: string }, session: BackendSession) { + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { page, name } = msg; + + // 检查时间 + const serverType = await getGVGServerType(serverId); + const checkResult = await checkCanManage(serverId, serverType); + if(checkResult.code != 0) return checkResult; + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const invitations = await GVGLeagueApplyModel.findInviteFromLeague(myLeague.leagueCode); + const serverIds = await getGVGServersOfSameGroup(serverType, serverId); + const serverNames = await getAllServerName(); + const guilds = await GuildModel.findGuildsForGVG(page, name, serverIds); + let result = guilds.map(guild => { + let data = new LeagueGuildInfo(guild, serverNames); + let hasInvited = !!invitations.find(cur => cur.guildCode == guild.code); + data.setHasInvited(hasInvited); + return data + }); + + // 返回 + return resResult(STATUS.SUCCESS, { + guilds: result + }); + } + + // 邀请加入联军 + async inviteGuild(msg: { guildCodes: string[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + const { guildCodes } = msg; + + // 必须跨服玩法 + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 权限 + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.INVITE); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + const guilds = await GuildModel.findByCodes(guildCodes); + const serverNames = await getAllServerName(); + + let result: LeagueGuildInfo[] = []; + for(let guild of guilds) { + await GVGLeagueApplyModel.createApply(myLeague, guild, GVG_APPLY_TYPE.INVITE); + let data = new LeagueGuildInfo(guild, serverNames); + data.setHasInvited(true); + result.push(data); + const leader = guild.leader; + await sendMessageToUserWithSuc(leader.roleId, PUSH_ROUTE.LEAGUE_INVITE, { leagueCode: myLeague.leagueCode }); + } + + // 返回 + return resResult(STATUS.SUCCESS, { guilds: result }); + } + + // 获取邀请我们军团的联军 + async getLeagueInvitations(msg: {}, session: BackendSession) { + const guildCode = session.get('guildCode'); + + const serverNames = await getAllServerName(); + const invitations = await GVGLeagueApplyModel.findInviteFromGuild(guildCode); + const applies = await GVGLeagueApplyModel.findApplyFromGuild(guildCode); + + let result: LeagueListInfo[] = []; + for(let invitation of invitations) { + let obj = await getLeagueInviteData(invitation, serverNames, applies); + result.push(obj); + } + + // 返回 + return resResult(STATUS.SUCCESS, { leagues: result }); + } + + // 处理邀请 + async handleInvitation(msg: { leagueCode: string, isReceive: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { leagueCode: targetLeagueCode, isReceive } = msg; + + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + // 军团权限 + const checkGuildResult = await checkGuildLeader(guildCode, roleId); + if(checkGuildResult.code != 0) return checkGuildResult; + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(myLeague) return resResult(STATUS.GVG_LEAGUE_HAS_EXIST); + + const league = await GVGLeagueModel.findByCode(targetLeagueCode); + if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let hasLeague = false; + if(isReceive) { + let result = await joinGuildToLeague(league, guildCode); + if(result.code == 0) { + hasLeague = true; + await GVGLeagueApplyModel.deleteByGuild(guildCode); + } else { + await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode); + return result; + } + } else { // 不同意,删除申请 + await GVGLeagueApplyModel.deleteInvite(guildCode, league.leagueCode); + } + + // 返回 + return resResult(STATUS.SUCCESS, { + leagueCode: targetLeagueCode, + isReceive, + hasLeague + }); + } + + // 获取组成的所有军团列表 + async getGuilds(msg: { leagueCode: string }, session: BackendSession) { + + const { leagueCode: targetLeagueCode } = msg; + const league = await GVGLeagueModel.findByCode(targetLeagueCode); + if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId } = getGVGConfig(); + const guilds = await GuildModel.findByCodes(league.guildCodes); + const members = league.members||[]; + let roleIds = members.map(member => member.roleId); + const serverNames = await getAllServerName(); + const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); + const result = guilds.map(guild => { + let obj = new LeagueGuildInfo(guild, serverNames); + let active = userdatas.reduce((pre, userdata) => { + let member = members.find(cur => cur.roleId == userdata.roleId); + if(member && member.guildCode == guild.code) { + return pre + (userdata.active||0); + } + return pre; + }, 0); + obj.setActive(active); + return obj; + }); + + // 返回 + return resResult(STATUS.SUCCESS, { + guilds: result + }); + } + + // 获取组成的所有玩家列表 + async getMembers(msg: { leagueCode: string }, session: BackendSession) { + + const { leagueCode: targetLeagueCode } = msg; + const league = await GVGLeagueModel.findByCode(targetLeagueCode); + if(!league) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let { configId } = getGVGConfig(); + + const members = league.members||[]; + let roleIds = members.map(member => member.roleId); + const roles = await RoleModel.findByRoleIds(roleIds); + const serverNames = await getAllServerName(); + const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); + const result: LeagueMemberListInfo[] = []; + for(let role of roles) { + let obj = new LeagueMemberListInfo(role, serverNames); + let userdata = userdatas.find(userdata => userdata.roleId == role.roleId); + if(userdata) obj.setByUserData(userdata); + let member = members.find(cur => cur.roleId == role.roleId); + if(member) obj.setAuth(member.auth); + let isOnline = await isRoleOnline(role.roleId); + obj.setOnline(!!isOnline); + result.push(obj); + } + + // 返回 + return resResult(STATUS.SUCCESS, { + members: result + }); + } + + // 踢掉某个军团 + async kick(msg: { guildCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { guildCode: targetGuildCode } = msg; + + // 不能踢自己的军团 + if(guildCode == targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD); + + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.KICK); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 更新对方军团信息 + const guild = await GuildModel.quitFromLeague(targetGuildCode, myLeague.leagueCode, '+members'); + if(!guild) return resResult(STATUS.GUILD_HAS_QUIT); + // 更新联军信息 + myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild); + + // 发送消息 + await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode }); + guildQuitLeagueRecord(myLeague.leagueCode, guild.name); + await sendMailToGuildByContent(MAIL_TYPE.LEAGUE_KICK, targetGuildCode, { params: [ myLeague.name ] }); + + // 返回 + return resResult(STATUS.SUCCESS, { + guildCnt: myLeague.guildCnt, + memberCnt: myLeague.memberCnt, + leagueCe: await calLeagueCe(myLeague), + }); + } + + // 军团退出 + async quit(msg: { guildCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { guildCode: targetGuildCode } = msg; + // 检查是否是自己军团 + if(guildCode != targetGuildCode) return resResult(STATUS.GVG_CANNOUT_KICK_SELF_GUILD); + + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + // 只能团长退出 + let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); + const checkGuildResult = await checkGuildLeader(guildCode, roleId, guild); + if(checkGuildResult.code != 0) return checkGuildResult; + + // 联军盟主不能退出 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.QUIT); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 更新对方军团信息 + guild = await GuildModel.quitFromLeague(guild.code, myLeague.leagueCode, '+members'); + // 更新联军信息 + myLeague = await GVGLeagueModel.quitGuild(myLeague.leagueCode, guild); + // 发送消息 + await sendMessageToGuildWithSuc(targetGuildCode, PUSH_ROUTE.LEAGUE_KICK, { leagueCode: myLeague.leagueCode }); + guildQuitLeagueRecord(myLeague.leagueCode, guild.name); + + // 返回 + return resResult(STATUS.SUCCESS, { + hasLeague: !!guild.leagueCode + }); + } + + // 解散联军 + async dismiss(msg: { leagueCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { leagueCode: targetLeagueCode } = msg; + const { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); + const groupKey = await getGroupKey(serverId); + + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR); + + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.DISSMISS); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 更新对方军团信息 + await GuildModel.dissmissLeague(targetLeagueCode); + // 更新联军信息 + await GVGLeagueModel.dismiss(myLeague.leagueCode); + await GVGLeagueApplyModel.deleteByLeague(myLeague.leagueCode); + // 发送消息 + for(let guildCode of myLeague.guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_DISSMISS, { leagueCode: myLeague.leagueCode }); + await sendMailToGuildByContent(MAIL_TYPE.LEAGUE_DISSMISS, guildCode, { params: [ myLeague.name ]}); + } + await GVGCity.leagueDismiss(configId, groupKey, targetLeagueCode); + + // 返回 + return resResult(STATUS.SUCCESS, { + hasLeague: false + }); + } + + // 获取可转让的人的列表 + async getCandidate(msg: { leagueCode: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { leagueCode: targetLeagueCode } = msg; + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.LEAGUE_CODE_ERR); + + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + let { configId } = getGVGConfig(); + + const members = myLeague.members||[]; + const candidates = members.filter(cur => cur.auth == LEAGUE_AUTH.SUB_LEADER); + let roleIds = candidates.map(member => member.roleId); + const roles = await RoleModel.findByRoleIds(roleIds); + const serverNames = await getAllServerName(); + const userdatas = await GVGUserDataModel.findByRoles(configId, targetLeagueCode, roleIds); + const result = roles.map(role => { + let obj = new LeagueMemberListInfo(role, serverNames); + let userdata = userdatas.find(userdata => userdata.roleId == role.roleId); + if(userdata) obj.setByUserData(userdata); + let member = members.find(cur => cur.roleId == role.roleId); + if(member) obj.setAuth(member.auth); + return obj; + }); + + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, targetLeagueCode); + const { producerCnt, fighterCnt } = leaguePrepare||{ producerCnt: 0, fighterCnt: 0 } + + // 返回 + return resResult(STATUS.SUCCESS, { + producerCnt, fighterCnt, + members: result + }); + } + + // 获取可转让的人的列表 + async abdicate(msg: { roleId: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { roleId: targetRoleId } = msg; + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.ABDICATE); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + const checkHisAuth = await checkLeagueAuth(targetRoleId, myLeague, LEAGUE_MANAGE_TYPE.BE_ABDICATED); + if(!checkHisAuth) return resResult(STATUS.GVG_HE_HAS_NO_AUTH); + + const targetRole = await RoleModel.findByRoleId(targetRoleId, '_id roleName serverId guildName roleId'); + let targetRoleServerName = await getServerName(targetRole.serverId); + + // 修改联军数据 members,leader + myLeague = await GVGLeagueModel.abdicate(myLeague.leagueCode, roleId, targetRoleId, targetRole._id); + // 推送 + await sendMessageToUserWithSuc(targetRoleId, PUSH_ROUTE.LEAGUE_ABDICATE, { leagueCode: myLeague.leagueCode }); + await sendMailByContent(MAIL_TYPE.LEAGUE_ABDICATE, roleId, { params: [ myLeague.name ] }); + await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'leader', value: new LeagueLeader(targetRole) }]); + + let myAuth = getMyAuth(myLeague, roleId); + // 返回 + return resResult(STATUS.SUCCESS, { + auth: myAuth, + leader: { + name: targetRole.roleName, + serverId: targetRole.serverId, + serverName: targetRoleServerName + }, + }); + } + + // 设置联军信息 + async setLeagueInfo(msg: { leagueCode: string, name: string, notice: string, icon: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + + const { leagueCode: targetLeagueCode, name, notice, icon } = msg; + + // 检查名字是否重 + if(name != undefined) { + const checkNameResult = await GVGLeagueModel.checkName(name); + if (checkNameResult) return resResult(STATUS.LEAGUE_NAME_DUP); + } + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + if(myLeague.leagueCode != targetLeagueCode) return resResult(STATUS.WRONG_PARMS); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SET_INFO); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 修改联军数据 + myLeague = await GVGLeagueModel.setInfo(targetLeagueCode, name, notice, icon); + if(name != undefined) { + await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'name', value: name }]); + addLeagueRenameRecord(myLeague.leagueCode, name); + } + if(icon != undefined) { + await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'icon', value: icon }]); + } + if(notice != undefined) { + await changeNoticeMessage(roleId, roleName, myLeague, notice); + } + await updateGVGBattleLeagueInfo(serverId, myLeague.leagueCode, { leagueName: name, icon }) + + // 返回 + return resResult(STATUS.SUCCESS, { + leagueCode: myLeague.leagueCode, + name: myLeague.name, + notice: myLeague.notice, + icon: myLeague.icon, + }); + } + + // 团长发送消息给军团内所有成员的邮箱 + async sendMail(msg: { content: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const { content } = msg; + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.SEND_MAIL); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + let auth = getMyAuth(myLeague, roleId); + + //下发邮件 + await sendMailToLeagueByContent(MAIL_TYPE.LEAGUE_MAIL, myLeague.leagueCode, { sendName: `${auth == 1? "盟主": "副盟主"}:${roleName}`, params: [content] }, myLeague); + + return resResult(STATUS.SUCCESS, { isSuccess: true }); + } + + // 团长发送世界频道 + async recruit(msg: { content: string }, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + const { content } = msg; + // 检查时间 + const checkResult = await checkCanManage(serverId); + if(checkResult.code != 0) return checkResult; + + // 权限 + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + const checkAuth = await checkLeagueAuth(roleId, myLeague, LEAGUE_MANAGE_TYPE.RERUIT); + if(!checkAuth) return resResult(STATUS.GVG_HAS_NO_AUTH); + + // 发送战区频道消息 + const groupId = await getGVGGroupIdOfServer(serverId); + let channelId = `${groupId}`; + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GVG, channelId, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_RECURIT, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, info: content }), '', ''); + if (!msgData) return resResult(STATUS.WRONG_PARMS); + await pushGroupMsgToRoom(msgData); + + return resResult(STATUS.SUCCESS, { isSuccess: true }); + } +} + diff --git a/game-server/app/servers/guild/handler/gvgProduceHandler.ts b/game-server/app/servers/guild/handler/gvgProduceHandler.ts index 62c7dc055..de2ffdae1 100644 --- a/game-server/app/servers/guild/handler/gvgProduceHandler.ts +++ b/game-server/app/servers/guild/handler/gvgProduceHandler.ts @@ -1,559 +1,560 @@ -import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; -import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_ITEM_TYPE, GVG_PERIOD, GVG_RESOURCE_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, STATUS, TASK_TYPE } from "../../../consts"; -import { GVGLeagueModel } from "../../../db/GVGLeague"; -import { GVGLeagueFarmModel, GVGLeagueFarmType } from "../../../db/GVGLeagueFarm"; -import { GVGLeagueFarmRecModel } from "../../../db/GVGLeagueFarmRec"; -import { GVGLeaguePrepareModel } from "../../../db/GVGLeaguePrepare"; -import { GVGUserItemModel } from "../../../db/GVGUserItem"; -import { RoleModel } from "../../../db/Role"; -import { LeagueFarmListInfo, LeagueFarmMember, LeagueField } from "../../../domain/gvgField/returnData"; -import { gameData, getGVGResourceBasesByType } from "../../../pubUtils/data"; -import { ItemInter, RewardInter } from "../../../pubUtils/interface"; -import { nowSeconds } from "../../../pubUtils/timeUtil"; -import { resResult } from "../../../pubUtils/util"; -import { getGVGCities } from "../../../services/gvg/gvgBattleService"; -import { addGVGReward, getProduceCoinCnt, handleGVGCost } from "../../../services/gvg/gvgItemService"; -import { addGVGActive, addResource, getCostSeedReward, getItemIdOfSeedType, getLeagueFarmShowResult, getLockFieldCnt, getmyContributeRank, rollbackUnPlantFields, lockField, calFarmOutput, sumOutputByResults, lockMineOrForestry, calMineOutput, calForestryOutput, checkItemCanUserInFarm, checkResourceAndLv } from "../../../services/gvg/gvgPrepareService"; -import { getGVGConfig, getGVGPeriodData } from "../../../services/gvg/gvgService"; -import { sendMailByContent } from "../../../services/mailService"; -import { getAllServerName, getRoleOnlineInfo } from "../../../services/redisService"; -import { checkGVGTask } from "../../../services/task/taskService"; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new GVGProduceHandler(app); -} - -export class GVGProduceHandler { - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - // 内政令兑换 - async exchangeItem(msg: { id: number, count: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - const { id, count } = msg; - - const dicGVGItem = gameData.gvgItem.get(id); - if(!dicGVGItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(dicGVGItem.type != GVG_ITEM_TYPE.SEED && dicGVGItem.type != GVG_ITEM_TYPE.SCOOP && dicGVGItem.type != GVG_ITEM_TYPE.AXE) { - return resResult(STATUS.GVG_ITEMS_NOT_PRODUCE); - } - - const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const leagueItems = dicGVGItem.leagueConsume.map(cur => ({ id: cur.id, count: cur.count * count })); - const items = dicGVGItem.consume.map(cur => ({ id: cur.id, count: cur.count * count })); - - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.GVG_EXCHANGE_SEEDS); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [{ id, count }], [], ITEM_CHANGE_REASON.GVG_EXCHANGE_SEEDS); - - return resResult(STATUS.SUCCESS, { - leagueGoods - }); - } - - // 获取农场/矿山/林场状态 - async getProduceList(msg: { type: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - const { type } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - const leagueLv = leaguePrepare?.lv||0; - - const leagueFarms = await GVGLeagueFarmModel.findByType(configId, myLeague.leagueCode, type); - - const dicFarms = getGVGResourceBasesByType(type); - const result: LeagueFarmListInfo[] = []; - for(let { id, lv, type } of dicFarms) { - if(lv > leagueLv) continue; - const leagueFarm = leagueFarms.filter(cur => cur.farmId == id && cur.unlockTime >= nowSeconds()); // 已种植单位 - const canHarvestFarms = leagueFarms.filter(cur => type == GVG_RESOURCE_TYPE.FOOD && cur.farmId == id && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds()); - let obj = new LeagueFarmListInfo(id, leagueFarm.length, canHarvestFarms.length > 0); - result.push(obj); - } - - return resResult(STATUS.SUCCESS, { - type, - list: result - }); - } - - // 不能进的农场,获取其他人的状态 - async getOtherFarms(msg: { farmId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const { farmId } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const fields = await GVGLeagueFarmModel.findPlantedByFarmId(configId, myLeague.leagueCode, farmId); - const roleIds: string[] = [], fieldByRoleId = new Map(); - for(let field of fields) { - if(roleIds.indexOf(field.lockRoleId) == -1) { - roleIds.push(field.lockRoleId); - fieldByRoleId.set(field.lockRoleId, []); - } - fieldByRoleId.get(field.lockRoleId).push(field); - } - - const serverNames = await getAllServerName(); - const roles = await RoleModel.findByRoleIds(roleIds); - const result: LeagueFarmMember[] = []; - for(let role of roles) { - let obj = new LeagueFarmMember(role, serverNames); - let myFields = fieldByRoleId.get(role.roleId)||[] - obj.setByFields(myFields); - result.push(obj); - } - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - members: result - }); - } - - // 小游戏界面 - async getMyFarm(msg: { farmId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - - const { farmId } = msg; - - let { period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let dicResource = gameData.gvgResource.get(farmId); - if(dicResource.type == GVG_RESOURCE_TYPE.FOOD) { - await lockField(myLeague.leagueCode, roleId, roleName, farmId); - } - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), - myRank, - }); - } - - // 种田 - async plant(msg: { farmId: number, seeds: { fieldId: number, seedType: number, index: number }[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - - const { farmId, seeds } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const fields = await GVGLeagueFarmModel.findByFieldIds(configId, myLeague.leagueCode, farmId, seeds.map(({fieldId}) => fieldId)); - for(let field of fields) { - if(!field) return resResult(STATUS.GVG_FIELD_NOT_FOUND); - if(field.lockRoleId != roleId && field.unlockTime > nowSeconds()) return resResult(STATUS.GVG_FIELD_HAS_LOCKED); - if(field.lockRoleId == roleId && field.harvestTime > 0) return resResult(STATUS.GVG_FIELD_HAS_PLANT); - } - - const cities = await getGVGCities(myLeague); - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.FOOD)) return resResult(STATUS.GVG_LV_RESOURCE); - - const cost: RewardInter[] = [], updateFields: { fieldId: number, seedType: number, index: number, time: number, output: number, outputStr: string }[] = []; - for(let { fieldId, seedType, index } of seeds) { - let itemId = getItemIdOfSeedType(seedType); - let dicItem = gameData.gvgItem.get(itemId); - let field = fields.find(cur => cur.fieldId == fieldId); - if(!field) continue; - let output = calFarmOutput(seedType, field.addType, farmId, cities, leaguePrepare?.activeTech||[]); - updateFields.push({ fieldId, seedType, index, time: dicItem.ripeTime, ...output }); - // 算消耗的种子 - let costObj = cost.find(({ id }) => id == itemId); - costObj? costObj.count++: cost.push({ id: itemId, count: 1 }); - } - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, cost, [], ITEM_CHANGE_REASON.PLANT) - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - const plantResult = await GVGLeagueFarmModel.plant(configId, myLeague.leagueCode, farmId, updateFields, roleId); - await rollbackUnPlantFields(cost, plantResult, session, myLeague.leagueCode); // 可能会有田已经被其他人占领的情况,将种子还回去 - await GVGLeagueFarmRecModel.insertRecs(GVG_RESOURCE_TYPE.FOOD, plantResult); - checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId) - }); - } - - // 收获 - async harvest(msg: { farmId: number, fieldIds: number[] }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - const guildCode = session.get('guildCode'); - - const { farmId, fieldIds } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const myResultFields = await GVGLeagueFarmModel.harvest(configId, myLeague.leagueCode, farmId, fieldIds, roleId); // 解锁 - if(myResultFields.length <= 0) return resResult(STATUS.GVG_CANNOT_HARVEST); - // 计算产量 - const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults(myResultFields); - // 资源 - let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.FOOD, foodSum, sid)||{}; - // 相关物品 - let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewardSum, rewardSum, ITEM_CHANGE_REASON.HARVEST) - // 活跃 - const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum); - // 收获后再次预锁定一批田 - // await lockField(myLeague.leagueCode, roleId, roleName, farmId); - await GVGLeagueFarmRecModel.updateRecs(myResultFields, roleId); - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - myRank, - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), - leagueGoods, - active, - ...resourceResult - }); - } - - // 关闭页面 - async plantEnd(msg: { farmId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - const { farmId } = msg; - let { configId } = getGVGConfig(); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - await GVGLeagueFarmModel.releaseLock(configId, myLeague.leagueCode, farmId, roleId); - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), - }); - } - - // 帮收 - async helpHarvest(msg: { farmId: number, roleId: string }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - - const { farmId, roleId: targetRoleId } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let dicFarm = gameData.gvgResource.get(farmId); - if(!dicFarm) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const resultField = await GVGLeagueFarmModel.helpHarvest(configId, myLeague.leagueCode, farmId, targetRoleId); // 解锁 - if(!resultField || resultField.length == 0) return resResult(STATUS.GVG_CANNOT_HARVEST); - - let targetOnlineInfo = await getRoleOnlineInfo(targetRoleId); - - // 计算产量 - const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults(resultField); - // 资源 - let resourceResult = await addResource(myLeague, targetRoleId, resultField[0].lockRoleName, GVG_RESOURCE_TYPE.FOOD, foodSum)||{}; - await sendMailByContent(MAIL_TYPE.HELP_HARVEST, targetRoleId, { sendName: roleName, goods: rewardSum }); - // 相关物品 - await addGVGReward(targetRoleId, roleName, myLeague.leagueCode, targetOnlineInfo.sid, leagueRewardSum, [], ITEM_CHANGE_REASON.HARVEST) - // 活跃 - await addGVGActive(myLeague.leagueCode, targetRoleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum); - - const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, myLeague.leagueCode, farmId); - const leagueFarm = leagueFarms.filter(cur => cur.farmId == dicFarm.id && cur.unlockTime >= nowSeconds()); // 已种植单位 - const canHarvestFarms = leagueFarms.filter(cur => dicFarm.type == GVG_RESOURCE_TYPE.FOOD && cur.farmId == dicFarm.id && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds()); - let obj = new LeagueFarmListInfo(dicFarm.id, leagueFarm.length, canHarvestFarms.length > 0); - - return resResult(STATUS.SUCCESS, { - ...obj, - ...resourceResult - }); - } - - // 进入矿山 - async mineStart(msg: { farmId: number, itemId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - const { farmId, itemId } = msg; - if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE); - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.MINERAL)) return resResult(STATUS.GVG_LV_RESOURCE); - - const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1); - if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId); - if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED); - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - myRank, - fieldId: lockResult.fieldId, - unlockTime: lockResult.unlockTime - }); - } - - // 结算矿场 - async mineEnd(msg: { farmId: number, fieldId: number, result: [{ type: number, count: number }] }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - const { farmId, fieldId, result } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 检查数据是否上传争取 - let dicMine = gameData.gvgResource.get(farmId); - if(!dicMine) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let mineralSum = 0; - for(let { type, count } of result) { - let max = dicMine.mineralValue.find(cur => cur.type == type)?.count||0; - if(count > max) return resResult(STATUS.GVG_MINERAL_COUNT_OVER); - mineralSum += count; - } - - const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId); - if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_MINE_HAS_OVER); - if(!!field.harvestTime) return resResult(STATUS.GVG_MINE_HAS_HARVEST); - let dicGVGItem = gameData.gvgItem.get(field.itemId); - if(mineralSum > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER); - - // 扣铲子 - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - // 计算资源 - const cities = await getGVGCities(myLeague); - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - const { output, outputStr } = calMineOutput(farmId, result, cities, leaguePrepare?.activeTech||[]); - // 挖完 - await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr); - // 计算产量 - let { reward, leagueReward, leagueConsume } = dicGVGItem; - let produceCoin = getProduceCoinCnt(leagueConsume); - // 资源 - let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.MINERAL, output, sid)||{}; - // 相关物品 - let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST) - // 活跃 - const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin); - checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - myRank, - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - ...resourceResult, - leagueGoods, - active - }); - } - - // 不能进的矿山,获取其他人的状态 - async getOtherMines(msg: { farmId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - const { farmId } = msg; - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const fields = await GVGLeagueFarmModel.findLockedByFarmId(configId, myLeague.leagueCode, farmId); - const roleIds: string[] = [], fieldByRoleId = new Map(); - for(let field of fields) { - if(roleIds.indexOf(field.lockRoleId) == -1) { - roleIds.push(field.lockRoleId); - fieldByRoleId.set(field.lockRoleId, []); - } - fieldByRoleId.get(field.lockRoleId).push(field); - } - - const serverNames = await getAllServerName(); - const roles = await RoleModel.findByRoleIds(roleIds); - const result: LeagueFarmMember[] = []; - for(let role of roles) { - let obj = new LeagueFarmMember(role, serverNames); - let myFields = fieldByRoleId.get(role.roleId)||[] - obj.setByMines(myFields); - result.push(obj); - } - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - members: result - }); - } - - // 进入林场 - async forestryStart(msg: { farmId: number, itemId: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const guildCode = session.get('guildCode'); - - const { farmId, itemId } = msg; - if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE); - - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.WOOD)) return resResult(STATUS.GVG_LV_RESOURCE); - - const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1); - if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId); - if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED); - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - myRank, - fieldId: lockResult.fieldId, - unlockTime: lockResult.unlockTime - }); - } - - // 林场结算 - async forestryEnd(msg: { farmId: number, fieldId: number, result: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - const serverId = session.get('serverId'); - - const { farmId, fieldId, result } = msg; - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - // 检查数据是否上传争取 - let dicForestry = gameData.gvgResource.get(farmId); - if(!dicForestry) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId); - if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_FORESTRY_HAS_OVER); - if(!!field.harvestTime) return resResult(STATUS.GVG_FORESTRY_HAS_HARVEST); - let dicGVGItem = gameData.gvgItem.get(field.itemId); - if(result > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER); - - // 扣斧头 - const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END); - if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); - - // 计算资源 - const cities = await getGVGCities(myLeague); - const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); - const { output, outputStr } = calForestryOutput(farmId, result, cities, leaguePrepare?.activeTech||[]); - // 挖完 - await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr); - // 计算产量 - let { reward, leagueReward, leagueConsume } = dicGVGItem; - let produceCoin = getProduceCoinCnt(leagueConsume); - // 资源 - let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.WOOD, output, sid)||{}; - // 相关物品 - let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST) - // 活跃 - const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin); - checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); - const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); - - return resResult(STATUS.SUCCESS, { - myRank, - ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), - ...resourceResult, - leagueGoods, - active - }); - } - - // 获取资源 - async debugAddResource(msg: { type: number, count: number }, session: BackendSession) { - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - const { type, count } = msg; - - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - let resourceResult = await addResource(myLeague, roleId, roleName, type, count, sid); - if(!resourceResult) return resResult(STATUS.WRONG_PARMS); - - return resResult(STATUS.SUCCESS, resourceResult); - } - - // 设置农田的收获时间 - async debugAdjustHarvest(msg: { time: number }, session: BackendSession) { - const guildCode = session.get('guildCode'); - const { time } = msg; - - let { configId } = getGVGPeriodData(); - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); - - await GVGLeagueFarmModel.setMyHarvestTime(configId, myLeague.leagueCode, time); - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; +import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_ITEM_TYPE, GVG_PERIOD, GVG_RESOURCE_TYPE, ITEM_CHANGE_REASON, MAIL_TYPE, STATUS, TASK_TYPE } from "../../../consts"; +import { GVGLeagueModel } from "@db/GVGLeague"; +import { GVGLeagueFarmModel, GVGLeagueFarmType } from "@db/GVGLeagueFarm"; +import { GVGLeagueFarmRecModel } from "@db/GVGLeagueFarmRec"; +import { GVGLeaguePrepareModel } from "@db/GVGLeaguePrepare"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { RoleModel } from "@db/Role"; +import { LeagueFarmListInfo, LeagueFarmMember, LeagueField } from "@domain/gvgField/returnData"; +import { gameData, getGVGResourceBasesByType } from "@pubUtils/data"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { resResult } from "@pubUtils/util"; +import { getGVGCities } from "../../../services/gvg/gvgBattleService"; +import { addGVGReward, getProduceCoinCnt, handleGVGCost } from "../../../services/gvg/gvgItemService"; +import { addGVGActive, addResource, getCostSeedReward, getItemIdOfSeedType, getLeagueFarmShowResult, getLockFieldCnt, getmyContributeRank, rollbackUnPlantFields, lockField, calFarmOutput, sumOutputByResults, lockMineOrForestry, calMineOutput, calForestryOutput, checkItemCanUserInFarm, checkResourceAndLv } from "../../../services/gvg/gvgPrepareService"; +import { getGVGConfig, getGVGPeriodData } from "../../../services/gvg/gvgService"; +import { sendMailByContent } from "../../../services/mailService"; +import { getAllServerName, getRoleOnlineInfo } from "../../../services/redisService"; +import { checkGVGTask } from "../../../services/task/taskService"; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new GVGProduceHandler(app); +} + +export class GVGProduceHandler { + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + // 内政令兑换 + async exchangeItem(msg: { id: number, count: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + const { id, count } = msg; + + const dicGVGItem = gameData.gvgItem.get(id); + if(!dicGVGItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(dicGVGItem.type != GVG_ITEM_TYPE.SEED && dicGVGItem.type != GVG_ITEM_TYPE.SCOOP && dicGVGItem.type != GVG_ITEM_TYPE.AXE) { + return resResult(STATUS.GVG_ITEMS_NOT_PRODUCE); + } + + const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const leagueItems = dicGVGItem.leagueConsume.map(cur => ({ id: cur.id, count: cur.count * count })); + const items = dicGVGItem.consume.map(cur => ({ id: cur.id, count: cur.count * count })); + + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, leagueItems, items, ITEM_CHANGE_REASON.GVG_EXCHANGE_SEEDS); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, [{ id, count }], [], ITEM_CHANGE_REASON.GVG_EXCHANGE_SEEDS); + + return resResult(STATUS.SUCCESS, { + leagueGoods + }); + } + + // 获取农场/矿山/林场状态 + async getProduceList(msg: { type: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + const { type } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + const leagueLv = leaguePrepare?.lv||0; + + const leagueFarms = await GVGLeagueFarmModel.findByType(configId, myLeague.leagueCode, type); + + const dicFarms = getGVGResourceBasesByType(type); + const result: LeagueFarmListInfo[] = []; + for(let { id, lv, type } of dicFarms) { + if(lv > leagueLv) continue; + const leagueFarm = leagueFarms.filter(cur => cur.farmId == id && cur.unlockTime >= nowSeconds()); // 已种植单位 + const canHarvestFarms = leagueFarms.filter(cur => type == GVG_RESOURCE_TYPE.FOOD && cur.farmId == id && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds()); + let obj = new LeagueFarmListInfo(id, leagueFarm.length, canHarvestFarms.length > 0); + result.push(obj); + } + + return resResult(STATUS.SUCCESS, { + type, + list: result + }); + } + + // 不能进的农场,获取其他人的状态 + async getOtherFarms(msg: { farmId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const { farmId } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const fields = await GVGLeagueFarmModel.findPlantedByFarmId(configId, myLeague.leagueCode, farmId); + const roleIds: string[] = [], fieldByRoleId = new Map(); + for(let field of fields) { + if(roleIds.indexOf(field.lockRoleId) == -1) { + roleIds.push(field.lockRoleId); + fieldByRoleId.set(field.lockRoleId, []); + } + fieldByRoleId.get(field.lockRoleId).push(field); + } + + const serverNames = await getAllServerName(); + const roles = await RoleModel.findByRoleIds(roleIds); + const result: LeagueFarmMember[] = []; + for(let role of roles) { + let obj = new LeagueFarmMember(role, serverNames); + let myFields = fieldByRoleId.get(role.roleId)||[] + obj.setByFields(myFields); + result.push(obj); + } + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + members: result + }); + } + + // 小游戏界面 + async getMyFarm(msg: { farmId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + + const { farmId } = msg; + + let { period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let dicResource = gameData.gvgResource.get(farmId); + if(dicResource.type == GVG_RESOURCE_TYPE.FOOD) { + await lockField(myLeague.leagueCode, roleId, roleName, farmId); + } + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), + myRank, + }); + } + + // 种田 + async plant(msg: { farmId: number, seeds: { fieldId: number, seedType: number, index: number }[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + const { farmId, seeds } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const fields = await GVGLeagueFarmModel.findByFieldIds(configId, myLeague.leagueCode, farmId, seeds.map(({fieldId}) => fieldId)); + for(let field of fields) { + if(!field) return resResult(STATUS.GVG_FIELD_NOT_FOUND); + if(field.lockRoleId != roleId && field.unlockTime > nowSeconds()) return resResult(STATUS.GVG_FIELD_HAS_LOCKED); + if(field.lockRoleId == roleId && field.harvestTime > 0) return resResult(STATUS.GVG_FIELD_HAS_PLANT); + } + + const cities = await getGVGCities(myLeague); + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.FOOD)) return resResult(STATUS.GVG_LV_RESOURCE); + + const cost: RewardInter[] = [], updateFields: { fieldId: number, seedType: number, index: number, time: number, output: number, outputStr: string }[] = []; + for(let { fieldId, seedType, index } of seeds) { + let itemId = getItemIdOfSeedType(seedType); + let dicItem = gameData.gvgItem.get(itemId); + let field = fields.find(cur => cur.fieldId == fieldId); + if(!field) continue; + let output = calFarmOutput(seedType, field.addType, farmId, cities, leaguePrepare?.activeTech||[]); + updateFields.push({ fieldId, seedType, index, time: dicItem.ripeTime, ...output }); + // 算消耗的种子 + let costObj = cost.find(({ id }) => id == itemId); + costObj? costObj.count++: cost.push({ id: itemId, count: 1 }); + } + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, cost, [], ITEM_CHANGE_REASON.PLANT) + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + const plantResult = await GVGLeagueFarmModel.plant(configId, myLeague.leagueCode, farmId, updateFields, roleId); + await rollbackUnPlantFields(cost, plantResult, session, myLeague.leagueCode); // 可能会有田已经被其他人占领的情况,将种子还回去 + await GVGLeagueFarmRecModel.insertRecs(GVG_RESOURCE_TYPE.FOOD, plantResult); + checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId) + }); + } + + // 收获 + async harvest(msg: { farmId: number, fieldIds: number[] }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const guildCode = session.get('guildCode'); + + const { farmId, fieldIds } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const myResultFields = await GVGLeagueFarmModel.harvest(configId, myLeague.leagueCode, farmId, fieldIds, roleId); // 解锁 + if(myResultFields.length <= 0) return resResult(STATUS.GVG_CANNOT_HARVEST); + // 计算产量 + const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults(myResultFields); + // 资源 + let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.FOOD, foodSum, sid)||{}; + // 相关物品 + let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewardSum, rewardSum, ITEM_CHANGE_REASON.HARVEST) + // 活跃 + const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum); + // 收获后再次预锁定一批田 + // await lockField(myLeague.leagueCode, roleId, roleName, farmId); + await GVGLeagueFarmRecModel.updateRecs(myResultFields, roleId); + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + myRank, + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), + leagueGoods, + active, + ...resourceResult + }); + } + + // 关闭页面 + async plantEnd(msg: { farmId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + const { farmId } = msg; + let { configId } = getGVGConfig(); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + await GVGLeagueFarmModel.releaseLock(configId, myLeague.leagueCode, farmId, roleId); + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId), + }); + } + + // 帮收 + async helpHarvest(msg: { farmId: number, roleId: string }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + + const { farmId, roleId: targetRoleId } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let dicFarm = gameData.gvgResource.get(farmId); + if(!dicFarm) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const resultField = await GVGLeagueFarmModel.helpHarvest(configId, myLeague.leagueCode, farmId, targetRoleId); // 解锁 + if(!resultField || resultField.length == 0) return resResult(STATUS.GVG_CANNOT_HARVEST); + + let targetOnlineInfo = await getRoleOnlineInfo(targetRoleId); + + // 计算产量 + const { foodSum, rewardSum, leagueRewardSum, activeSum } = await sumOutputByResults(resultField); + // 资源 + let resourceResult = await addResource(myLeague, targetRoleId, resultField[0].lockRoleName, GVG_RESOURCE_TYPE.FOOD, foodSum)||{}; + await sendMailByContent(MAIL_TYPE.HELP_HARVEST, targetRoleId, { sendName: roleName, goods: rewardSum }); + // 相关物品 + await addGVGReward(targetRoleId, roleName, myLeague.leagueCode, targetOnlineInfo.sid, leagueRewardSum, [], ITEM_CHANGE_REASON.HARVEST) + // 活跃 + await addGVGActive(myLeague.leagueCode, targetRoleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, activeSum); + + const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, myLeague.leagueCode, farmId); + const leagueFarm = leagueFarms.filter(cur => cur.farmId == dicFarm.id && cur.unlockTime >= nowSeconds()); // 已种植单位 + const canHarvestFarms = leagueFarms.filter(cur => dicFarm.type == GVG_RESOURCE_TYPE.FOOD && cur.farmId == dicFarm.id && cur.harvestTime > 0 && cur.harvestTime <= nowSeconds()); + let obj = new LeagueFarmListInfo(dicFarm.id, leagueFarm.length, canHarvestFarms.length > 0); + + return resResult(STATUS.SUCCESS, { + ...obj, + ...resourceResult + }); + } + + // 进入矿山 + async mineStart(msg: { farmId: number, itemId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + const { farmId, itemId } = msg; + if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE); + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.MINERAL)) return resResult(STATUS.GVG_LV_RESOURCE); + + const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1); + if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId); + if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED); + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + myRank, + fieldId: lockResult.fieldId, + unlockTime: lockResult.unlockTime + }); + } + + // 结算矿场 + async mineEnd(msg: { farmId: number, fieldId: number, result: [{ type: number, count: number }] }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + const { farmId, fieldId, result } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 检查数据是否上传争取 + let dicMine = gameData.gvgResource.get(farmId); + if(!dicMine) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let mineralSum = 0; + for(let { type, count } of result) { + let max = dicMine.mineralValue.find(cur => cur.type == type)?.count||0; + if(count > max) return resResult(STATUS.GVG_MINERAL_COUNT_OVER); + mineralSum += count; + } + + const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId); + if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_MINE_HAS_OVER); + if(!!field.harvestTime) return resResult(STATUS.GVG_MINE_HAS_HARVEST); + let dicGVGItem = gameData.gvgItem.get(field.itemId); + if(mineralSum > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER); + + // 扣铲子 + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + // 计算资源 + const cities = await getGVGCities(myLeague); + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + const { output, outputStr } = calMineOutput(farmId, result, cities, leaguePrepare?.activeTech||[]); + // 挖完 + await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr); + // 计算产量 + let { reward, leagueReward, leagueConsume } = dicGVGItem; + let produceCoin = getProduceCoinCnt(leagueConsume); + // 资源 + let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.MINERAL, output, sid)||{}; + // 相关物品 + let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST) + // 活跃 + const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin); + checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + myRank, + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + ...resourceResult, + leagueGoods, + active + }); + } + + // 不能进的矿山,获取其他人的状态 + async getOtherMines(msg: { farmId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + const { farmId } = msg; + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const fields = await GVGLeagueFarmModel.findLockedByFarmId(configId, myLeague.leagueCode, farmId); + const roleIds: string[] = [], fieldByRoleId = new Map(); + for(let field of fields) { + if(roleIds.indexOf(field.lockRoleId) == -1) { + roleIds.push(field.lockRoleId); + fieldByRoleId.set(field.lockRoleId, []); + } + fieldByRoleId.get(field.lockRoleId).push(field); + } + + const serverNames = await getAllServerName(); + const roles = await RoleModel.findByRoleIds(roleIds); + const result: LeagueFarmMember[] = []; + for(let role of roles) { + let obj = new LeagueFarmMember(role, serverNames); + let myFields = fieldByRoleId.get(role.roleId)||[] + obj.setByMines(myFields); + result.push(obj); + } + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + members: result + }); + } + + // 进入林场 + async forestryStart(msg: { farmId: number, itemId: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const guildCode = session.get('guildCode'); + + const { farmId, itemId } = msg; + if(!checkItemCanUserInFarm(farmId, itemId)) return resResult(STATUS.GVG_ITEM_CANNOT_USE); + + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + if(!checkResourceAndLv(leaguePrepare, GVG_RESOURCE_TYPE.WOOD)) return resResult(STATUS.GVG_LV_RESOURCE); + + const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, itemId, 1); + if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + const lockResult = await lockMineOrForestry(myLeague.leagueCode, roleId, farmId, itemId); + if(!lockResult) return resResult(STATUS.GVG_MINE_HAS_LOCKED); + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + myRank, + fieldId: lockResult.fieldId, + unlockTime: lockResult.unlockTime + }); + } + + // 林场结算 + async forestryEnd(msg: { farmId: number, fieldId: number, result: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + const serverId = session.get('serverId'); + + const { farmId, fieldId, result } = msg; + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD); + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + // 检查数据是否上传争取 + let dicForestry = gameData.gvgResource.get(farmId); + if(!dicForestry) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + const field = await GVGLeagueFarmModel.findByField(configId, myLeague.leagueCode, farmId, fieldId); + if(!field || field.lockRoleId != roleId) return resResult(STATUS.GVG_FORESTRY_HAS_OVER); + if(!!field.harvestTime) return resResult(STATUS.GVG_FORESTRY_HAS_HARVEST); + let dicGVGItem = gameData.gvgItem.get(field.itemId); + if(result > (dicGVGItem?.value||0)) return resResult(STATUS.GVG_MINE_SCOOP_OVER); + + // 扣斧头 + const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: field.itemId, count: 1 }], [], ITEM_CHANGE_REASON.MINE_END); + if(!costResult) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH); + + // 计算资源 + const cities = await getGVGCities(myLeague); + const leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, myLeague.leagueCode); + const { output, outputStr } = calForestryOutput(farmId, result, cities, leaguePrepare?.activeTech||[]); + // 挖完 + await GVGLeagueFarmModel.mineOrForestryEnd(configId, myLeague.leagueCode, farmId, roleId, fieldId, output, outputStr); + // 计算产量 + let { reward, leagueReward, leagueConsume } = dicGVGItem; + let produceCoin = getProduceCoinCnt(leagueConsume); + // 资源 + let resourceResult = await addResource(myLeague, roleId, roleName, GVG_RESOURCE_TYPE.WOOD, output, sid)||{}; + // 相关物品 + let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, reward, ITEM_CHANGE_REASON.HARVEST) + // 活跃 + const active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_PRODUCE_COIN, produceCoin); + checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_FARM, { count: 1 }); + const myRank = await getmyContributeRank(myLeague.leagueCode, myLeague.members, roleId); + + return resResult(STATUS.SUCCESS, { + myRank, + ...await getLeagueFarmShowResult(myLeague.leagueCode, roleId, farmId, false), + ...resourceResult, + leagueGoods, + active + }); + } + + // 获取资源 + async debugAddResource(msg: { type: number, count: number }, session: BackendSession) { + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + const { type, count } = msg; + + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + let resourceResult = await addResource(myLeague, roleId, roleName, type, count, sid); + if(!resourceResult) return resResult(STATUS.WRONG_PARMS); + + return resResult(STATUS.SUCCESS, resourceResult); + } + + // 设置农田的收获时间 + async debugAdjustHarvest(msg: { time: number }, session: BackendSession) { + const guildCode = session.get('guildCode'); + const { time } = msg; + + let { configId } = getGVGPeriodData(); + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST); + + await GVGLeagueFarmModel.setMyHarvestTime(configId, myLeague.leagueCode, time); + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/raceActivityHandler.ts b/game-server/app/servers/guild/handler/raceActivityHandler.ts index 8c05c7576..e4ddd6ac3 100644 --- a/game-server/app/servers/guild/handler/raceActivityHandler.ts +++ b/game-server/app/servers/guild/handler/raceActivityHandler.ts @@ -1,269 +1,270 @@ -import { Application, ChannelService, BackendSession, HandlerService, pinus, } from "pinus"; -import { GUILD_ACTIVITY_TYPE, STATUS, GUILD_ACTIVITY_STATUS, REDIS_KEY, TASK_TYPE, PUSH_ROUTE, DEBUG_MAGIC_WORD } from "../../../consts"; -import { genCode, resResult } from "../../../pubUtils/util"; -import { getGuildActivityStatus, getWoodenHorseList, getGAIndexInPinus, getJoinIndex, leaveRaceActivity } from "../../../services/guildActivity/guildActivityService"; -import { UserGuildModel } from "../../../db/UserGuild"; -import { GuildActivityRecordModel } from "../../../db/GuildActivityRec"; -import { UserGuildActivityRecModel } from "../../../db/UserGuildActivityRec"; -import { Rank } from "../../../services/rankService"; -import { checkTask } from "../../../services/task/taskService"; -import { ServerRecordModel } from "../../../db/ServerRecords"; -import { sendMessageToGuildWithSuc } from "../../../services/pushService"; -import { RaceActivityRankParam } from "../../../domain/battleField/guildActivity"; -import { GuildRankInfo } from "../../../domain/rank"; -import { dispatch } from "../../../pubUtils/dispatcher"; -import { redisClient } from "../../../services/redisService"; -import { getRaceActivityObj } from "../../../services/memoryCache/guildActivityData"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RaceActivityHandler(app); -} - -export class RaceActivityHandler { - - channelService: ChannelService; - constructor(private app: Application) { - this.channelService = app.get('channelService'); - } - - private aid = GUILD_ACTIVITY_TYPE.RACE_ACTIVITY; // 蛮夷入侵id - - // 进入粮草先行界面 - async getRaceActivity(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let obj = getRaceActivityObj(); - let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); - if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let events = obj.getEvents(guildCode, woodenHorse.distance); - let ranks: { myGuildRank?: RaceActivityRankParam, guildRank?: RaceActivityRankParam[] } = {}; - let hasJoin = await obj.updateMemberSid(guildCode, serverId, roleId, sid); - - if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { - ranks = await obj.getRanks(serverId, guildCode); - } else { - let index = getGAIndexInPinus(this.aid); - let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId, index }); - r.setGenerFieldsFun(function (param: GuildRankInfo) { - let { rank, code, name, num, num1, num2 } = param; - return { rank, code, name, num, time: Math.floor(num1/1000), durability: num2 }; - }); - let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); - ranks = { guildRank, myGuildRank } - } - - - return resResult(STATUS.SUCCESS, { - ...statusResult, - hasJoin: !!hasJoin, - code: hasJoin?.code||'', - woodenHorse, - ...ranks, - events - }); - } - - // 离开粮草先行界面 - async leavePage(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - await leaveRaceActivity(serverId, guildCode, roleId); - - return resResult(STATUS.SUCCESS); - } - - // 加入木马 - async join(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - const sid = session.get('sid'); - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - let joinIndex = getJoinIndex(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let obj = getRaceActivityObj(); - - let hasJoin = !!obj.getMember(guildCode, roleId); - if (hasJoin) { - return resResult(STATUS.RACE_HAS_JOIN); - } - - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, joinIndex, obj.getEvents(guildCode, 0)); - if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); - - let { code: sourceCode } = guildActivityRec; - let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); - - let myGuild = await UserGuildModel.getMyGuild(roleId, 'job'); - let woodenHorse = await obj.joinWoodenHorse(guildCode, roleId, roleName, serverId, sid, myGuild.job, myGuildActivityRec.code); - if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - await GuildActivityRecordModel.join(guildCode, this.aid, joinIndex, { roleId, roleName, job: myGuild.job, code: myGuildActivityRec.code }); - - let events = obj.getEvents(guildCode, woodenHorse.distance); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_RACE_JOIN, { timestamp: Date.now(), woodenHorse }); - - // 全服活跃统计 - await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); - - return resResult(STATUS.SUCCESS, { - code: myGuildActivityRec.code, - ...statusResult, - hasJoin, - woodenHorse, - events - }); - } - - // 打开竞赛页面 - async getRace(msg: {}, session: BackendSession) { - - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - // if (statusResult.status != GUILD_ACTIVITY_STATUS.START) { - // return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - // } - - let obj = getRaceActivityObj(); - let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); - if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); - - let events = obj.getEvents(guildCode, woodenHorse.distance); - let hasJoin = !!obj.getMember(guildCode, roleId); - let items = obj.getItem(roleId); - - let woodenHorseList = await getWoodenHorseList(guildCode, serverId); - - return resResult(STATUS.SUCCESS, { - ...statusResult, - hasJoin, - woodenHorseList, - events, - items - }); - } - - - // 使用道具 - async useItem(msg: { id: number, count: number, toGuild: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - let sid = session.get('sid'); - let joinIndex = getJoinIndex(); - - let { id, count, toGuild } = msg; - let obj = getRaceActivityObj(); - let woodenHorse = obj.getWoodenHorse(toGuild, serverId); - if (!woodenHorse) return resResult(STATUS.WRONG_PARMS); - - let event = await obj.useItem(serverId, roleId, sid, guildCode, toGuild, id, count); - if (!event) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - await GuildActivityRecordModel.pushEvent(guildCode, this.aid, joinIndex, event); - - return resResult(STATUS.SUCCESS, { - timestamp: Date.now(), - events: obj.getEvents(guildCode, 0) - }); - } - - // 结束挑战 - async battleEnd(msg: { code: string, isSuccess: boolean }, session: BackendSession) { - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - - let { code, isSuccess } = msg; - let joinIndex = getJoinIndex(); - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 更新userGuildActivityRecord - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, joinIndex); - let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true }); - if (!guildActivityRec || !myGuildActivityRec) return resResult(STATUS.WRONG_PARMS); - - let hasShow = !!myGuildActivityRec.hasShow; - if(!hasShow) { - await UserGuildActivityRecModel.updateInfo(code, { hasShow: true }); - } - - // 返回当前军团总军功 - let obj = getRaceActivityObj(); - let myGuildRank = 0; - let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); - if(woodenHorse) { - let { myGuildRank: rank, guildRank } = await obj.getRanks(serverId, guildCode); - // console.log('#', JSON.stringify(guildRank)) - myGuildRank = rank?.rank||0; - if(woodenHorse) { - // console.log('########', woodenHorse.time - woodenHorse.allStartTime, rank.sortTime); - woodenHorse = woodenHorse.getTreatTime(); - } - } else { - woodenHorse = guildActivityRec.woodenHorse; - myGuildRank = guildActivityRec.rank; - } - - - return resResult(STATUS.SUCCESS, { - timestamp: Date.now(), - hasShow, - woodenHorse, - myGuildRank - }) - } - - // 加入木马 - async debugAddHorse(msg: { magicWord: string, isMyGuild: number, memberCnt: number, itemInterval: number }, session: BackendSession) { - const { magicWord, isMyGuild, memberCnt, itemInterval } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - const serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - if(!isMyGuild) { - guildCode = genCode(8); - } - - let statusResult = getGuildActivityStatus(this.aid); - if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - if(statusResult.status != GUILD_ACTIVITY_STATUS.START) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); - - - let guild = pinus.app.getServersByType('guild'); - let sid = await dispatch(redisClient(), `${serverId}`, guild, 'guild'); - pinus.app.rpc.guild.guildActivityRemote.debugAddHorse.toServer(sid.id, serverId, guildCode, memberCnt, itemInterval) - - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, ChannelService, BackendSession, HandlerService, pinus, } from "pinus"; +import { GUILD_ACTIVITY_TYPE, STATUS, GUILD_ACTIVITY_STATUS, REDIS_KEY, TASK_TYPE, PUSH_ROUTE, DEBUG_MAGIC_WORD } from "../../../consts"; +import { genCode, resResult } from "@pubUtils/util"; +import { getGuildActivityStatus, getWoodenHorseList, getGAIndexInPinus, getJoinIndex, leaveRaceActivity } from "../../../services/guildActivity/guildActivityService"; +import { UserGuildModel } from "@db/UserGuild"; +import { GuildActivityRecordModel } from "@db/GuildActivityRec"; +import { UserGuildActivityRecModel } from "@db/UserGuildActivityRec"; +import { Rank } from "../../../services/rankService"; +import { checkTask } from "../../../services/task/taskService"; +import { ServerRecordModel } from "@db/ServerRecords"; +import { sendMessageToGuildWithSuc } from "../../../services/pushService"; +import { RaceActivityRankParam } from "@domain/battleField/guildActivity"; +import { GuildRankInfo } from "@domain/rank"; +import { dispatch } from "@pubUtils/dispatcher"; +import { redisClient } from "../../../services/redisService"; +import { getRaceActivityObj } from "../../../services/memoryCache/guildActivityData"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RaceActivityHandler(app); +} + +export class RaceActivityHandler { + + channelService: ChannelService; + constructor(private app: Application) { + this.channelService = app.get('channelService'); + } + + private aid = GUILD_ACTIVITY_TYPE.RACE_ACTIVITY; // 蛮夷入侵id + + // 进入粮草先行界面 + async getRaceActivity(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let obj = getRaceActivityObj(); + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + let ranks: { myGuildRank?: RaceActivityRankParam, guildRank?: RaceActivityRankParam[] } = {}; + let hasJoin = await obj.updateMemberSid(guildCode, serverId, roleId, sid); + + if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { + ranks = await obj.getRanks(serverId, guildCode); + } else { + let index = getGAIndexInPinus(this.aid); + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId, index }); + r.setGenerFieldsFun(function (param: GuildRankInfo) { + let { rank, code, name, num, num1, num2 } = param; + return { rank, code, name, num, time: Math.floor(num1/1000), durability: num2 }; + }); + let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); + ranks = { guildRank, myGuildRank } + } + + + return resResult(STATUS.SUCCESS, { + ...statusResult, + hasJoin: !!hasJoin, + code: hasJoin?.code||'', + woodenHorse, + ...ranks, + events + }); + } + + // 离开粮草先行界面 + async leavePage(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + await leaveRaceActivity(serverId, guildCode, roleId); + + return resResult(STATUS.SUCCESS); + } + + // 加入木马 + async join(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + const sid = session.get('sid'); + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + let joinIndex = getJoinIndex(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let obj = getRaceActivityObj(); + + let hasJoin = !!obj.getMember(guildCode, roleId); + if (hasJoin) { + return resResult(STATUS.RACE_HAS_JOIN); + } + + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, joinIndex, obj.getEvents(guildCode, 0)); + if (!guildActivityRec) return resResult(STATUS.WRONG_PARMS); + + let { code: sourceCode } = guildActivityRec; + let myGuildActivityRec = await UserGuildActivityRecModel.getRecord(roleId, roleName, guildCode, serverId, sourceCode, this.aid); + + let myGuild = await UserGuildModel.getMyGuild(roleId, 'job'); + let woodenHorse = await obj.joinWoodenHorse(guildCode, roleId, roleName, serverId, sid, myGuild.job, myGuildActivityRec.code); + if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + await GuildActivityRecordModel.join(guildCode, this.aid, joinIndex, { roleId, roleName, job: myGuild.job, code: myGuildActivityRec.code }); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_RACE_JOIN, { timestamp: Date.now(), woodenHorse }); + + // 全服活跃统计 + await ServerRecordModel.addActiveGuild(serverId, roleId, guildCode); + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_ACTIVITY, { aid: this.aid }); + + return resResult(STATUS.SUCCESS, { + code: myGuildActivityRec.code, + ...statusResult, + hasJoin, + woodenHorse, + events + }); + } + + // 打开竞赛页面 + async getRace(msg: {}, session: BackendSession) { + + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + if (!guildCode) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // if (statusResult.status != GUILD_ACTIVITY_STATUS.START) { + // return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + // } + + let obj = getRaceActivityObj(); + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if (!woodenHorse) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH); + + let events = obj.getEvents(guildCode, woodenHorse.distance); + let hasJoin = !!obj.getMember(guildCode, roleId); + let items = obj.getItem(roleId); + + let woodenHorseList = await getWoodenHorseList(guildCode, serverId); + + return resResult(STATUS.SUCCESS, { + ...statusResult, + hasJoin, + woodenHorseList, + events, + items + }); + } + + + // 使用道具 + async useItem(msg: { id: number, count: number, toGuild: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + let sid = session.get('sid'); + let joinIndex = getJoinIndex(); + + let { id, count, toGuild } = msg; + let obj = getRaceActivityObj(); + let woodenHorse = obj.getWoodenHorse(toGuild, serverId); + if (!woodenHorse) return resResult(STATUS.WRONG_PARMS); + + let event = await obj.useItem(serverId, roleId, sid, guildCode, toGuild, id, count); + if (!event) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + await GuildActivityRecordModel.pushEvent(guildCode, this.aid, joinIndex, event); + + return resResult(STATUS.SUCCESS, { + timestamp: Date.now(), + events: obj.getEvents(guildCode, 0) + }); + } + + // 结束挑战 + async battleEnd(msg: { code: string, isSuccess: boolean }, session: BackendSession) { + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + + let { code, isSuccess } = msg; + let joinIndex = getJoinIndex(); + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 更新userGuildActivityRecord + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, this.aid, joinIndex); + let myGuildActivityRec = await UserGuildActivityRecModel.updateInfo(code, { isSuccess, isCompleted: true }); + if (!guildActivityRec || !myGuildActivityRec) return resResult(STATUS.WRONG_PARMS); + + let hasShow = !!myGuildActivityRec.hasShow; + if(!hasShow) { + await UserGuildActivityRecModel.updateInfo(code, { hasShow: true }); + } + + // 返回当前军团总军功 + let obj = getRaceActivityObj(); + let myGuildRank = 0; + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if(woodenHorse) { + let { myGuildRank: rank, guildRank } = await obj.getRanks(serverId, guildCode); + // console.log('#', JSON.stringify(guildRank)) + myGuildRank = rank?.rank||0; + if(woodenHorse) { + // console.log('########', woodenHorse.time - woodenHorse.allStartTime, rank.sortTime); + woodenHorse = woodenHorse.getTreatTime(); + } + } else { + woodenHorse = guildActivityRec.woodenHorse; + myGuildRank = guildActivityRec.rank; + } + + + return resResult(STATUS.SUCCESS, { + timestamp: Date.now(), + hasShow, + woodenHorse, + myGuildRank + }) + } + + // 加入木马 + async debugAddHorse(msg: { magicWord: string, isMyGuild: number, memberCnt: number, itemInterval: number }, session: BackendSession) { + const { magicWord, isMyGuild, memberCnt, itemInterval } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + const serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + if(!isMyGuild) { + guildCode = genCode(8); + } + + let statusResult = getGuildActivityStatus(this.aid); + if (!statusResult) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(!statusResult.isOpen) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + if(statusResult.status != GUILD_ACTIVITY_STATUS.START) return resResult(STATUS.GUILD_ACTIVITY_NOT_OPEN); + + + let guild = pinus.app.getServersByType('guild'); + let sid = await dispatch(redisClient(), `${serverId}`, guild, 'guild'); + pinus.app.rpc.guild.guildActivityRemote.debugAddHorse.toServer(sid.id, serverId, guildCode, memberCnt, itemInterval) + + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/guild/handler/wishPoolHandler.ts b/game-server/app/servers/guild/handler/wishPoolHandler.ts index 5029be3ca..d70686020 100644 --- a/game-server/app/servers/guild/handler/wishPoolHandler.ts +++ b/game-server/app/servers/guild/handler/wishPoolHandler.ts @@ -1,172 +1,173 @@ -import { Application, BackendSession } from 'pinus'; -import { UserGuildModel } from '../../../db/UserGuild'; -import { GuildModel } from '../../../db/Guild'; -import { WishPoolReportModel } from '../../../db/WishPoolReport'; -import { resResult, genCode } from '../../../pubUtils/util'; -import { ITEM_CHANGE_REASON, PUSH_ROUTE, STATUS } from '../../../consts'; -import { gameData, getGoodById, getWishPoolReward } from '../../../pubUtils/data'; -import { addItems, checkGoods, checkHeroEquips, checkHeroes, getHonourObject, handleCost } from '../../../services/role/rewardService'; -import { ITID, CONSUME_TYPE } from '../../../consts/constModules/itemConst'; -import { GUILD_POINT_WAYS, GUILD_STRUCTURE, WISH_POOL_TYPE } from '../../../consts/constModules/guildConst'; -import { getWishPool, getUserGuildWithRefActive, addActive, canWishToday } from '../../../services/guildService'; -import { findIndex, findWhere } from 'underscore'; -import { RoleModel } from '../../../db/Role'; -import { getRoleOnlineInfo } from '../../../services/redisService'; -import { ARMY } from '../../../pubUtils/dicParam'; -import { guildInter } from '../../../pubUtils/interface'; -import { getSeconds, getZeroPoint, nowSeconds, isToday } from '../../../pubUtils/timeUtil'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; -import { isGoodsHidden } from '../../../services/dataService'; -export default function(app: Application) { - return new WishPoolHandler(app); -} - -export class WishPoolHandler { - constructor(private app: Application) { - - } - - async getWishPool(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - let res = await getWishPool(userGuild); - return resResult(STATUS.SUCCESS, res); - } - - // 许愿 - async wishGoods(msg: guildInter & {goodId: number, type: number}, session: BackendSession) { - const { goodId, type, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const serverId: number = parseInt(session.get('serverId')); - - if(isGoodsHidden(goodId)) return resResult(STATUS.ITEM_IS_HIDDEN); - let dicGoods = getGoodById(goodId) - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicItid = ITID.get(dicGoods.itid); - if (dicItid.type != CONSUME_TYPE.SOUL || type != WISH_POOL_TYPE.SOUL) - return resResult(STATUS.GUILD_WISH_POOL_CAN_NOT_WISH); - - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) return resResult(STATUS.WRONG_PARMS); - - // 退出A军团 和 新入B军团 在同一天, 且在A军团已经许过愿,那么此时不允许许愿 - if (!await canWishToday(roleId)) { - return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); - } - - const { guildCode: code, wishGoods, receivedWishPool } = userGuild; - - let { lv } = await GuildModel.findGuild(code, serverId, 'lv'); - let len = wishGoods.filter(cur => cur.type == type).length; - - if(receivedWishPool.indexOf(type) != -1) { - return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); - } - if (len >= ARMY.ARMY_WISH_TIMES) //今日已经许愿过 - return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); - - let dicStructure = gameData.centerBase.get(lv); - let count = 0; - if (type == WISH_POOL_TYPE.SOUL) { - let wishGoodsHero = dicStructure.wishgoodsHero.find(cur => cur.quality == dicGoods.quality); - if (!wishGoodsHero) return resResult(STATUS.NOT_WISH_THE_QUALITY_GOODS); - count = wishGoodsHero.count; - } - - const id = genCode(6); - let { wishGoods: resWishGoods } = await UserGuildModel.pushAndUpdate(roleId, {}, { wishGoods: { type, goodId, count, receiveCnt: 0, drawCnt: 0, id, donateNames:[]} }, 'wishGoods'); - return resResult(STATUS.SUCCESS, { wishGoods: resWishGoods, receivedWishPool }); - } - - // 捐赠 - async donateGoods(msg: guildInter & {wishRoleId: string, id: string}, session: BackendSession) { - let { wishRoleId, id, myUserGuild } = msg; - const dntRoleId: string = session.get('roleId'); - const dntRoleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - if (wishRoleId == dntRoleId) - return resResult(STATUS.WRONG_PARMS); - let role = await RoleModel.findByRoleId(wishRoleId); - if (!role) - return resResult(STATUS.WRONG_PARMS);//没有玩家 - let wishUserGuild = await getUserGuildWithRefActive(wishRoleId, ' wishDntCnt wishGoods guildCode'); - if (!wishUserGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code, wishGoods } = wishUserGuild; - let dntRoleGuild = await getUserGuildWithRefActive(dntRoleId); - if (!dntRoleGuild) - return resResult(STATUS.WRONG_PARMS); - if (dntRoleGuild.guildCode != code) - return resResult(STATUS.WRONG_PARMS); - if (dntRoleGuild.wishDntCnt >= ARMY.ARMY_WISH_HELP) - return resResult(STATUS.HAS_REACH_WISH_DONATE_COUNT_LIMIT); - let wishGood = findWhere(wishGoods, { id }); - if (!wishGood) - return resResult(STATUS.WRONG_PARMS);//没有该许愿 - if (wishGood.receiveCnt >= wishGood.count) - return resResult(STATUS.HAS_RECEIVE_WISH_GOOD);//已经收到 - - if(isGoodsHidden(wishGood.goodId)) return resResult(STATUS.ITEM_IS_HIDDEN); - - let dicWishReward = getWishPoolReward(wishGood.goodId); - if(!dicWishReward) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let costResult = await handleCost(dntRoleId, sid, [{ id: wishGood.goodId, count: 1 }], ITEM_CHANGE_REASON.WISH_POOL_DONATE); - if(!costResult) return resResult(STATUS.GUILD_DONATE_CAN_NOT_SEND); - - let { wishDntCnt } = await UserGuildModel.donateGoods(dntRoleId, 1, 'wishDntCnt'); - let { wishGoods: resWishGoods } = await UserGuildModel.donateUpdate(wishRoleId, dntRoleName, id, 'wishGoods'); - - let hisOnlineInfo = await getRoleOnlineInfo(wishRoleId); - if(hisOnlineInfo.isOnline && hisOnlineInfo.sid) { - sendMessageToUserWithSuc(wishRoleId, PUSH_ROUTE.WISH_GOODS_RECEIVE, { wishGoods: resWishGoods }, hisOnlineInfo.sid); - } - await WishPoolReportModel.addReport(code, wishRoleId, role.roleName , dntRoleId, dntRoleName, wishGood.goodId, 1); - let goods = await addItems(dntRoleId, dntRoleName, sid, [getHonourObject(dicWishReward.honourReward)], ITEM_CHANGE_REASON.WISH_POOL_DONATE); - await addActive(dntRoleId, serverId, GUILD_POINT_WAYS.WISH_POOL); - - return resResult(STATUS.SUCCESS, { wishDntCnt, goods, updateWishGoods: resWishGoods.map(({type, goodId, count, receiveCnt, drawCnt, id})=>{ - return { type, goodId, count, receiveCnt, drawCnt, id, roleId: wishRoleId }; - }) - }); - } - - async receiveGoods(msg: guildInter & { id: string }, session: BackendSession) { - let { id, myUserGuild } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { wishGoods, receivedWishPool } = userGuild; - let index = findIndex(wishGoods, { id }); - if (index == -1) - return resResult(STATUS.WRONG_PARMS); - let { drawCnt, goodId } = wishGoods[index]; - if (drawCnt <= 0) - return resResult(STATUS.WRONG_PARMS); - wishGoods[index].drawCnt = 0; - if(receivedWishPool.indexOf(wishGoods[index].type) == -1) receivedWishPool.push(wishGoods[index].type); - - let result = await UserGuildModel.updateInfo(roleId, { wishGoods, receivedWishPool }, {}); - if (!result) - resResult(STATUS.INTERNAL_ERR); - let goods = await addItems(roleId, roleName, sid, [{ id : goodId, count: drawCnt }], ITEM_CHANGE_REASON.WISH_POOL_RECEIVE); - return resResult(STATUS.SUCCESS, { goods, wishGoods, receivedWishPool }); - } - - async getReports(msg: guildInter & {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const { myUserGuild } = msg; - let userGuild = await getUserGuildWithRefActive(roleId); - if (!userGuild) - return resResult(STATUS.WRONG_PARMS); - const { guildCode: code } = userGuild; - const reports = await WishPoolReportModel.getReportsByTime(code, 1);//获得今天的捐赠日报 - return resResult(STATUS.SUCCESS, { reports }); - } -} \ No newline at end of file +import { Application, BackendSession } from 'pinus'; +import { UserGuildModel } from '@db/UserGuild'; +import { GuildModel } from '@db/Guild'; +import { WishPoolReportModel } from '@db/WishPoolReport'; +import { resResult, genCode } from '@pubUtils/util'; +import { ITEM_CHANGE_REASON, PUSH_ROUTE, STATUS } from '../../../consts'; +import { gameData, getGoodById, getWishPoolReward } from '@pubUtils/data'; +import { addItems, checkGoods, checkHeroEquips, checkHeroes, getHonourObject, handleCost } from '../../../services/role/rewardService'; +import { ITID, CONSUME_TYPE } from '@consts/constModules/itemConst'; +import { GUILD_POINT_WAYS, GUILD_STRUCTURE, WISH_POOL_TYPE } from '@consts/constModules/guildConst'; +import { getWishPool, getUserGuildWithRefActive, addActive, canWishToday } from '../../../services/guildService'; +import { findIndex, findWhere } from 'underscore'; +import { RoleModel } from '@db/Role'; +import { getRoleOnlineInfo } from '../../../services/redisService'; +import { ARMY } from '@pubUtils/dicParam'; +import { guildInter } from '@pubUtils/interface'; +import { getSeconds, getZeroPoint, nowSeconds, isToday } from '@pubUtils/timeUtil'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; +import { isGoodsHidden } from '../../../services/dataService'; +export default function(app: Application) { + return new WishPoolHandler(app); +} + +export class WishPoolHandler { + constructor(private app: Application) { + + } + + async getWishPool(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + let res = await getWishPool(userGuild); + return resResult(STATUS.SUCCESS, res); + } + + // 许愿 + async wishGoods(msg: guildInter & {goodId: number, type: number}, session: BackendSession) { + const { goodId, type, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const serverId: number = parseInt(session.get('serverId')); + + if(isGoodsHidden(goodId)) return resResult(STATUS.ITEM_IS_HIDDEN); + let dicGoods = getGoodById(goodId) + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicItid = ITID.get(dicGoods.itid); + if (dicItid.type != CONSUME_TYPE.SOUL || type != WISH_POOL_TYPE.SOUL) + return resResult(STATUS.GUILD_WISH_POOL_CAN_NOT_WISH); + + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) return resResult(STATUS.WRONG_PARMS); + + // 退出A军团 和 新入B军团 在同一天, 且在A军团已经许过愿,那么此时不允许许愿 + if (!await canWishToday(roleId)) { + return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); + } + + const { guildCode: code, wishGoods, receivedWishPool } = userGuild; + + let { lv } = await GuildModel.findGuild(code, serverId, 'lv'); + let len = wishGoods.filter(cur => cur.type == type).length; + + if(receivedWishPool.indexOf(type) != -1) { + return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); + } + if (len >= ARMY.ARMY_WISH_TIMES) //今日已经许愿过 + return resResult(STATUS.HAS_REACH_WISH_COUNT_LIMIT); + + let dicStructure = gameData.centerBase.get(lv); + let count = 0; + if (type == WISH_POOL_TYPE.SOUL) { + let wishGoodsHero = dicStructure.wishgoodsHero.find(cur => cur.quality == dicGoods.quality); + if (!wishGoodsHero) return resResult(STATUS.NOT_WISH_THE_QUALITY_GOODS); + count = wishGoodsHero.count; + } + + const id = genCode(6); + let { wishGoods: resWishGoods } = await UserGuildModel.pushAndUpdate(roleId, {}, { wishGoods: { type, goodId, count, receiveCnt: 0, drawCnt: 0, id, donateNames:[]} }, 'wishGoods'); + return resResult(STATUS.SUCCESS, { wishGoods: resWishGoods, receivedWishPool }); + } + + // 捐赠 + async donateGoods(msg: guildInter & {wishRoleId: string, id: string}, session: BackendSession) { + let { wishRoleId, id, myUserGuild } = msg; + const dntRoleId: string = session.get('roleId'); + const dntRoleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + if (wishRoleId == dntRoleId) + return resResult(STATUS.WRONG_PARMS); + let role = await RoleModel.findByRoleId(wishRoleId); + if (!role) + return resResult(STATUS.WRONG_PARMS);//没有玩家 + let wishUserGuild = await getUserGuildWithRefActive(wishRoleId, ' wishDntCnt wishGoods guildCode'); + if (!wishUserGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code, wishGoods } = wishUserGuild; + let dntRoleGuild = await getUserGuildWithRefActive(dntRoleId); + if (!dntRoleGuild) + return resResult(STATUS.WRONG_PARMS); + if (dntRoleGuild.guildCode != code) + return resResult(STATUS.WRONG_PARMS); + if (dntRoleGuild.wishDntCnt >= ARMY.ARMY_WISH_HELP) + return resResult(STATUS.HAS_REACH_WISH_DONATE_COUNT_LIMIT); + let wishGood = findWhere(wishGoods, { id }); + if (!wishGood) + return resResult(STATUS.WRONG_PARMS);//没有该许愿 + if (wishGood.receiveCnt >= wishGood.count) + return resResult(STATUS.HAS_RECEIVE_WISH_GOOD);//已经收到 + + if(isGoodsHidden(wishGood.goodId)) return resResult(STATUS.ITEM_IS_HIDDEN); + + let dicWishReward = getWishPoolReward(wishGood.goodId); + if(!dicWishReward) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let costResult = await handleCost(dntRoleId, sid, [{ id: wishGood.goodId, count: 1 }], ITEM_CHANGE_REASON.WISH_POOL_DONATE); + if(!costResult) return resResult(STATUS.GUILD_DONATE_CAN_NOT_SEND); + + let { wishDntCnt } = await UserGuildModel.donateGoods(dntRoleId, 1, 'wishDntCnt'); + let { wishGoods: resWishGoods } = await UserGuildModel.donateUpdate(wishRoleId, dntRoleName, id, 'wishGoods'); + + let hisOnlineInfo = await getRoleOnlineInfo(wishRoleId); + if(hisOnlineInfo.isOnline && hisOnlineInfo.sid) { + sendMessageToUserWithSuc(wishRoleId, PUSH_ROUTE.WISH_GOODS_RECEIVE, { wishGoods: resWishGoods }, hisOnlineInfo.sid); + } + await WishPoolReportModel.addReport(code, wishRoleId, role.roleName , dntRoleId, dntRoleName, wishGood.goodId, 1); + let goods = await addItems(dntRoleId, dntRoleName, sid, [getHonourObject(dicWishReward.honourReward)], ITEM_CHANGE_REASON.WISH_POOL_DONATE); + await addActive(dntRoleId, serverId, GUILD_POINT_WAYS.WISH_POOL); + + return resResult(STATUS.SUCCESS, { wishDntCnt, goods, updateWishGoods: resWishGoods.map(({type, goodId, count, receiveCnt, drawCnt, id})=>{ + return { type, goodId, count, receiveCnt, drawCnt, id, roleId: wishRoleId }; + }) + }); + } + + async receiveGoods(msg: guildInter & { id: string }, session: BackendSession) { + let { id, myUserGuild } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { wishGoods, receivedWishPool } = userGuild; + let index = findIndex(wishGoods, { id }); + if (index == -1) + return resResult(STATUS.WRONG_PARMS); + let { drawCnt, goodId } = wishGoods[index]; + if (drawCnt <= 0) + return resResult(STATUS.WRONG_PARMS); + wishGoods[index].drawCnt = 0; + if(receivedWishPool.indexOf(wishGoods[index].type) == -1) receivedWishPool.push(wishGoods[index].type); + + let result = await UserGuildModel.updateInfo(roleId, { wishGoods, receivedWishPool }, {}); + if (!result) + resResult(STATUS.INTERNAL_ERR); + let goods = await addItems(roleId, roleName, sid, [{ id : goodId, count: drawCnt }], ITEM_CHANGE_REASON.WISH_POOL_RECEIVE); + return resResult(STATUS.SUCCESS, { goods, wishGoods, receivedWishPool }); + } + + async getReports(msg: guildInter & {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const { myUserGuild } = msg; + let userGuild = await getUserGuildWithRefActive(roleId); + if (!userGuild) + return resResult(STATUS.WRONG_PARMS); + const { guildCode: code } = userGuild; + const reports = await WishPoolReportModel.getReportsByTime(code, 1);//获得今天的捐赠日报 + return resResult(STATUS.SUCCESS, { reports }); + } +} + diff --git a/game-server/app/servers/guild/remote/guildActivityRemote.ts b/game-server/app/servers/guild/remote/guildActivityRemote.ts index 05ee60a0d..8abf288c8 100644 --- a/game-server/app/servers/guild/remote/guildActivityRemote.ts +++ b/game-server/app/servers/guild/remote/guildActivityRemote.ts @@ -1,241 +1,242 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { sendAllGuildRanks, calWoodenHorseAndSend, sendRaceStartMsg, setDicGuildActivity, setDicAuctionTime, settleGuildActivityReward, setGuildActivityIndexInPinus, guildActivityStart, debugSendGateHp, debugAddHorse, leaveRaceActivity, leaveRaceWhenQuitGuild, leaveRaceWhenDismiss } from '../../../services/guildActivity/guildActivityService'; -import { gameData } from '../../../pubUtils/data'; -import { setWeek } from '../../../pubUtils/timeUtil'; -import { sendUngotDividend } from '../../../services/auctionService'; -import { errlogger } from '../../../util/logger'; -import { GUILD_ACTIVITY_TYPE } from '../../../consts'; -import { saveGuildActivityIndexMemory } from '../../../services/log/memoryLogService'; -import { clearActivityObj } from '../../../services/memoryCache/guildActivityData'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildActivityRemote(app); -} - -export class GuildActivityRemote { - - constructor(private app: Application) { - this.app = app; - } - - private currentTime: number = Date.now(); - private setTime: number = Date.now(); - private isAuctionPopUp: boolean = false; - - /** - * 从systimer服分发到guild各个服,发送排行榜数据 - */ - public async sendRankToGuilds(aid: number) { - try { - await sendAllGuildRanks(aid); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 发送结束活动消息 - */ - public async guildActivityEnd(aid: number) { - try { - await settleGuildActivityReward(aid); - this.isAuctionPopUp = true; - setTimeout(() => { // 军团活动结束的15分钟内就不会再弹出了 - this.isAuctionPopUp = false; - }, 15 * 60 * 1000); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 计算粮草先行木马状态并发送 - */ - public async calWoodenHorseAndSend(serverId: number) { - try { - await calWoodenHorseAndSend(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 诸侯混战和蛮夷入侵开始 - */ - async guildActivityStart(aid: number) { - try { - await guildActivityStart(aid); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 发送粮草先行活动开始通知 - */ - async raceActivityStart(serverId: number) { - try { - await sendRaceStartMsg(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * !! 注意,这条函数会改变内存中的字典表,影响甚大,请考虑清楚后使用 - */ - async updateGuildActivityData(aid: number, isStart: boolean) { - try { - let guildActivity = gameData.guildActivity; - let cur = guildActivity.get(aid); - - if (isStart) { - let now = new Date(); - cur.startMinute = now.getMinutes(); - cur.startTime = now.getHours(); - cur.startSeconds = now.getSeconds(); - } else { - let now = new Date(Date.now() - cur.duringTime * 1000); - cur.startMinute = now.getMinutes(); - cur.startTime = now.getHours(); - cur.startSeconds = now.getSeconds(); - } - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的军团活动开始时间&持续时间 - * @param {number} aid 活动 - * @param {number} startSeconds 从现在开始几秒后开启活动 - * @param {number} endSeconds 从开始之后几秒后结束活动 - */ - async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { - try { - return setDicGuildActivity(now, aid, startSeconds, endSeconds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的拍卖行时间 - */ - async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { - try { - setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * !! 注意,这条函数会改变内存时间,影响甚大,请考虑清楚后使用 - */ - async setDay(week: number) { - try { - setWeek(week); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - setCurrentTime(time: number) { - try { - this.currentTime = time; - this.setTime = Date.now(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - getCurrentTime() { - try { - return Date.now() - this.setTime + this.currentTime; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async sendUngotDividend() { - try { - await sendUngotDividend(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getAuctionPopUpShow() { - try { - return this.isAuctionPopUp; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - async clearActivityObj() { - try { - clearActivityObj(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - async setGuildActivityIndex(aid: number, index: number) { - try { - setGuildActivityIndexInPinus(aid, index); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async debugSendGateHp(serverId: number, cityId: number) { - try { - await debugSendGateHp(serverId, cityId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async debugAddHorse(serverId: number, guildCode: string, memberCnt: number, itemInterval: number) { - try { - await debugAddHorse(serverId, guildCode, memberCnt, itemInterval); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public saveGuildActivityIndexMemory() { - try { - return saveGuildActivityIndexMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public leaveRaceActivity(serverId: number, guildCode: string, roleId: string) { - try { - return leaveRaceActivity(serverId, guildCode, roleId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public leaveRaceWhenQuitGuild(serverId: number, guildCode: string, roleId: string) { - try { - return leaveRaceWhenQuitGuild(serverId, guildCode, roleId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public leaveRaceWhenDismiss(guildCode: string, serverId: number) { - try { - return leaveRaceWhenDismiss(guildCode, serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { sendAllGuildRanks, calWoodenHorseAndSend, sendRaceStartMsg, setDicGuildActivity, setDicAuctionTime, settleGuildActivityReward, setGuildActivityIndexInPinus, guildActivityStart, debugSendGateHp, debugAddHorse, leaveRaceActivity, leaveRaceWhenQuitGuild, leaveRaceWhenDismiss } from '../../../services/guildActivity/guildActivityService'; +import { gameData } from '@pubUtils/data'; +import { setWeek } from '@pubUtils/timeUtil'; +import { sendUngotDividend } from '../../../services/auctionService'; +import { errlogger } from '../../../util/logger'; +import { GUILD_ACTIVITY_TYPE } from '../../../consts'; +import { saveGuildActivityIndexMemory } from '../../../services/log/memoryLogService'; +import { clearActivityObj } from '../../../services/memoryCache/guildActivityData'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildActivityRemote(app); +} + +export class GuildActivityRemote { + + constructor(private app: Application) { + this.app = app; + } + + private currentTime: number = Date.now(); + private setTime: number = Date.now(); + private isAuctionPopUp: boolean = false; + + /** + * 从systimer服分发到guild各个服,发送排行榜数据 + */ + public async sendRankToGuilds(aid: number) { + try { + await sendAllGuildRanks(aid); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 发送结束活动消息 + */ + public async guildActivityEnd(aid: number) { + try { + await settleGuildActivityReward(aid); + this.isAuctionPopUp = true; + setTimeout(() => { // 军团活动结束的15分钟内就不会再弹出了 + this.isAuctionPopUp = false; + }, 15 * 60 * 1000); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 计算粮草先行木马状态并发送 + */ + public async calWoodenHorseAndSend(serverId: number) { + try { + await calWoodenHorseAndSend(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 诸侯混战和蛮夷入侵开始 + */ + async guildActivityStart(aid: number) { + try { + await guildActivityStart(aid); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 发送粮草先行活动开始通知 + */ + async raceActivityStart(serverId: number) { + try { + await sendRaceStartMsg(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * !! 注意,这条函数会改变内存中的字典表,影响甚大,请考虑清楚后使用 + */ + async updateGuildActivityData(aid: number, isStart: boolean) { + try { + let guildActivity = gameData.guildActivity; + let cur = guildActivity.get(aid); + + if (isStart) { + let now = new Date(); + cur.startMinute = now.getMinutes(); + cur.startTime = now.getHours(); + cur.startSeconds = now.getSeconds(); + } else { + let now = new Date(Date.now() - cur.duringTime * 1000); + cur.startMinute = now.getMinutes(); + cur.startTime = now.getHours(); + cur.startSeconds = now.getSeconds(); + } + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的军团活动开始时间&持续时间 + * @param {number} aid 活动 + * @param {number} startSeconds 从现在开始几秒后开启活动 + * @param {number} endSeconds 从开始之后几秒后结束活动 + */ + async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { + try { + return setDicGuildActivity(now, aid, startSeconds, endSeconds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的拍卖行时间 + */ + async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { + try { + setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * !! 注意,这条函数会改变内存时间,影响甚大,请考虑清楚后使用 + */ + async setDay(week: number) { + try { + setWeek(week); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + setCurrentTime(time: number) { + try { + this.currentTime = time; + this.setTime = Date.now(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + getCurrentTime() { + try { + return Date.now() - this.setTime + this.currentTime; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async sendUngotDividend() { + try { + await sendUngotDividend(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getAuctionPopUpShow() { + try { + return this.isAuctionPopUp; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + async clearActivityObj() { + try { + clearActivityObj(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + async setGuildActivityIndex(aid: number, index: number) { + try { + setGuildActivityIndexInPinus(aid, index); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async debugSendGateHp(serverId: number, cityId: number) { + try { + await debugSendGateHp(serverId, cityId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async debugAddHorse(serverId: number, guildCode: string, memberCnt: number, itemInterval: number) { + try { + await debugAddHorse(serverId, guildCode, memberCnt, itemInterval); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public saveGuildActivityIndexMemory() { + try { + return saveGuildActivityIndexMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public leaveRaceActivity(serverId: number, guildCode: string, roleId: string) { + try { + return leaveRaceActivity(serverId, guildCode, roleId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public leaveRaceWhenQuitGuild(serverId: number, guildCode: string, roleId: string) { + try { + return leaveRaceWhenQuitGuild(serverId, guildCode, roleId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public leaveRaceWhenDismiss(guildCode: string, serverId: number) { + try { + return leaveRaceWhenDismiss(guildCode, serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/guild/remote/guildRemote.ts b/game-server/app/servers/guild/remote/guildRemote.ts index c0962797d..dff8a3ee1 100644 --- a/game-server/app/servers/guild/remote/guildRemote.ts +++ b/game-server/app/servers/guild/remote/guildRemote.ts @@ -1,240 +1,241 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { taflush, treatGuildName } from '../../../services/sdkService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { errlogger } from '../../../util/logger'; -import { setApiIsClose } from '../../../services/chatService'; -import { setKvToMemory } from '../../../services/pushService'; -import { getGVGConfig, setGVGConfig } from '../../../services/gvg/gvgService'; -import { GVGConfigType } from '../../../db/GVGConfig'; -import { catapultHurt, gvgBattleEnd, gvgBattleSeconds, gvgBattleStart, initCatapult, leaveCityMem } from '../../../services/gvg/gvgBattleService'; -import { clearBattleMemory } from '../../../services/memoryCache/gvgBattleData'; -import { updateLeagueNameMem, updateTeamRoleInfoMem } from '../../../services/gvg/gvgTeamService'; -import { resetPeriodTime, setPeriodTime } from '../../../services/gvg/gvgFightService'; -import { setServerGroup } from '../../../services/serverService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new GuildRemote(app); -} - -export class GuildRemote { - - constructor(private app: Application) { - this.app = app; - } - - /** - * 重载json资源 - */ - public reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async treatGuildName(content: string) { - try { - await treatGuildName(content); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGVGConfig(config: GVGConfigType) { - try { - await setGVGConfig(config); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async getGVGConfig() { - try { - return getGVGConfig(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - return setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gvgBattleStart() { - try { - return await gvgBattleStart(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async initCatapult(cityId: number, groupKey: string, leagueCode: string, leagueName: string) { - try { - return await initCatapult(cityId, groupKey, leagueCode, leagueName); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async catapultHurt() { - try { - return await catapultHurt(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gvgBattleSeconds() { - try { - return await gvgBattleSeconds(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gvgBattleEnd() { - try { - return await gvgBattleEnd(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async clearBattleMemory() { - try { - return clearBattleMemory(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async leaveCityMem(groupKey: string, roleId: string) { - try { - return leaveCityMem(groupKey, roleId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async updateLeagueNameMem(serverId: number, leagueCode: string, leagueName: string) { - try { - return updateLeagueNameMem(serverId, leagueCode, leagueName); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async updateTeamRoleInfoMem(serverId: number, roleId: string, info: { roleName?: string, lv?: number }) { - try { - return updateTeamRoleInfoMem(serverId, roleId, info); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setPeriodTime(startFightTime: number, endFightTime: number) { - try { - return setPeriodTime(startFightTime, endFightTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public resetPeriodTime() { - try { - return resetPeriodTime(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { taflush, treatGuildName } from '../../../services/sdkService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { errlogger } from '../../../util/logger'; +import { setApiIsClose } from '../../../services/chatService'; +import { setKvToMemory } from '../../../services/pushService'; +import { getGVGConfig, setGVGConfig } from '../../../services/gvg/gvgService'; +import { GVGConfigType } from '@db/GVGConfig'; +import { catapultHurt, gvgBattleEnd, gvgBattleSeconds, gvgBattleStart, initCatapult, leaveCityMem } from '../../../services/gvg/gvgBattleService'; +import { clearBattleMemory } from '../../../services/memoryCache/gvgBattleData'; +import { updateLeagueNameMem, updateTeamRoleInfoMem } from '../../../services/gvg/gvgTeamService'; +import { resetPeriodTime, setPeriodTime } from '../../../services/gvg/gvgFightService'; +import { setServerGroup } from '../../../services/serverService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new GuildRemote(app); +} + +export class GuildRemote { + + constructor(private app: Application) { + this.app = app; + } + + /** + * 重载json资源 + */ + public reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async treatGuildName(content: string) { + try { + await treatGuildName(content); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGVGConfig(config: GVGConfigType) { + try { + await setGVGConfig(config); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async getGVGConfig() { + try { + return getGVGConfig(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + return setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleStart() { + try { + return await gvgBattleStart(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async initCatapult(cityId: number, groupKey: string, leagueCode: string, leagueName: string) { + try { + return await initCatapult(cityId, groupKey, leagueCode, leagueName); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async catapultHurt() { + try { + return await catapultHurt(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleSeconds() { + try { + return await gvgBattleSeconds(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleEnd() { + try { + return await gvgBattleEnd(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async clearBattleMemory() { + try { + return clearBattleMemory(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async leaveCityMem(groupKey: string, roleId: string) { + try { + return leaveCityMem(groupKey, roleId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async updateLeagueNameMem(serverId: number, leagueCode: string, leagueName: string) { + try { + return updateLeagueNameMem(serverId, leagueCode, leagueName); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async updateTeamRoleInfoMem(serverId: number, roleId: string, info: { roleName?: string, lv?: number }) { + try { + return updateTeamRoleInfoMem(serverId, roleId, info); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setPeriodTime(startFightTime: number, endFightTime: number) { + try { + return setPeriodTime(startFightTime, endFightTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public resetPeriodTime() { + try { + return resetPeriodTime(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/order/handler/orderHandler.ts b/game-server/app/servers/order/handler/orderHandler.ts index 145066372..ad66d87e1 100644 --- a/game-server/app/servers/order/handler/orderHandler.ts +++ b/game-server/app/servers/order/handler/orderHandler.ts @@ -1,315 +1,316 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { genCode, resResult } from '../../../pubUtils/util'; -import { ACTIVITY_TYPE, CURRENCY, DEBUG_MAGIC_WORD, DEBUG_PRICE, ITEM_CHANGE_REASON, ORDER_STATE, PAY_TYPE, STATUS, TASK_TYPE, TA_EVENT } from '../../../consts'; -import { dicRMB } from '../../../pubUtils/dictionary/DicRMB'; -import { UserOrderModel } from '../../../db/UserOrder'; -import _ = require('underscore'); -import { applyOrderWX } from '../../../services/pay/weixinPay'; -import { applyOrderALI } from '../../../services/pay/aliPay'; -import { applyOrder37 } from '../../../services/pay/37Pay'; -import { checkOrderCanBuy, settleOrder, settleOrderAli, settleOrderFromHandler, settleOrderWx } from '../../../services/orderService'; -import { getActivityById } from '../../../services/activity/activityService'; -import { reportTAEvent } from '../../../services/sdkService'; -import { canPay, isDebugPay } from '../../../pubUtils/sdkUtil'; -import { isDevelopEnv } from '../../../services/utilService'; -import { checkVoucherId, getVoucherCoinObject, getVoucherObject, handleCost } from '../../../services/role/rewardService'; -import { CheckMeterial } from '../../../services/role/checkMaterial'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new orderHandler(app); -} - -export class orderHandler { - constructor(private app: Application) { - } - - /************************订单****************************/ - - /** - * @description 获取订单号 - * @param {{productID:string, payType:number ,activityId: number, paramStr: string }} msg - * @param {BackendSession} session - * @memberof orderHandler - */ - async applyOrder(msg: { productID: string, payType: number, activityId: number, paramStr: string, useVoucher: number }, session: BackendSession) { - const { productID, payType, activityId, paramStr, useVoucher } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const ip = session.get('ip'); - - //如果有特殊情况,activityId可为0 - if (!productID || !_.isString(productID) || !_.isNumber(payType)) { - return resResult(STATUS.WRONG_PARMS); - } - - if(!canPay()) { - return resResult(STATUS.PAY_NOT_OPEN) - } - - //商品价格信息 - let productInfo = dicRMB.get(productID) - if (!productInfo) { - console.log('productID', productID) - return resResult(STATUS.NO_PRODUCT_ID); - } - - let price = productInfo.price;//价格 - let productType = productInfo.type;//类型 - let message = productInfo.message;//商品信息 - let localOrderID = genCode(32);//本地订单号 - let orderID = '';//平台订单号 - let sdkOrderInfo = null;//客户端需要的平台订单信息 - - if(useVoucher) { - if(!checkVoucherId(useVoucher)) return resResult(STATUS.WRONG_PARMS); - let check = new CheckMeterial(roleId); - let isEnough = await check.decrease([{ id: useVoucher, count: price}]); - if (!isEnough) return resResult(STATUS.VOUCHER_NOT_ENOUGH); - } else { - switch (payType) { - case PAY_TYPE.THREE_SEVEN: - case PAY_TYPE.THREE_SEVEN_IOS: - { - let pay37Order = await applyOrder37(localOrderID, roleId, productInfo); - if (pay37Order.code == -1) { - console.log('37下单失败') - return pay37Order.resData; - } - sdkOrderInfo = pay37Order.data; - orderID = '' - break; - } - case PAY_TYPE.WX: - { - let weixinOrder = await applyOrderWX(localOrderID, price * 100, message); - if (weixinOrder.code == -1) { - console.log('微信下单失败') - return resResult(STATUS.APPLY_ORDER_ERROR); - } - sdkOrderInfo = weixinOrder.data; - orderID = weixinOrder.data.prepayid;//微信订单号 - break; - } - case PAY_TYPE.ALI: - { - let aliOrder = await applyOrderALI(localOrderID, price, message); - if (aliOrder.code == -1) { - console.log('支付宝下单失败') - return resResult(STATUS.APPLY_ORDER_ERROR); - } - sdkOrderInfo = aliOrder.data; - orderID = aliOrder.data;//支付宝订单 - - break; - } - - case PAY_TYPE.TEST: - { - if(!isDevelopEnv()) { - return resResult(STATUS.NO_PAY_TYPE); - } - break; - } - case PAY_TYPE.APPLE: - { - break; - } - default: - console.log('未知支付类型'); - return resResult(STATUS.NO_PAY_TYPE); - } - } - - if(activityId > 0) { - let activityData = await getActivityById(activityId); - let check = await checkOrderCanBuy(roleId, serverId, activityData, productID, paramStr); - if(!check) return resResult(STATUS.ORDER_CANNOT_BUY) - } - - - await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, !!useVoucher, useVoucher); - reportTAEvent(roleId, TA_EVENT.RECHARGE, { - pay_id: localOrderID, chargeId: productID, pay_name: message, pay_amount: price, pay_channel: payType - }, ip) - if(isDebugPay()) { - productInfo = {...productInfo, price: DEBUG_PRICE} - } - return resResult(STATUS.SUCCESS, { orderInfo: sdkOrderInfo, productInfo: { - productID: productInfo.channelProductID, - message: productInfo.message, - price: productInfo.price, - }, localOrderID }); - } - - /** - * @description 查询订单,结算奖励 - * @param {{ localOrderID: string}} msg - * @param {BackendSession} session - * @memberof firstGiftHandler - */ - async checkOrder(msg: { localOrderID: string }, session: BackendSession) { - const { localOrderID } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - if (!localOrderID || !_.isString(localOrderID)) { - return resResult(STATUS.WRONG_PARMS); - } - let orderInfo = await UserOrderModel.findOrder(localOrderID); - if (!orderInfo) { - return resResult(STATUS.NO_ORDER); - } - - //商品价格信息 - let productInfo = dicRMB.get(orderInfo.productID) - if (!productInfo) { - console.log(orderInfo.productID) - return resResult(STATUS.NO_PRODUCT_ID); - } - - if(orderInfo.useVoucher) { - let voucherId = orderInfo.voucherId; - let voucher = [{ id: voucherId, count: productInfo.price }]; - - if(orderInfo.state != ORDER_STATE.APPLY) { - return resResult(STATUS.DUPLICATE_ORDER); - } - if(orderInfo.roleId != roleId) { - console.log('订单玩家错误'); - return resResult(STATUS.ORDER_STATUS_ERROR); - } - - let result = await handleCost(roleId, sid, voucher, ITEM_CHANGE_REASON.USE_VOUCHER); - if(!result) return resResult(STATUS.VOUCHER_NOT_ENOUGH); - - let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - } else { - switch (orderInfo.payType) { - case PAY_TYPE.TEST: - { - let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - break; - } - case PAY_TYPE.THREE_SEVEN: - case PAY_TYPE.THREE_SEVEN_IOS: - case PAY_TYPE.APPLE: - { - break; - } - case PAY_TYPE.WX: - { - let res = await settleOrderWx(orderInfo, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - break; - } - case PAY_TYPE.ALI: - { - let res = await settleOrderAli(orderInfo, serverId, sid); - if(res.code != 0) { - return resResult(res); - } - orderInfo = await UserOrderModel.findOrder(localOrderID); - break; - } - - default: - console.log('未知支付类型'); - return resResult(STATUS.NO_PAY_TYPE); - } - } - - //订单成功 - console.log('结算完成', localOrderID) - let res: any = {}; - try { - res = orderInfo.rewardResult? JSON.parse(orderInfo.rewardResult): {}; - } catch(e) { - console.log('order rewardResult', e); - } - if(res.code && res.code != 0) { - return resResult(STATUS.APPLY_ORDER_ERROR); - } - - return resResult(STATUS.SUCCESS, { - ...res, - price: orderInfo.price, - state: orderInfo.state, - localOrderID: orderInfo.localOrderID - }); - } - - - /** - * @description 支付测试 - * @param {{productID:string, magicWord:string, paramStr: string }} msg - * @param {BackendSession} session - * @memberof orderHandler - */ - async debugOrder(msg: { productID: string, magicWord: string, paramStr: string, activityId: number }, session: BackendSession) { - const { magicWord, productID, paramStr, activityId } = msg; - if (magicWord !== DEBUG_MAGIC_WORD || !activityId) { - return resResult(STATUS.WRONG_PARMS); - } - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - - - let payType = PAY_TYPE.TEST - //如果有特殊情况,activityId可为0 - if (!productID || !_.isString(productID)) { - return resResult(STATUS.WRONG_PARMS); - } - - //商品价格信息 - let productInfo = dicRMB.get(productID) - if (!productInfo) { - console.log('productID', productID) - return resResult(STATUS.NO_PRODUCT_ID); - } - - let price = productInfo.price;//价格 - let productType = productInfo.type;//类型 - let message = productInfo.message;//商品信息 - let localOrderID = genCode(32);//本地订单号 - let orderID = '';//平台订单号 - let sdkOrderInfo = null;//客户端需要的平台订单信息 - - // let { activityGroupId } = await ServerlistModel.findByServerId(serverId); - // let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, productType, -1); - // if (activityArray.length === 0) { - // return resResult(STATUS.ACTIVITY_MISSING); - // } - let activityData = await getActivityById(activityId); - if (!activityData) return resResult(STATUS.ACTIVITY_MISSING); - let check = await checkOrderCanBuy(roleId, serverId, activityData, productID, paramStr); - if(!check) return resResult(STATUS.ORDER_CANNOT_BUY) - - let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false, 0); - - //订单成功 - if(!orderInfo) { - return resResult(STATUS.NO_ORDER); - } - let result = await settleOrder(orderInfo, serverId, sid); - orderInfo = await UserOrderModel.success(roleId, localOrderID, JSON.stringify(result)); - console.log(`测试支付完成!!!!!!!!!!!!! serverId:${serverId}, productID:${productID}, productType:${productType}, roleId:${roleId}, localOrderID:${localOrderID}, payType:${payType}`) - return resResult(STATUS.SUCCESS, {...result, localOrderID}); - } -} +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { genCode, resResult } from '@pubUtils/util'; +import { ACTIVITY_TYPE, CURRENCY, DEBUG_MAGIC_WORD, DEBUG_PRICE, ITEM_CHANGE_REASON, ORDER_STATE, PAY_TYPE, STATUS, TASK_TYPE, TA_EVENT } from '../../../consts'; +import { dicRMB } from '@pubUtils/dictionary/DicRMB'; +import { UserOrderModel } from '@db/UserOrder'; +import _ = require('underscore'); +import { applyOrderWX } from '../../../services/pay/weixinPay'; +import { applyOrderALI } from '../../../services/pay/aliPay'; +import { applyOrder37 } from '../../../services/pay/37Pay'; +import { checkOrderCanBuy, settleOrder, settleOrderAli, settleOrderFromHandler, settleOrderWx } from '../../../services/orderService'; +import { getActivityById } from '../../../services/activity/activityService'; +import { reportTAEvent } from '../../../services/sdkService'; +import { canPay, isDebugPay } from '@pubUtils/sdkUtil'; +import { isDevelopEnv } from '../../../services/utilService'; +import { checkVoucherId, getVoucherCoinObject, getVoucherObject, handleCost } from '../../../services/role/rewardService'; +import { CheckMeterial } from '../../../services/role/checkMaterial'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new orderHandler(app); +} + +export class orderHandler { + constructor(private app: Application) { + } + + /************************订单****************************/ + + /** + * @description 获取订单号 + * @param {{productID:string, payType:number ,activityId: number, paramStr: string }} msg + * @param {BackendSession} session + * @memberof orderHandler + */ + async applyOrder(msg: { productID: string, payType: number, activityId: number, paramStr: string, useVoucher: number }, session: BackendSession) { + const { productID, payType, activityId, paramStr, useVoucher } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const ip = session.get('ip'); + + //如果有特殊情况,activityId可为0 + if (!productID || !_.isString(productID) || !_.isNumber(payType)) { + return resResult(STATUS.WRONG_PARMS); + } + + if(!canPay()) { + return resResult(STATUS.PAY_NOT_OPEN) + } + + //商品价格信息 + let productInfo = dicRMB.get(productID) + if (!productInfo) { + console.log('productID', productID) + return resResult(STATUS.NO_PRODUCT_ID); + } + + let price = productInfo.price;//价格 + let productType = productInfo.type;//类型 + let message = productInfo.message;//商品信息 + let localOrderID = genCode(32);//本地订单号 + let orderID = '';//平台订单号 + let sdkOrderInfo = null;//客户端需要的平台订单信息 + + if(useVoucher) { + if(!checkVoucherId(useVoucher)) return resResult(STATUS.WRONG_PARMS); + let check = new CheckMeterial(roleId); + let isEnough = await check.decrease([{ id: useVoucher, count: price}]); + if (!isEnough) return resResult(STATUS.VOUCHER_NOT_ENOUGH); + } else { + switch (payType) { + case PAY_TYPE.THREE_SEVEN: + case PAY_TYPE.THREE_SEVEN_IOS: + { + let pay37Order = await applyOrder37(localOrderID, roleId, productInfo); + if (pay37Order.code == -1) { + console.log('37下单失败') + return pay37Order.resData; + } + sdkOrderInfo = pay37Order.data; + orderID = '' + break; + } + case PAY_TYPE.WX: + { + let weixinOrder = await applyOrderWX(localOrderID, price * 100, message); + if (weixinOrder.code == -1) { + console.log('微信下单失败') + return resResult(STATUS.APPLY_ORDER_ERROR); + } + sdkOrderInfo = weixinOrder.data; + orderID = weixinOrder.data.prepayid;//微信订单号 + break; + } + case PAY_TYPE.ALI: + { + let aliOrder = await applyOrderALI(localOrderID, price, message); + if (aliOrder.code == -1) { + console.log('支付宝下单失败') + return resResult(STATUS.APPLY_ORDER_ERROR); + } + sdkOrderInfo = aliOrder.data; + orderID = aliOrder.data;//支付宝订单 + + break; + } + + case PAY_TYPE.TEST: + { + if(!isDevelopEnv()) { + return resResult(STATUS.NO_PAY_TYPE); + } + break; + } + case PAY_TYPE.APPLE: + { + break; + } + default: + console.log('未知支付类型'); + return resResult(STATUS.NO_PAY_TYPE); + } + } + + if(activityId > 0) { + let activityData = await getActivityById(activityId); + let check = await checkOrderCanBuy(roleId, serverId, activityData, productID, paramStr); + if(!check) return resResult(STATUS.ORDER_CANNOT_BUY) + } + + + await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, !!useVoucher, useVoucher); + reportTAEvent(roleId, TA_EVENT.RECHARGE, { + pay_id: localOrderID, chargeId: productID, pay_name: message, pay_amount: price, pay_channel: payType + }, ip) + if(isDebugPay()) { + productInfo = {...productInfo, price: DEBUG_PRICE} + } + return resResult(STATUS.SUCCESS, { orderInfo: sdkOrderInfo, productInfo: { + productID: productInfo.channelProductID, + message: productInfo.message, + price: productInfo.price, + }, localOrderID }); + } + + /** + * @description 查询订单,结算奖励 + * @param {{ localOrderID: string}} msg + * @param {BackendSession} session + * @memberof firstGiftHandler + */ + async checkOrder(msg: { localOrderID: string }, session: BackendSession) { + const { localOrderID } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + if (!localOrderID || !_.isString(localOrderID)) { + return resResult(STATUS.WRONG_PARMS); + } + let orderInfo = await UserOrderModel.findOrder(localOrderID); + if (!orderInfo) { + return resResult(STATUS.NO_ORDER); + } + + //商品价格信息 + let productInfo = dicRMB.get(orderInfo.productID) + if (!productInfo) { + console.log(orderInfo.productID) + return resResult(STATUS.NO_PRODUCT_ID); + } + + if(orderInfo.useVoucher) { + let voucherId = orderInfo.voucherId; + let voucher = [{ id: voucherId, count: productInfo.price }]; + + if(orderInfo.state != ORDER_STATE.APPLY) { + return resResult(STATUS.DUPLICATE_ORDER); + } + if(orderInfo.roleId != roleId) { + console.log('订单玩家错误'); + return resResult(STATUS.ORDER_STATUS_ERROR); + } + + let result = await handleCost(roleId, sid, voucher, ITEM_CHANGE_REASON.USE_VOUCHER); + if(!result) return resResult(STATUS.VOUCHER_NOT_ENOUGH); + + let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + } else { + switch (orderInfo.payType) { + case PAY_TYPE.TEST: + { + let res = await settleOrderFromHandler(localOrderID, roleId, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + case PAY_TYPE.THREE_SEVEN: + case PAY_TYPE.THREE_SEVEN_IOS: + case PAY_TYPE.APPLE: + { + break; + } + case PAY_TYPE.WX: + { + let res = await settleOrderWx(orderInfo, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + case PAY_TYPE.ALI: + { + let res = await settleOrderAli(orderInfo, serverId, sid); + if(res.code != 0) { + return resResult(res); + } + orderInfo = await UserOrderModel.findOrder(localOrderID); + break; + } + + default: + console.log('未知支付类型'); + return resResult(STATUS.NO_PAY_TYPE); + } + } + + //订单成功 + console.log('结算完成', localOrderID) + let res: any = {}; + try { + res = orderInfo.rewardResult? JSON.parse(orderInfo.rewardResult): {}; + } catch(e) { + console.log('order rewardResult', e); + } + if(res.code && res.code != 0) { + return resResult(STATUS.APPLY_ORDER_ERROR); + } + + return resResult(STATUS.SUCCESS, { + ...res, + price: orderInfo.price, + state: orderInfo.state, + localOrderID: orderInfo.localOrderID + }); + } + + + /** + * @description 支付测试 + * @param {{productID:string, magicWord:string, paramStr: string }} msg + * @param {BackendSession} session + * @memberof orderHandler + */ + async debugOrder(msg: { productID: string, magicWord: string, paramStr: string, activityId: number }, session: BackendSession) { + const { magicWord, productID, paramStr, activityId } = msg; + if (magicWord !== DEBUG_MAGIC_WORD || !activityId) { + return resResult(STATUS.WRONG_PARMS); + } + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + + + let payType = PAY_TYPE.TEST + //如果有特殊情况,activityId可为0 + if (!productID || !_.isString(productID)) { + return resResult(STATUS.WRONG_PARMS); + } + + //商品价格信息 + let productInfo = dicRMB.get(productID) + if (!productInfo) { + console.log('productID', productID) + return resResult(STATUS.NO_PRODUCT_ID); + } + + let price = productInfo.price;//价格 + let productType = productInfo.type;//类型 + let message = productInfo.message;//商品信息 + let localOrderID = genCode(32);//本地订单号 + let orderID = '';//平台订单号 + let sdkOrderInfo = null;//客户端需要的平台订单信息 + + // let { activityGroupId } = await ServerlistModel.findByServerId(serverId); + // let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, productType, -1); + // if (activityArray.length === 0) { + // return resResult(STATUS.ACTIVITY_MISSING); + // } + let activityData = await getActivityById(activityId); + if (!activityData) return resResult(STATUS.ACTIVITY_MISSING); + let check = await checkOrderCanBuy(roleId, serverId, activityData, productID, paramStr); + if(!check) return resResult(STATUS.ORDER_CANNOT_BUY) + + let orderInfo = await UserOrderModel.applyOrder(serverId, roleId, productID, localOrderID, orderID, price, payType, activityId, paramStr, message, false, 0); + + //订单成功 + if(!orderInfo) { + return resResult(STATUS.NO_ORDER); + } + let result = await settleOrder(orderInfo, serverId, sid); + orderInfo = await UserOrderModel.success(roleId, localOrderID, JSON.stringify(result)); + console.log(`测试支付完成!!!!!!!!!!!!! serverId:${serverId}, productID:${productID}, productType:${productType}, roleId:${roleId}, localOrderID:${localOrderID}, payType:${payType}`) + return resResult(STATUS.SUCCESS, {...result, localOrderID}); + } +} + diff --git a/game-server/app/servers/order/remote/orderRemote.ts b/game-server/app/servers/order/remote/orderRemote.ts index c82cd6e4f..67dcdbaf5 100644 --- a/game-server/app/servers/order/remote/orderRemote.ts +++ b/game-server/app/servers/order/remote/orderRemote.ts @@ -1,133 +1,134 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { refundOrderFromRedisPub, settleOrderFromRedisPub } from '../../../services/orderService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { taflush } from '../../../services/sdkService'; -import { errlogger } from '../../../util/logger'; -import { setApiIsClose } from '../../../services/chatService'; -import { setKvToMemory } from '../../../services/pushService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new OrderRemote(app); -} - -export class OrderRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - - private channelService: ChannelService; - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async settleOrderFromRedisPub(message: string) { - try { - await settleOrderFromRedisPub(message); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async refundOrderFromRedisPub(message: string) { - try { - await refundOrderFromRedisPub(message); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} \ No newline at end of file +import { Application, ChannelService, HandlerService, } from 'pinus'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { refundOrderFromRedisPub, settleOrderFromRedisPub } from '../../../services/orderService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { taflush } from '../../../services/sdkService'; +import { errlogger } from '../../../util/logger'; +import { setApiIsClose } from '../../../services/chatService'; +import { setKvToMemory } from '../../../services/pushService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new OrderRemote(app); +} + +export class OrderRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + + private channelService: ChannelService; + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async settleOrderFromRedisPub(message: string) { + try { + await settleOrderFromRedisPub(message); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async refundOrderFromRedisPub(message: string) { + try { + await refundOrderFromRedisPub(message); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/role/handler/artifactHandler.ts b/game-server/app/servers/role/handler/artifactHandler.ts index af359c4b7..2609a3b6b 100644 --- a/game-server/app/servers/role/handler/artifactHandler.ts +++ b/game-server/app/servers/role/handler/artifactHandler.ts @@ -1,358 +1,359 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts"; -import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from "../../../db/Artifact"; -import { HeroModel } from "../../../db/Hero"; -import { ArtifactParam } from "../../../domain/roleField/hero"; -import { gameData, getArtifactByGidAndType, getArtifactStageZero, getArtifactWithQuality, getDicArtifactLvByPlanId, getNextArtifact } from "../../../pubUtils/data"; -import { ARTIFACT, BAG } from "../../../pubUtils/dicParam"; -import { ItemInter, RewardInter } from "../../../pubUtils/interface"; - -import { resResult, parseGoodStr, arrToMap, genCode } from "../../../pubUtils/util"; -import { checkArtifactCanCompose, getRebuildConsume, hasArtifactStrength } from "../../../services/equipService"; -import { calculateCeWithHero } from "../../../services/playerCeService"; -import { CheckMeterial } from "../../../services/role/checkMaterial"; -import { addItems, handleCost } from "../../../services/role/rewardService"; -import { combineItems } from "../../../services/role/util"; -import { checkTask } from "../../../services/task/taskService"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ArtifactHandler(app); -} - -export class ArtifactHandler { - - constructor(private app: Application) { - } - - public async putOn(msg: { seqId: number, hid: number, isExtendLv: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { seqId, hid, isExtendLv } = msg; - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId); - if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - if(chosenArtifact.lv > 0) isExtendLv = false; - - let artifacts: ArtifactModelType[] = []; - let artifactOfHero = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; // 原本自己的天晶石 - let targetLv = artifactOfHero?.lv, returnCoin: RewardInter[] = []; - let dicChosenArtifact = getArtifactWithQuality(chosenArtifact.artifactId); - if(!dicChosenArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if(isExtendLv && targetLv > dicChosenArtifact.maxLv) { - for(let lv = dicChosenArtifact.maxLv + 1; lv <= targetLv; lv++) { - let dicArtifactLv = getDicArtifactLvByPlanId(dicChosenArtifact.lvAttrPlan, lv); - if(!dicArtifactLv) break; - returnCoin.push(...dicArtifactLv.consumes); - } - targetLv = dicChosenArtifact.maxLv; - }; - - if(artifactOfHero) { // 更新自己的天晶石 - artifactOfHero = await ArtifactModel.putOnOrOff(roleId, artifactOfHero.seqId, 0, isExtendLv? 0: undefined); - if(artifactOfHero) artifacts.push(artifactOfHero); - } - if(chosenArtifact.hid != 0) { - let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者 - if(heroOfChosenArtifact) { - await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 对方卸下 - } - } - chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, hid, isExtendLv? targetLv: undefined); - if(chosenArtifact) artifacts.push(chosenArtifact); - await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, serverId, sid, hid, { artifact: seqId }, { artifact: chosenArtifact, job: hero.job, skinId: hero.skinId }); // 把我的换给他 - await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts }); - - let goods = returnCoin.length > 0? await addItems(roleId, roleName, sid, combineItems(returnCoin), ITEM_CHANGE_REASON.ARTIFACT_LV_RETURN): undefined; - - return resResult(STATUS.SUCCESS, { artifacts: artifacts.map(artifact => new ArtifactParam(artifact)), goods }); - } - - public async putOff(msg: { seqId: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { seqId } = msg; - - let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId); - if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者 - if(!heroOfChosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_EQUIPED); - - chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, 0); - let artifacts: ArtifactParam[] = [new ArtifactParam(chosenArtifact)]; - - await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 把我的换给他 - - return resResult(STATUS.SUCCESS, { artifacts }); - } - - public async lvUp(msg: { seqId: number, isOneClick: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { seqId, isOneClick } = msg; - - let artifact = await ArtifactModel.findbySeqId(roleId, seqId); - if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let dicArtifact = getArtifactWithQuality(artifact.artifactId); - if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if(artifact.lv >= dicArtifact.maxLv) return resResult(STATUS.ARTIFACT_LV_MAX); - let toLv = isOneClick? artifact.lv + 5: artifact.lv + 1; - if(toLv > dicArtifact.maxLv) toLv = dicArtifact.maxLv; - let newLv = artifact.lv; - - let check = new CheckMeterial(roleId); - for (let lv = artifact.lv + 1; lv <= toLv; lv++) { - let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); - if(!dicArtifactLv) break; - let isEnough = await check.decrease(dicArtifactLv.consumes); - if(!isEnough) break; // 消耗不足 - newLv = lv; - } - if(newLv == artifact.lv) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.ARTIFACT_LV); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { lv: newLv }); - if(artifact.hid > 0) { - await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_LV, roleId, serverId, sid, artifact.hid, {}, { artifact }); - } - await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_LV, { artifacts: [artifact] }); - - return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) }); - } - - public async compose(msg: { seqId: number, material: number[], generalItems: {id: number, count: number}[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { seqId, material = [], generalItems = [] } = msg; - - let seqIds = [seqId, ...material]; - let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); - if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - let artifactMap = arrToMap(artifacts, obj => obj.seqId); - - let originArtifact = artifactMap.get(seqId); - if(!originArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let dicOriginArtifact = getArtifactWithQuality(originArtifact.artifactId); - if(!dicOriginArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - let dicNextArtifact = getNextArtifact(originArtifact.artifactId); - if(!dicNextArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 狗粮处理 - let remainCnt = dicNextArtifact.materialCnt, cost: ItemInter[] = [], delSeqIds: number[] = []; - for(let seqId of material) { - let artifact = artifactMap.get(seqId); - let res = checkArtifactCanCompose(originArtifact.artifactId, artifact); - if(res.code != 0) return resResult(res); - cost.push({ seqId, id: artifact.id }); - delSeqIds.push(seqId); - remainCnt--; - } - // 通用道具 - if(dicNextArtifact.materialGroup == 0 && remainCnt > 0) { // 可使用材料代替,不是必须同名的那种 - let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifact.materialId); - if(!dicMaterialArtifactQuality) return resResult(STATUS.DIC_DATA_NOT_FOUND); - for(let { id, count } of dicMaterialArtifactQuality.generalItem) { - let needCount = count * remainCnt; - let chosenItem = generalItems.find(cur => cur.id == id); - if(!chosenItem || chosenItem.count < needCount) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - cost.push({ id, count: needCount }); - } - remainCnt = 0; - } - if(remainCnt > 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ARTIFACT_QUALITY); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { quality, qualityStage, artifactId, goodId } = dicNextArtifact; - originArtifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id: goodId }); - if(originArtifact.hid > 0) { - let hero = await HeroModel.findByHidAndRole(originArtifact.hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_QUALITY, roleId, serverId, sid, originArtifact.hid, {}, { artifact: originArtifact, job: hero.job, skinId: hero.skinId }); - await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts: [originArtifact] }); - } - await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: 1 }); - - return resResult(STATUS.SUCCESS, { delSeqIds, artifact: new ArtifactParam(originArtifact) }); - } - - public async composeAll(msg: {}, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let taskCount = 0; - const batchCode = genCode(10), delSeqIds: (number|string)[] = []; - for(let [_, { quality, canComposeAll }] of gameData.artifactQualityById) { - if(!canComposeAll) continue; - - let artifacts = await ArtifactModel.findByQuality(roleId, quality); - let used: (number|string)[] = [], materials: ItemInter[] = [], target: ArtifactModelUpdate[] = []; - for(let artifact of artifacts) { - if(used.indexOf(artifact.seqId) > -1) continue; - let tmpUsed: (number|string)[] = [artifact.seqId]; - let dicNextArtifact = getNextArtifact(artifact.artifactId); - if(!dicNextArtifact) continue; - - let { materialCnt, goodId: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage } = dicNextArtifact; - let canUseMaterial: ItemInter[] = []; - for(let i = 0; i < materialCnt; i++) { - for(let _artifact of artifacts) { - if(used.indexOf(_artifact.seqId) > -1 || tmpUsed.indexOf(_artifact.seqId) > -1) continue; - let res = checkArtifactCanCompose(artifact.artifactId, _artifact); - if(res.code != 0) continue; - canUseMaterial.push({ id: _artifact.id, seqId: _artifact.seqId }); - tmpUsed.push(_artifact.seqId); - break; - } - } - if(materialCnt == canUseMaterial.length) { - used.push(...tmpUsed); - materials.push(...canUseMaterial); - delSeqIds.push(...canUseMaterial.map(cur => cur.seqId)); - target.push({ seqId: artifact.seqId, id: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage }); - taskCount++; - } - - } - - let result = await handleCost(roleId, sid, materials, ITEM_CHANGE_REASON.ARTIFACT_QUALITY); - if (!result) continue; - for(let { seqId, quality, qualityStage, artifactId, id} of target) { - await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id, batchCode }); - } - } - let artifacts = await ArtifactModel.findByBatchCode(batchCode); - await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: taskCount }); - - return resResult(STATUS.SUCCESS, { delSeqIds, artifacts: artifacts.map(artifact => new ArtifactParam(artifact))}); - } - - public async transfer(msg: { seqId: number, type: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - let { seqId, type } = msg; - - let artifact = await ArtifactModel.findbySeqId(roleId, seqId); - if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let dicArtifact = gameData.artifact.get(artifact.artifactId); - if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(dicArtifact.type == type) return resResult(STATUS.ARTIFACT_TYPE_SAME); - - let dicTargetArtifact = getArtifactByGidAndType(dicArtifact.goodId, type); - if(!dicTargetArtifact) return resResult(STATUS.ARTIFACT_TYPE_ERR); - - let consume = parseGoodStr(ARTIFACT.TRANSFER_COST); - let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_TRANSFER); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - - let { artifactId, goodId } = dicTargetArtifact; - artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { artifactId, id: goodId }); - if(artifact.hid > 0) { - let hero = await HeroModel.findByHidAndRole(artifact.hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER, roleId, serverId, sid, artifact.hid, {}, { artifact, job: hero.job, skinId: hero.skinId }); - } - - return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) }); - } - - public async previewRebuild(msg: { seqIds: number[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let { seqIds } = msg; - - let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); - if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let consumes = getRebuildConsume(artifacts); - - return resResult(STATUS.SUCCESS, { consumes }); - } - - public async rebuild(msg: { seqIds: number[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let serverId: number = session.get('serverId'); - let sid: string = session.get('sid'); - let { seqIds } = msg; - - let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); - if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let rebuildConsumes = getRebuildConsume(artifacts); - if(rebuildConsumes.length <= 0) return resResult(STATUS.ARTIFACT_HAS_NO_STRENGTH); - - let consume = parseGoodStr(ARTIFACT.REBUILD_COST); - let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_REBUILD); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let returnArtifact: ArtifactParam[] = []; - for(let artifact of artifacts) { - let dicArtifactZero = getArtifactStageZero(artifact.artifactId); - if(!dicArtifactZero) continue; - let { artifactId, goodId, quality, qualityStage } = dicArtifactZero; - let result = await ArtifactModel.updateInfoBySeqId(roleId, artifact.seqId, { artifactId, id: goodId, quality, qualityStage, lv: 0 }); - if(result && result.hid > 0) { - let hero = await HeroModel.findByHidAndRole(result.hid, roleId); - await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_REBUILD, roleId, serverId, sid, result.hid, {}, { artifact: result, skinId: hero.skinId, job: hero.job }); - } - returnArtifact.push(new ArtifactParam(result)); - } - let goods = await addItems(roleId, roleName, sid, rebuildConsumes, ITEM_CHANGE_REASON.ARTIFACT_REBUILD); - return resResult(STATUS.SUCCESS, { artifacts: returnArtifact, goods }); - } - - public async decompose(msg: { seqIds: number[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let roleName: string = session.get('roleName'); - - let { seqIds } = msg; - if(seqIds.length > BAG.BAG_ARTIFACT_DECOMPOSE_UPLIMITED) { - return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT); - } - let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); - if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); - - let cost: ItemInter[] = [], add: ItemInter[] = [], delSeqIds: (number|string)[] = []; - for(let artifact of artifacts) { - if(artifact.hid > 0 || hasArtifactStrength(artifact)) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE); - let dicArtifact = getArtifactWithQuality(artifact.artifactId); - if(!dicArtifact || !dicArtifact.canDecompose) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE); - let dicZeroArtifact = getArtifactStageZero(artifact.artifactId); - if(!dicZeroArtifact) continue; - add.push(...dicZeroArtifact.generalItem); - - cost.push({ seqId: artifact.seqId, id: artifact.id, count: 1 }); - delSeqIds.push(artifact.seqId); - } - - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); // 删掉装备 - if(!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let result = await addItems(roleId, roleName, sid, add, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); - return resResult(STATUS.SUCCESS, { delSeqIds, goods: combineItems(result) }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts"; +import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from "@db/Artifact"; +import { HeroModel } from "@db/Hero"; +import { ArtifactParam } from "@domain/roleField/hero"; +import { gameData, getArtifactByGidAndType, getArtifactStageZero, getArtifactWithQuality, getDicArtifactLvByPlanId, getNextArtifact } from "@pubUtils/data"; +import { ARTIFACT, BAG } from "@pubUtils/dicParam"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; + +import { resResult, parseGoodStr, arrToMap, genCode } from "@pubUtils/util"; +import { checkArtifactCanCompose, getRebuildConsume, hasArtifactStrength } from "../../../services/equipService"; +import { calculateCeWithHero } from "../../../services/playerCeService"; +import { CheckMeterial } from "../../../services/role/checkMaterial"; +import { addItems, handleCost } from "../../../services/role/rewardService"; +import { combineItems } from "../../../services/role/util"; +import { checkTask } from "../../../services/task/taskService"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ArtifactHandler(app); +} + +export class ArtifactHandler { + + constructor(private app: Application) { + } + + public async putOn(msg: { seqId: number, hid: number, isExtendLv: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { seqId, hid, isExtendLv } = msg; + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId); + if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + if(chosenArtifact.lv > 0) isExtendLv = false; + + let artifacts: ArtifactModelType[] = []; + let artifactOfHero = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; // 原本自己的天晶石 + let targetLv = artifactOfHero?.lv, returnCoin: RewardInter[] = []; + let dicChosenArtifact = getArtifactWithQuality(chosenArtifact.artifactId); + if(!dicChosenArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if(isExtendLv && targetLv > dicChosenArtifact.maxLv) { + for(let lv = dicChosenArtifact.maxLv + 1; lv <= targetLv; lv++) { + let dicArtifactLv = getDicArtifactLvByPlanId(dicChosenArtifact.lvAttrPlan, lv); + if(!dicArtifactLv) break; + returnCoin.push(...dicArtifactLv.consumes); + } + targetLv = dicChosenArtifact.maxLv; + }; + + if(artifactOfHero) { // 更新自己的天晶石 + artifactOfHero = await ArtifactModel.putOnOrOff(roleId, artifactOfHero.seqId, 0, isExtendLv? 0: undefined); + if(artifactOfHero) artifacts.push(artifactOfHero); + } + if(chosenArtifact.hid != 0) { + let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者 + if(heroOfChosenArtifact) { + await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 对方卸下 + } + } + chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, hid, isExtendLv? targetLv: undefined); + if(chosenArtifact) artifacts.push(chosenArtifact); + await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, serverId, sid, hid, { artifact: seqId }, { artifact: chosenArtifact, job: hero.job, skinId: hero.skinId }); // 把我的换给他 + await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts }); + + let goods = returnCoin.length > 0? await addItems(roleId, roleName, sid, combineItems(returnCoin), ITEM_CHANGE_REASON.ARTIFACT_LV_RETURN): undefined; + + return resResult(STATUS.SUCCESS, { artifacts: artifacts.map(artifact => new ArtifactParam(artifact)), goods }); + } + + public async putOff(msg: { seqId: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { seqId } = msg; + + let chosenArtifact = await ArtifactModel.findbySeqId(roleId, seqId); + if(!chosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let heroOfChosenArtifact = await HeroModel.findByHidAndRole(chosenArtifact.hid, roleId); // 我想要的宝物的原持有者 + if(!heroOfChosenArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_EQUIPED); + + chosenArtifact = await ArtifactModel.putOnOrOff(roleId, seqId, 0); + let artifacts: ArtifactParam[] = [new ArtifactParam(chosenArtifact)]; + + await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT, roleId, serverId, sid, heroOfChosenArtifact.hid, { artifact: 0 }); // 把我的换给他 + + return resResult(STATUS.SUCCESS, { artifacts }); + } + + public async lvUp(msg: { seqId: number, isOneClick: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { seqId, isOneClick } = msg; + + let artifact = await ArtifactModel.findbySeqId(roleId, seqId); + if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let dicArtifact = getArtifactWithQuality(artifact.artifactId); + if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if(artifact.lv >= dicArtifact.maxLv) return resResult(STATUS.ARTIFACT_LV_MAX); + let toLv = isOneClick? artifact.lv + 5: artifact.lv + 1; + if(toLv > dicArtifact.maxLv) toLv = dicArtifact.maxLv; + let newLv = artifact.lv; + + let check = new CheckMeterial(roleId); + for (let lv = artifact.lv + 1; lv <= toLv; lv++) { + let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); + if(!dicArtifactLv) break; + let isEnough = await check.decrease(dicArtifactLv.consumes); + if(!isEnough) break; // 消耗不足 + newLv = lv; + } + if(newLv == artifact.lv) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.ARTIFACT_LV); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { lv: newLv }); + if(artifact.hid > 0) { + await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_LV, roleId, serverId, sid, artifact.hid, {}, { artifact }); + } + await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_LV, { artifacts: [artifact] }); + + return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) }); + } + + public async compose(msg: { seqId: number, material: number[], generalItems: {id: number, count: number}[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { seqId, material = [], generalItems = [] } = msg; + + let seqIds = [seqId, ...material]; + let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); + if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + let artifactMap = arrToMap(artifacts, obj => obj.seqId); + + let originArtifact = artifactMap.get(seqId); + if(!originArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let dicOriginArtifact = getArtifactWithQuality(originArtifact.artifactId); + if(!dicOriginArtifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + let dicNextArtifact = getNextArtifact(originArtifact.artifactId); + if(!dicNextArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 狗粮处理 + let remainCnt = dicNextArtifact.materialCnt, cost: ItemInter[] = [], delSeqIds: number[] = []; + for(let seqId of material) { + let artifact = artifactMap.get(seqId); + let res = checkArtifactCanCompose(originArtifact.artifactId, artifact); + if(res.code != 0) return resResult(res); + cost.push({ seqId, id: artifact.id }); + delSeqIds.push(seqId); + remainCnt--; + } + // 通用道具 + if(dicNextArtifact.materialGroup == 0 && remainCnt > 0) { // 可使用材料代替,不是必须同名的那种 + let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifact.materialId); + if(!dicMaterialArtifactQuality) return resResult(STATUS.DIC_DATA_NOT_FOUND); + for(let { id, count } of dicMaterialArtifactQuality.generalItem) { + let needCount = count * remainCnt; + let chosenItem = generalItems.find(cur => cur.id == id); + if(!chosenItem || chosenItem.count < needCount) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + cost.push({ id, count: needCount }); + } + remainCnt = 0; + } + if(remainCnt > 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ARTIFACT_QUALITY); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { quality, qualityStage, artifactId, goodId } = dicNextArtifact; + originArtifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id: goodId }); + if(originArtifact.hid > 0) { + let hero = await HeroModel.findByHidAndRole(originArtifact.hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_QUALITY, roleId, serverId, sid, originArtifact.hid, {}, { artifact: originArtifact, job: hero.job, skinId: hero.skinId }); + await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_QUALITY_EQUIP, { artifacts: [originArtifact] }); + } + await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: 1 }); + + return resResult(STATUS.SUCCESS, { delSeqIds, artifact: new ArtifactParam(originArtifact) }); + } + + public async composeAll(msg: {}, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let taskCount = 0; + const batchCode = genCode(10), delSeqIds: (number|string)[] = []; + for(let [_, { quality, canComposeAll }] of gameData.artifactQualityById) { + if(!canComposeAll) continue; + + let artifacts = await ArtifactModel.findByQuality(roleId, quality); + let used: (number|string)[] = [], materials: ItemInter[] = [], target: ArtifactModelUpdate[] = []; + for(let artifact of artifacts) { + if(used.indexOf(artifact.seqId) > -1) continue; + let tmpUsed: (number|string)[] = [artifact.seqId]; + let dicNextArtifact = getNextArtifact(artifact.artifactId); + if(!dicNextArtifact) continue; + + let { materialCnt, goodId: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage } = dicNextArtifact; + let canUseMaterial: ItemInter[] = []; + for(let i = 0; i < materialCnt; i++) { + for(let _artifact of artifacts) { + if(used.indexOf(_artifact.seqId) > -1 || tmpUsed.indexOf(_artifact.seqId) > -1) continue; + let res = checkArtifactCanCompose(artifact.artifactId, _artifact); + if(res.code != 0) continue; + canUseMaterial.push({ id: _artifact.id, seqId: _artifact.seqId }); + tmpUsed.push(_artifact.seqId); + break; + } + } + if(materialCnt == canUseMaterial.length) { + used.push(...tmpUsed); + materials.push(...canUseMaterial); + delSeqIds.push(...canUseMaterial.map(cur => cur.seqId)); + target.push({ seqId: artifact.seqId, id: nextGid, artifactId: nextArtId, quality: nextQuality, qualityStage: nextStage }); + taskCount++; + } + + } + + let result = await handleCost(roleId, sid, materials, ITEM_CHANGE_REASON.ARTIFACT_QUALITY); + if (!result) continue; + for(let { seqId, quality, qualityStage, artifactId, id} of target) { + await ArtifactModel.updateInfoBySeqId(roleId, seqId, { quality, qualityStage, artifactId, id, batchCode }); + } + } + let artifacts = await ArtifactModel.findByBatchCode(batchCode); + await checkTask(serverId, roleId, sid, TASK_TYPE.ARTIFACT_COMPOSE, { count: taskCount }); + + return resResult(STATUS.SUCCESS, { delSeqIds, artifacts: artifacts.map(artifact => new ArtifactParam(artifact))}); + } + + public async transfer(msg: { seqId: number, type: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + let { seqId, type } = msg; + + let artifact = await ArtifactModel.findbySeqId(roleId, seqId); + if(!artifact) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let dicArtifact = gameData.artifact.get(artifact.artifactId); + if(!dicArtifact) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(dicArtifact.type == type) return resResult(STATUS.ARTIFACT_TYPE_SAME); + + let dicTargetArtifact = getArtifactByGidAndType(dicArtifact.goodId, type); + if(!dicTargetArtifact) return resResult(STATUS.ARTIFACT_TYPE_ERR); + + let consume = parseGoodStr(ARTIFACT.TRANSFER_COST); + let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_TRANSFER); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + + let { artifactId, goodId } = dicTargetArtifact; + artifact = await ArtifactModel.updateInfoBySeqId(roleId, seqId, { artifactId, id: goodId }); + if(artifact.hid > 0) { + let hero = await HeroModel.findByHidAndRole(artifact.hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER, roleId, serverId, sid, artifact.hid, {}, { artifact, job: hero.job, skinId: hero.skinId }); + } + + return resResult(STATUS.SUCCESS, { artifact: new ArtifactParam(artifact) }); + } + + public async previewRebuild(msg: { seqIds: number[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let { seqIds } = msg; + + let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); + if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let consumes = getRebuildConsume(artifacts); + + return resResult(STATUS.SUCCESS, { consumes }); + } + + public async rebuild(msg: { seqIds: number[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let serverId: number = session.get('serverId'); + let sid: string = session.get('sid'); + let { seqIds } = msg; + + let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); + if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let rebuildConsumes = getRebuildConsume(artifacts); + if(rebuildConsumes.length <= 0) return resResult(STATUS.ARTIFACT_HAS_NO_STRENGTH); + + let consume = parseGoodStr(ARTIFACT.REBUILD_COST); + let result = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.ARTIFACT_REBUILD); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let returnArtifact: ArtifactParam[] = []; + for(let artifact of artifacts) { + let dicArtifactZero = getArtifactStageZero(artifact.artifactId); + if(!dicArtifactZero) continue; + let { artifactId, goodId, quality, qualityStage } = dicArtifactZero; + let result = await ArtifactModel.updateInfoBySeqId(roleId, artifact.seqId, { artifactId, id: goodId, quality, qualityStage, lv: 0 }); + if(result && result.hid > 0) { + let hero = await HeroModel.findByHidAndRole(result.hid, roleId); + await calculateCeWithHero(HERO_SYSTEM_TYPE.ARTIFACT_REBUILD, roleId, serverId, sid, result.hid, {}, { artifact: result, skinId: hero.skinId, job: hero.job }); + } + returnArtifact.push(new ArtifactParam(result)); + } + let goods = await addItems(roleId, roleName, sid, rebuildConsumes, ITEM_CHANGE_REASON.ARTIFACT_REBUILD); + return resResult(STATUS.SUCCESS, { artifacts: returnArtifact, goods }); + } + + public async decompose(msg: { seqIds: number[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let roleName: string = session.get('roleName'); + + let { seqIds } = msg; + if(seqIds.length > BAG.BAG_ARTIFACT_DECOMPOSE_UPLIMITED) { + return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT); + } + let artifacts = await ArtifactModel.findbySeqIds(roleId, seqIds); + if (artifacts.length < seqIds.length) return resResult(STATUS.ARTIFACT_IS_NOT_FIND); + + let cost: ItemInter[] = [], add: ItemInter[] = [], delSeqIds: (number|string)[] = []; + for(let artifact of artifacts) { + if(artifact.hid > 0 || hasArtifactStrength(artifact)) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE); + let dicArtifact = getArtifactWithQuality(artifact.artifactId); + if(!dicArtifact || !dicArtifact.canDecompose) return resResult(STATUS.ARTIFACT_CANNOT_DECOMPOSE); + let dicZeroArtifact = getArtifactStageZero(artifact.artifactId); + if(!dicZeroArtifact) continue; + add.push(...dicZeroArtifact.generalItem); + + cost.push({ seqId: artifact.seqId, id: artifact.id, count: 1 }); + delSeqIds.push(artifact.seqId); + } + + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); // 删掉装备 + if(!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let result = await addItems(roleId, roleName, sid, add, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); + return resResult(STATUS.SUCCESS, { delSeqIds, goods: combineItems(result) }); + } +} + diff --git a/game-server/app/servers/role/handler/authorBookHandler.ts b/game-server/app/servers/role/handler/authorBookHandler.ts index a3b53a31a..e0a3eef52 100644 --- a/game-server/app/servers/role/handler/authorBookHandler.ts +++ b/game-server/app/servers/role/handler/authorBookHandler.ts @@ -1,183 +1,184 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts"; -import { gameData, getDicAuthorBookSub } from "../../../pubUtils/data"; -import { RewardInter } from "../../../pubUtils/interface"; - -import { resResult } from "../../../pubUtils/util"; -import { calculateCeWithRole } from "../../../services/playerCeService"; -import { CheckMeterial } from "../../../services/role/checkMaterial"; -import { addItems, handleCost } from "../../../services/role/rewardService"; -import { combineItems } from "../../../services/role/util"; -import { AuthorBookModel } from "../../../db/AuthorBook"; -import { checkAuthorBookLimit, replaceAuthorBooks } from "../../../services/roleService"; -import { checkTask } from "../../../services/task/taskService"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new AuthorsBookHandler(app); -} - -export class AuthorsBookHandler { - - constructor(private app: Application) { - } - - public async starUp(msg: { bookId: number, subId: number, star: number, useItem: boolean }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - - const { bookId, subId, star, useItem } = msg; - let allAuthorBooks = await AuthorBookModel.findByRoleId(roleId); - let authorBookData = allAuthorBooks.find(authorBook => authorBook.bookId == bookId); - let starInData = authorBookData?.authors?.find(cur => cur.subId == subId)?.star??0; - if(star != starInData) return resResult(STATUS.ACCESS_BUSY); - - let dicAuthorsBookSub = getDicAuthorBookSub(bookId, subId, star + 1); - if(!dicAuthorsBookSub) return resResult(STATUS.AUTHOR_BOOK_SUB_MAX); - - // 是否解锁(进度解锁) - if(!checkAuthorBookLimit(allAuthorBooks, bookId)) return resResult(STATUS.AUTHOR_BOOK_LOCK); - // 英灵是否够 - let check = new CheckMeterial(roleId); - let isEnough = await check.decreaseItemsContinue(dicAuthorsBookSub.spirits); - let useItemCnt = 0; - if(useItem) { // 使用英灵石代替 - if(!isEnough) { - let notEnoughItems = check.getNotEnoughItems(); - let replaceItems: RewardInter[] = []; - for(let [ id, count ] of notEnoughItems) { - let dicSpirit = gameData.spirit.get(id); - if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); // 应该是表填错,正常情况不可能出现 - - for(let item of dicSpirit.composeItem) { - replaceItems.push({ id: item.id, count: item.count * count }); - useItemCnt += item.count * count; - } - } - isEnough = await check.decreaseItemsContinue(replaceItems); - } - } - - if(!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.AUTHOR_BOOK_STAR_UP); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - // 升星 - authorBookData = await AuthorBookModel.upStar(roleId, bookId, subId, star, dicAuthorsBookSub.value, gameData.authorBookSubs.get(bookId)||[]); - if(!authorBookData) { - // 防并发问题 - await addItems(roleId, roleName, sid, consumes, ITEM_CHANGE_REASON.AUTHOR_BOOK_STAR_RETURN); - return resResult(STATUS.ACCESS_BUSY); - } - // 计算战力更新 - - await calculateCeWithRole(HERO_SYSTEM_TYPE.AUTHOR_BOOK_STAR, roleId, serverId, sid, {}, { authorBooks: replaceAuthorBooks(allAuthorBooks, authorBookData), bookId, subId }); - - let curAuthorBook = authorBookData.authors?.find(cur => cur.subId == subId); - let maxProgress = gameData.authorBookMaxProgress.get(bookId)??0; - - await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_AUTHOR, { authorProgress: await AuthorBookModel.findProgressByRoleId(roleId) }); - - return resResult(STATUS.SUCCESS, { - bookId, - subId, - star: curAuthorBook?.star??0, - progress: authorBookData.progress, - maxProgress, - useItemCnt - }); - } - - // 重置条目 - public async resetAuthor(msg: { bookId: number, subId: number, star: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - - const { bookId, subId, star } = msg; - let allAuthorBooks = await AuthorBookModel.findByRoleId(roleId); - let authorBookData = allAuthorBooks.find(authorBook => authorBook.bookId == bookId); - if(!authorBookData) return resResult(STATUS.ACCESS_BUSY) - let starInData = authorBookData?.authors?.find(cur => cur.subId == subId)?.star??0; - if(star != starInData) return resResult(STATUS.ACCESS_BUSY); - - let progress = 0, spirits: RewardInter[] = []; - for(let i = 1; i <= star; i++) { - let dicAuthorsBookSub = getDicAuthorBookSub(bookId, subId, i); - if(!dicAuthorsBookSub) return resResult(STATUS.DIC_DATA_NOT_FOUND); - progress += dicAuthorsBookSub.value; - spirits.push(...dicAuthorsBookSub.spirits); - } - // 重置诸子列传 - authorBookData = await AuthorBookModel.resetSub(roleId, bookId, subId, star, -progress); - if(!authorBookData) return resResult(STATUS.ACCESS_BUSY); - - let goods = await addItems(roleId, roleName, sid, combineItems(spirits), ITEM_CHANGE_REASON.AUTHOR_BOOK_SUB_RESET); - - // 计算战力更新 - await calculateCeWithRole(HERO_SYSTEM_TYPE.AUTHOR_BOOK_SUB_RESET, roleId, serverId, sid, {}, { authorBooks: replaceAuthorBooks(allAuthorBooks, authorBookData), bookId, subId }); - - let curAuthorBook = authorBookData.authors?.find(cur => cur.subId == subId); - let maxProgress = gameData.authorBookMaxProgress.get(bookId)??0; - - await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_AUTHOR, { authorProgress: await AuthorBookModel.findProgressByRoleId(roleId) }); - - return resResult(STATUS.SUCCESS, { - bookId, - subId, - star: curAuthorBook?.star??0, - progress: authorBookData.progress, - maxProgress, - goods - }); - - } - - // 买英灵 - public async buySpirit(msg: { id: number, count: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let roleName: string = session.get('roleName'); - - const { id, count } = msg; - let dicSpirit = gameData.spirit.get(id); - if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let consumes = dicSpirit.composeItem.map(cur => ({ id: cur.id, count: cur.count * count })); - let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.BUY_SPIRIT); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let reward = [{ id, count }]; - let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.BUY_SPIRIT); - - return resResult(STATUS.SUCCESS, { goods }); - } - - public async decomposeSpirit(msg: { spirits: { id: number, count: number }[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let roleName: string = session.get('roleName'); - - const { spirits = [] } = msg; - let rewards: RewardInter[] = []; - for(let { id, count } of spirits) { - let dicSpirit = gameData.spirit.get(id); - if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); - for(let item of dicSpirit.decomposeItem) { - rewards.push({ id: item.id, count: item.count * count }); - } - } - - let consumes = spirits; - let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.DECOMPOSE_SPIRIT); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.DECOMPOSE_SPIRIT); - - return resResult(STATUS.SUCCESS, { goods }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts"; +import { gameData, getDicAuthorBookSub } from "@pubUtils/data"; +import { RewardInter } from "@pubUtils/interface"; + +import { resResult } from "@pubUtils/util"; +import { calculateCeWithRole } from "../../../services/playerCeService"; +import { CheckMeterial } from "../../../services/role/checkMaterial"; +import { addItems, handleCost } from "../../../services/role/rewardService"; +import { combineItems } from "../../../services/role/util"; +import { AuthorBookModel } from "@db/AuthorBook"; +import { checkAuthorBookLimit, replaceAuthorBooks } from "../../../services/roleService"; +import { checkTask } from "../../../services/task/taskService"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new AuthorsBookHandler(app); +} + +export class AuthorsBookHandler { + + constructor(private app: Application) { + } + + public async starUp(msg: { bookId: number, subId: number, star: number, useItem: boolean }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + + const { bookId, subId, star, useItem } = msg; + let allAuthorBooks = await AuthorBookModel.findByRoleId(roleId); + let authorBookData = allAuthorBooks.find(authorBook => authorBook.bookId == bookId); + let starInData = authorBookData?.authors?.find(cur => cur.subId == subId)?.star??0; + if(star != starInData) return resResult(STATUS.ACCESS_BUSY); + + let dicAuthorsBookSub = getDicAuthorBookSub(bookId, subId, star + 1); + if(!dicAuthorsBookSub) return resResult(STATUS.AUTHOR_BOOK_SUB_MAX); + + // 是否解锁(进度解锁) + if(!checkAuthorBookLimit(allAuthorBooks, bookId)) return resResult(STATUS.AUTHOR_BOOK_LOCK); + // 英灵是否够 + let check = new CheckMeterial(roleId); + let isEnough = await check.decreaseItemsContinue(dicAuthorsBookSub.spirits); + let useItemCnt = 0; + if(useItem) { // 使用英灵石代替 + if(!isEnough) { + let notEnoughItems = check.getNotEnoughItems(); + let replaceItems: RewardInter[] = []; + for(let [ id, count ] of notEnoughItems) { + let dicSpirit = gameData.spirit.get(id); + if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); // 应该是表填错,正常情况不可能出现 + + for(let item of dicSpirit.composeItem) { + replaceItems.push({ id: item.id, count: item.count * count }); + useItemCnt += item.count * count; + } + } + isEnough = await check.decreaseItemsContinue(replaceItems); + } + } + + if(!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.AUTHOR_BOOK_STAR_UP); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + // 升星 + authorBookData = await AuthorBookModel.upStar(roleId, bookId, subId, star, dicAuthorsBookSub.value, gameData.authorBookSubs.get(bookId)||[]); + if(!authorBookData) { + // 防并发问题 + await addItems(roleId, roleName, sid, consumes, ITEM_CHANGE_REASON.AUTHOR_BOOK_STAR_RETURN); + return resResult(STATUS.ACCESS_BUSY); + } + // 计算战力更新 + + await calculateCeWithRole(HERO_SYSTEM_TYPE.AUTHOR_BOOK_STAR, roleId, serverId, sid, {}, { authorBooks: replaceAuthorBooks(allAuthorBooks, authorBookData), bookId, subId }); + + let curAuthorBook = authorBookData.authors?.find(cur => cur.subId == subId); + let maxProgress = gameData.authorBookMaxProgress.get(bookId)??0; + + await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_AUTHOR, { authorProgress: await AuthorBookModel.findProgressByRoleId(roleId) }); + + return resResult(STATUS.SUCCESS, { + bookId, + subId, + star: curAuthorBook?.star??0, + progress: authorBookData.progress, + maxProgress, + useItemCnt + }); + } + + // 重置条目 + public async resetAuthor(msg: { bookId: number, subId: number, star: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + + const { bookId, subId, star } = msg; + let allAuthorBooks = await AuthorBookModel.findByRoleId(roleId); + let authorBookData = allAuthorBooks.find(authorBook => authorBook.bookId == bookId); + if(!authorBookData) return resResult(STATUS.ACCESS_BUSY) + let starInData = authorBookData?.authors?.find(cur => cur.subId == subId)?.star??0; + if(star != starInData) return resResult(STATUS.ACCESS_BUSY); + + let progress = 0, spirits: RewardInter[] = []; + for(let i = 1; i <= star; i++) { + let dicAuthorsBookSub = getDicAuthorBookSub(bookId, subId, i); + if(!dicAuthorsBookSub) return resResult(STATUS.DIC_DATA_NOT_FOUND); + progress += dicAuthorsBookSub.value; + spirits.push(...dicAuthorsBookSub.spirits); + } + // 重置诸子列传 + authorBookData = await AuthorBookModel.resetSub(roleId, bookId, subId, star, -progress); + if(!authorBookData) return resResult(STATUS.ACCESS_BUSY); + + let goods = await addItems(roleId, roleName, sid, combineItems(spirits), ITEM_CHANGE_REASON.AUTHOR_BOOK_SUB_RESET); + + // 计算战力更新 + await calculateCeWithRole(HERO_SYSTEM_TYPE.AUTHOR_BOOK_SUB_RESET, roleId, serverId, sid, {}, { authorBooks: replaceAuthorBooks(allAuthorBooks, authorBookData), bookId, subId }); + + let curAuthorBook = authorBookData.authors?.find(cur => cur.subId == subId); + let maxProgress = gameData.authorBookMaxProgress.get(bookId)??0; + + await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_AUTHOR, { authorProgress: await AuthorBookModel.findProgressByRoleId(roleId) }); + + return resResult(STATUS.SUCCESS, { + bookId, + subId, + star: curAuthorBook?.star??0, + progress: authorBookData.progress, + maxProgress, + goods + }); + + } + + // 买英灵 + public async buySpirit(msg: { id: number, count: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let roleName: string = session.get('roleName'); + + const { id, count } = msg; + let dicSpirit = gameData.spirit.get(id); + if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let consumes = dicSpirit.composeItem.map(cur => ({ id: cur.id, count: cur.count * count })); + let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.BUY_SPIRIT); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let reward = [{ id, count }]; + let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.BUY_SPIRIT); + + return resResult(STATUS.SUCCESS, { goods }); + } + + public async decomposeSpirit(msg: { spirits: { id: number, count: number }[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let roleName: string = session.get('roleName'); + + const { spirits = [] } = msg; + let rewards: RewardInter[] = []; + for(let { id, count } of spirits) { + let dicSpirit = gameData.spirit.get(id); + if(!dicSpirit) return resResult(STATUS.DIC_DATA_NOT_FOUND); + for(let item of dicSpirit.decomposeItem) { + rewards.push({ id: item.id, count: item.count * count }); + } + } + + let consumes = spirits; + let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.DECOMPOSE_SPIRIT); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.DECOMPOSE_SPIRIT); + + return resResult(STATUS.SUCCESS, { goods }); + } +} + diff --git a/game-server/app/servers/role/handler/equipHandler.ts b/game-server/app/servers/role/handler/equipHandler.ts index d92189552..24e6e37dc 100644 --- a/game-server/app/servers/role/handler/equipHandler.ts +++ b/game-server/app/servers/role/handler/equipHandler.ts @@ -1,854 +1,855 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE, CONSUME_TYPE, RESONANCE } from "../../../consts"; -import { ItemInter, RewardInter } from "../../../pubUtils/interface"; - -import { resResult, parseGoodStr } from "../../../pubUtils/util"; -import { addItems, getJewelRandSe, handleCost } from "../../../services/role/rewardService"; -import { HeroModel, EPlace } from "../../../db/Hero"; -import { gameData, getEquipByJobClassAndEPlace, getNextEquipQuality, getEquipStarIdByEquipId, getNextEquipStar } from "../../../pubUtils/data"; -import { BAG, EQUIP } from "../../../pubUtils/dicParam"; -import { getRandSeResult, updateEplace, updateEplaces, checkJewelCanPutOnEquip, updateStone, checkStoneCanPutOnEquip, isLocked } from "../../../services/equipService"; - -import { clone, isNumber, max, min, pick } from 'underscore'; -import { JewelModel, RandSe } from "../../../db/Jewel"; -import { checkTaskInComposeEquip, checkTaskInEquipLvUp, checkTaskInComposeStone, checkTaskInEquipReset, checkTaskInEquipQuench, checkTaskInEquipQualityUp, checkTaskInEquipStarUp, checkTaskInPutJewel, checkTaskInPutStone } from '../../../services/task/taskService'; -import { pushEquipQualityMax, pushEquipStarMax } from "../../../services/sysChatService"; -import { addConsumeToHero } from "../../../services/roleService"; -import { CheckMeterial, getComposeStoneCostAndAdd, getCurItem } from "../../../services/role/checkMaterial"; -import { combineItems } from "../../../services/role/util"; -import { calculateCeWithHero } from "../../../services/playerCeService"; -import { ItemModel } from "../../../db/Item"; -import { index } from "typegoose"; -import { all } from "bluebird"; -import { getResonanceDataMap } from "../../../services/role/resonanceService"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new EquipHandler(app); -} - -export class EquipHandler { - - constructor(private app: Application) { - } - - public async composeEquip(msg: { hid: number, ePlaceId: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { hid, ePlaceId } = msg; - if (!isNumber(ePlaceId) || ePlaceId > 4 || ePlaceId < 1) return resResult(STATUS.WRONG_PARMS); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(equip => equip.id == ePlaceId); - if (curEquip) return resResult(STATUS.EQUIP_HAS_COMPOSE); - - let dicHero = gameData.hero.get(hero.skinId); - let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, ePlaceId); - if (!dicEquip) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let consumeResult = await handleCost(roleId, sid, dicEquip.composeMaterial, ITEM_CHANGE_REASON.EQUIP_COMPOSE); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let newEquip = new EPlace(ePlaceId, dicEquip.id); - let newEplace = [...oldEplace, newEquip]; - - let update = { - ePlace: newEplace, - consumes: addConsumeToHero(hero.consumes, dicEquip.composeMaterial), - } - - await calculateCeWithHero(HERO_SYSTEM_TYPE.COMPOSE_EQUIP, roleId, serverId, sid, hid, update, { ePlaceId, skinId: hero.skinId }); - await checkTaskInComposeEquip(serverId, roleId, sid, oldEplace, newEplace); - - let curHero = { - hid, - ePlace: [newEquip] - } - return resResult(STATUS.SUCCESS, { curHero }); - } - - // 装备栏强化 - public async strengthen(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - // let roleName: string = session.get('roleName'); - const serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - - let { hid, ePlaceId, isOneClick } = msg; - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - if (curEquip.lv >= hero.lv) return resResult(STATUS.ROLE_EQUIP_REACH_MAX); - let fromLv = curEquip.lv; - let toLv = isOneClick ? hero.lv : fromLv + 1; - let newLv = fromLv; - - let check = new CheckMeterial(roleId); - for (let lv = fromLv + 1; lv <= toLv; lv++) { - let dicCost = gameData.equipStrengthenCost.get(lv); - let isEnough = await check.decrease(dicCost.consume); - if (!isEnough) break; // 消耗不足 - newLv = lv; - } - if (newLv == fromLv) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STRENTHEN); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { lv: newLv }); - - let update = { - ePlace: newEplace, - consumes: addConsumeToHero(hero.consumes, consumes) - } - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, serverId, sid, hid, update, { ePlaceIds: [ePlaceId] }); - await checkTaskInEquipLvUp(serverId, roleId, sid, oldEplace, newEplace, [ePlaceId]); - - const curHero = { - hid, - ePlace: updatedEplace - } - return resResult(STATUS.SUCCESS, { curHero }); - - } - - // 装备栏一键强化至相应等级 - public async strengthenAll(msg: { hid: number, lv: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let serverId: number = session.get('serverId'); - let sid: string = session.get('sid'); - - let { hid, lv } = msg; // lv: 升到哪一级 - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let { ePlace, lv: playerLv } = hero; // 装备栏 - let fromLv = Math.min(...ePlace.map(cur => cur.lv)); // 最小的等级 - let toLv = lv < playerLv ? lv : playerLv; - - let eplaceIds = new Map(); // 更新了的装备栏id - let check = new CheckMeterial(roleId); - for (let lv = fromLv + 1; lv <= toLv; lv++) { - let isBreak = false; - for (let equip of ePlace) { - if (equip.lv >= lv) continue; - let dicCost = gameData.equipStrengthenCost.get(lv); - let isEnough = await check.decrease(dicCost.consume); - if (!isEnough) { isBreak = true; break; } // 消耗不足 - - eplaceIds.set(equip.id, { lv }); - } - if (isBreak) break; - } - - if (eplaceIds.size <= 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STRENTHEN); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { newEplace, updatedEplace } = updateEplaces(ePlace, eplaceIds); - - let update = { - ePlace: newEplace, - consumes: addConsumeToHero(hero.consumes, consumes), - } - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, serverId, sid, hid, update, { ePlaceIds: [...eplaceIds.keys()] }); - await checkTaskInEquipLvUp(serverId, roleId, sid, ePlace, newEplace, [...eplaceIds.keys()]); - - const curHero = { - hid, - ePlace: updatedEplace - } - return resResult(STATUS.SUCCESS, { curHero }); - - } - - - // 装备升品 - public async qualityUp(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - const serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - let { hid, ePlaceId, isOneClick } = msg; - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - - let nextEquipQuality = getNextEquipQuality(curEquip.equipId, curEquip.quality, curEquip.qualityStage); - if (!nextEquipQuality) return resResult(STATUS.EQUIP_QUALITY_MAX); - - let equipUpdate = { - quality: curEquip.quality, - qualityStage: curEquip.qualityStage, - } - let check = new CheckMeterial(roleId); - let count = 0; - if (isOneClick) { // 一键升到该品最高点 - if (nextEquipQuality.quality != curEquip.quality) { - return resResult(STATUS.EQUIP_QUALITYSTAGE_IS_MAX); - } - while (nextEquipQuality && nextEquipQuality.quality == curEquip.quality) { - let isEnough = await check.decrease(nextEquipQuality.consume); - if (!isEnough) break; // 消耗不足 - equipUpdate.qualityStage++; - nextEquipQuality = getNextEquipQuality(curEquip.equipId, equipUpdate.quality, equipUpdate.qualityStage); - count++; - } - } else { // 往下一阶,包括满点之后的升品 - let isEnough = await check.decrease(nextEquipQuality.consume); - if (isEnough) { - equipUpdate.quality = nextEquipQuality.quality; - equipUpdate.qualityStage = nextEquipQuality.point; - count++; - } - } - if (equipUpdate.quality == curEquip.quality && equipUpdate.qualityStage == curEquip.qualityStage) { - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_QUALITYUP); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let isUpQuality = equipUpdate.quality != curEquip.quality; - - let { newEplace, updatedEplace, newEquip } = updateEplace(oldEplace, ePlaceId, equipUpdate); - - let update = { - ePlace: newEplace, - consumes: addConsumeToHero(hero.consumes, consumes), - } - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_QUALITY, roleId, serverId, sid, hid, update, { ePlaceId }); - - await checkTaskInEquipQualityUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpQuality, count); - pushEquipQualityMax(roleId, roleName, serverId, hid, newEquip, isUpQuality); - const curHero = { - hid, - isUpQuality, - ePlace: updatedEplace - } - return resResult(STATUS.SUCCESS, { curHero }); - - } - - // 装备升星 - public async starUp(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - const serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - let { hid, ePlaceId, isOneClick } = msg; - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - let incEquipStarSum = 0; - let equipUpdate = { - star: curEquip.star, - starStage: curEquip.starStage, - } - - let check = new CheckMeterial(roleId); - let dicEquipStar = getEquipStarIdByEquipId(curEquip.equipId, curEquip.star); - if (!dicEquipStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let isUpStar = curEquip.starStage == dicEquipStar.count; - let count = 0; - - if (isUpStar) { // 升星 - if (isOneClick) { - return resResult(STATUS.EQUIP_STARSTAGE_IS_MAX); - } else { - let nextEquipStar = getNextEquipStar(curEquip.equipId, curEquip.star); - if (!nextEquipStar) return resResult(STATUS.EQUIP_STAR_MAX); - let dicEquipQualityExtra = gameData.equipQualityExtra.get(curEquip.quality); - if (!dicEquipQualityExtra || dicEquipQualityExtra.star < nextEquipStar.star) { - return resResult(STATUS.EQUIP_QUALITY_NOT_ENOUGH); - } - - let isEnough = await check.decrease(dicEquipStar.subConsume); - if (isEnough) { - equipUpdate.star = nextEquipStar.star; - equipUpdate.starStage = 0; - incEquipStarSum += equipUpdate.star - curEquip.star; - count++; - } - } - } else { // 升小点,包括一键升到满小点和升一个小点 - let toStage = isOneClick ? dicEquipStar.count : curEquip.starStage + 1; - for (let stage = curEquip.starStage + 1; stage <= toStage; stage++) { - let isEnough = await check.decrease(dicEquipStar.mainConsume); - if (!isEnough) break; // 消耗不足 - equipUpdate.starStage = stage; - count++; - } - } - - if (equipUpdate.star == curEquip.star && equipUpdate.starStage == curEquip.starStage) { - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STARUP); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let { newEplace, updatedEplace, newEquip } = updateEplace(oldEplace, ePlaceId, equipUpdate); - let update = { - ePlace: newEplace, - consumes: addConsumeToHero(hero.consumes, consumes) - } - - // console.log('### incEquipStarSum', incEquipStarSum) - let { curRole } = await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STAR, roleId, serverId, sid, hid, update, { ePlaceId, skinId: hero.skinId, roleIncUpdate: { equipStarSum: incEquipStarSum } }); - - checkTaskInEquipStarUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpStar, count, hero.skinId); - pushEquipStarMax(roleId, roleName, serverId, hid, newEquip, isUpStar); - - const curHero = { - hid, - isUpStar, - ePlace: updatedEplace - } - return resResult(STATUS.SUCCESS, { curHero }); - - } - - //镶嵌天晶石 - public async putOnJewel(msg: { hid: number, ePlaceId: number, jewel: number }, session: BackendSession) { - let { hid, ePlaceId, jewel: seqId } = msg; - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid) && RESONANCE.JEWEL) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_IS_NOT_FIND); - if (curEquip.jewel == seqId) return resResult(STATUS.JEWEL_HAS_SUIT); - if (!checkJewelCanPutOnEquip(curEquip, jewel)) { - return resResult(STATUS.EQUIP_NOT_MATCH_JEWEL) - } - - let originHeroResult: { hid: number, ePlace: Partial[] }; - let originJewel = curEquip.jewel ? await JewelModel.findbySeqId(curEquip.jewel) : null; // 原本自己的天晶石 - let canSentMineToOrigin = false; // 自己的能不能塞到对方身上 - if (jewel.hid != 0) { // 如果天晶石原本镶嵌在其他武将身上,把自己的给他 - let originHero = await HeroModel.findByHidAndRole(jewel.hid, roleId); - let originEplace = originHero?.ePlace || []; - let originEquip = originEplace.find(cur => cur.jewel == seqId); - if (originEquip) { - let canChange = originJewel && checkJewelCanPutOnEquip(originEquip, originJewel); - if (canChange) canSentMineToOrigin = true; - let { newEplace, updatedEplace } = updateEplace(originEplace, ePlaceId, { jewel: canChange ? originJewel.seqId : 0 }); - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, jewel.hid, { ePlace: newEplace }, { ePlaceId, jewel: canChange ? originJewel : null, skinId: originHero.skinId }); - await checkTaskInPutJewel(serverId, roleId, sid, jewel.hid, originEplace, newEplace, ePlaceId, jewel, canChange ? originJewel : null); - - originHeroResult = { hid: originHero.hid, ePlace: updatedEplace }; - } - } - if (originJewel) { // 更新自己的天晶石 - originJewel = await JewelModel.putOnOrOff(originJewel.seqId, canSentMineToOrigin ? jewel.hid : 0, canSentMineToOrigin ? ePlaceId : 0); - } - - // 目标镶嵌上 - let curJewel = await JewelModel.putOnOrOff(seqId, hid, ePlaceId); - let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { jewel: seqId }); - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, hid, { ePlace: newEplace }, { ePlaceId, jewel: curJewel, skinId: hero.skinId }); - await checkTaskInPutJewel(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, originJewel, curJewel); - - let curHero = { - hid, - ePlace: updatedEplace - } - - return resResult(STATUS.SUCCESS, { curHero, originHero: originHeroResult, curJewel, originJewel }); - } - - // 卸下天晶石 - public async putOffJewel(msg: { hid: number, ePlaceId: number }, session: BackendSession) { - let { hid, ePlaceId } = msg; - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid) && RESONANCE.JEWEL) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - if (curEquip.jewel == 0) return resResult(STATUS.JEWEL_NOT_SUIT); - - let curJewel = await JewelModel.putOnOrOff(curEquip.jewel, 0, 0); - let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { jewel: 0 }); - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, hid, { ePlace: newEplace }, { ePlaceId, jewel: null, skinId: hero.skinId }); - await checkTaskInPutJewel(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, null, curJewel); - - let curHero = { - hid, - ePlace: updatedEplace - } - - return resResult(STATUS.SUCCESS, { curHero, curJewel }); - } - - // 装备或卸载地玉石 - public async putOnOrOffStone(msg: { hid: number, ePlaceId: number, stonesId: number, gid: number }, session: BackendSession) { - let { hid, ePlaceId, stonesId, gid } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid) && RESONANCE.STONE) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let oldEplace = hero.ePlace || []; - let curEquip = oldEplace.find(cur => cur.id == ePlaceId); - if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); - - let curStone = curEquip.stones?.find(cur => cur.id == stonesId) || { id: stonesId, stone: 0 }; - if (curStone.stone == gid) { - return resResult(gid == 0 ? STATUS.STONE_NOT_SUIT : STATUS.STONE_HAS_SUIT); - } - if (!checkStoneCanPutOnEquip(curEquip, stonesId, gid)) { // 是否可以镶嵌 - return resResult(STATUS.STONE_CANNOT_SUIT); - } - - let updateConsumes = hero.consumes; - if (gid > 0) { - updateConsumes = addConsumeToHero(updateConsumes, [{ id: gid, count: 1 }]); - let consumeResult = await handleCost(roleId, sid, [{ id: gid, count: 1 }], ITEM_CHANGE_REASON.EQUIP_FILL_HOLE); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - if (curStone.stone > 0) { // 返回石头 - updateConsumes = addConsumeToHero(updateConsumes, [{ id: curStone.stone, count: -1 }]); - await addItems(roleId, roleName, sid, [{ id: curStone.stone, count: 1 }], ITEM_CHANGE_REASON.EQUIP_FILL_HOLE); - } - - let newStone = updateStone(curEquip.stones, stonesId, gid); - let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { stones: newStone }); - let jewel = await JewelModel.findbySeqId(curEquip.jewel); - let update = { - ePlace: newEplace, - consumes: updateConsumes, - } - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STONE, roleId, serverId, sid, hid, update, { ePlaceId, jewel, skinId: hero.skinId, stonesId }); - await checkTaskInPutStone(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, jewel); - - let curHero = { - hid, - ePlace: updatedEplace - } - - return resResult(STATUS.SUCCESS, { curHero }); - } - - // 随机属性锁定 - public async lockRandSe(msg: { seqId: number, randSeId: number, type: number }, session: BackendSession) { - let { seqId, randSeId, type } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { randSe } = jewel; - if (!randSe || randSe.length <= 0) { - return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); - } - let curSe = randSe.find(cur => cur.id == randSeId); - if (!curSe || (type == 1 && curSe.locked)) { - return resResult(STATUS.JEWEL_DUPLICATE_LOCK); - } - - if (type == 1) { // 仅在上锁时消耗,根据已有的锁的数量判断消耗 - let lockNum = randSe.filter(cur => cur.locked).length; - let consumes: Array<{ id: number, count: number }> = []; - if (lockNum == 0) { - consumes = parseGoodStr(EQUIP.EQUIP_ONE_LOCKED); - } else if (lockNum == 1) { - consumes = parseGoodStr(EQUIP.EQUIP_TWO_LOCKED); - } else if (lockNum == 2) { - consumes = parseGoodStr(EQUIP.EQUIP_THREE_LOCKED); - } else { - return resResult(STATUS.ROLE_ALL_SE_LOCK); - } - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_LOCK_RANDSE); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - let result = await JewelModel.lock(seqId, randSeId, type == 1); - if (!result) { - return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); - } - return resResult(STATUS.SUCCESS, { curJewel: pick(result, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe']) }); - - } - - // 装备洗炼预览 - public async previewRandSe(msg: { seqId: number }, session: BackendSession) { - - let roleId: string = session.get('roleId'); - // let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - - let { seqId } = msg; - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { id, randSe, previewRandSe } = jewel; - if (previewRandSe.length <= 0) { - - let previewRandSe = getRandSeResult(id, randSe); - if (!previewRandSe) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let lockNum = randSe.reduce((pre, cur) => { - return cur.locked ? pre + 1 : pre; - }, 0); - - if (lockNum >= randSe.length) { - return resResult(STATUS.ROLE_EQUIP_CANNOT_RESTRENGTHEN); - } - // 消耗 - let consumes: Array<{ id: number, count: number }> = []; - if (lockNum == 0) { - consumes = parseGoodStr(EQUIP.EQUIP_ONE_REFORGED); - } else if (lockNum == 1) { - consumes = parseGoodStr(EQUIP.EQUIP_TWO_REFORGED); - } else if (lockNum == 2) { - consumes = parseGoodStr(EQUIP.EQUIP_THREE_REFORGED); - } else { - consumes = parseGoodStr(EQUIP.EQUIP_FOUR_REFORGED); - } - - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_RESTRENGTHEN); - if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - jewel = await JewelModel.updateInfo(seqId, { previewRandSe }); - } - - - return resResult(STATUS.SUCCESS, { curJewel: pick(jewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - - } - - // 装备洗炼 - public async resetRandSe(msg: { seqId: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let serverId: number = session.get('serverId'); - let sid: string = session.get('sid'); - - let { seqId } = msg; - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { randSe, hid, ePlaceId, previewRandSe } = jewel; - if (!previewRandSe || previewRandSe.length <= 0) { // 没预览过 - return resResult(STATUS.EQUIP_RESTRENGTHEN_NOT_PREVIEW); - } - - let newJewel = await JewelModel.updateInfo(seqId, { previewRandSe: [], randSe: previewRandSe }); - // 更新战力 - if (hid > 0) { - const hero = await HeroModel.findByHidAndRole(hid, roleId); - await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE, roleId, serverId, sid, hid, { ePlace: hero.ePlace }, { ePlaceId, jewel: newJewel, skinId: hero.skinId }); - } - - await checkTaskInEquipReset(serverId, roleId, sid); - return resResult(STATUS.SUCCESS, { curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - - } - - // 放弃这条洗练 - public async giveupPreview(msg: { seqId: number }, session: BackendSession) { - - let { seqId } = msg; - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { randSe, previewRandSe } = jewel; - if (!randSe || randSe.length <= 0) { - return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); - } - - if (!previewRandSe) { // 没预览过 - return resResult(STATUS.JEWEL_NOT_PREVIEW); - } - - let jewelResult = await JewelModel.updateInfo(seqId, { previewRandSe: [] }) - - return resResult(STATUS.SUCCESS, { curJewel: pick(jewelResult, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - - } - - // 选择淬炼的那一条 - public async chooseQuench(msg: { seqId: number, randSeId: number }, session: BackendSession) { - - let { seqId, randSeId } = msg; - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { randSe } = jewel; - if (!randSe || randSe.length <= 0) { - return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); - } - - let quenchedSe = randSe.find(cur => cur.quenched); - if (!!quenchedSe) return resResult(STATUS.JEWEL_HAS_CHOOSEN_QUENCH); - - let curRandSe = randSe.find(cur => cur.id == randSeId); - if (!curRandSe) return resResult(STATUS.JEWEL_HAVE_NO_CUR_RANDSE); - - let jewelResult = await JewelModel.chooseQuench(seqId, randSeId); - - return resResult(STATUS.SUCCESS, { curJewel: pick(jewelResult, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - } - - // 淬火 - public async quench(msg: { seqId: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let serverId: number = session.get('serverId'); - let sid: string = session.get('sid'); - - let { seqId } = msg; - let jewel = await JewelModel.findbySeqId(seqId); - if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); - - let { randSe, hid, ePlaceId } = jewel; - if (!randSe || randSe.length <= 0) { - return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); - } - let quenchedSe = randSe.find(cur => cur.quenched); - if (!quenchedSe) return resResult(STATUS.JEWEL_NOT_CHOOSEN_QUENCH); - - let dicJewel = gameData.jewel.get(jewel.id); - if (!dicJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let consumeResult = await handleCost(roleId, sid, dicJewel.quenchConsume, ITEM_CHANGE_REASON.EQUIP_QUENCH); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let newRandSe = getJewelRandSe(quenchedSe.id, quenchedSe.seid); - let isSuccess = newRandSe.rand >= quenchedSe.rand; - let newJewel = await JewelModel.quench(seqId, isSuccess, newRandSe.rand); - // 更新战力 - if (isSuccess && hid > 0) { - const hero = await HeroModel.findByHidAndRole(hid, roleId); - await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_QUENCH, roleId, serverId, sid, hid, { ePlace: hero.ePlace }, { ePlaceId, jewel: newJewel, skinId: hero.skinId }); - } - - await checkTaskInEquipQuench(serverId, roleId, sid, isSuccess); - return resResult(STATUS.SUCCESS, { isSuccess, curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - - } - - // 地玉石和图纸分解 - public async decomposeItem(msg: { origin: { id: number, count: number }[] }, session: BackendSession) { - let { origin } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let goods: ItemInter[] = []; - - for (let { id, count } of origin) { - let dicGoods = gameData.goods.get(id); - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (!dicGoods.decomposeItem || dicGoods.decomposeItem.length <= 0) return resResult(STATUS.CONSUME_TYPE_ERR); - if (count < 0) return resResult(STATUS.WRONG_PARMS); - - for (let result of dicGoods.decomposeItem) { - goods.push({ id: result.id, count: result.count * count }); - } - } - - let costResult = await handleCost(roleId, sid, origin, ITEM_CHANGE_REASON.EQUIP_PIECE_DECOMPOSE); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let result = await addItems(roleId, roleName, sid, goods, ITEM_CHANGE_REASON.EQUIP_PIECE_DECOMPOSE); - return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); - } - - //分解装备 - public async decomposeJewel(msg: { origin: number[] }, session: BackendSession) { - let { origin } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - if (origin.length > BAG.BAG_RESOLVE_UPLIMITED) { - return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT); - } - let jewels = await JewelModel.findbySeqIds(origin); - if (jewels.length < origin.length) return resResult(STATUS.JEWEL_IS_NOT_FIND); - - let goods: RewardInter[] = []; - let cost: ItemInter[] = []; - - for (let jewel of jewels) { - if (jewel.hid > 0) { - return resResult(STATUS.JEWEL_IS_EQUIPED); - } - let dicGoods = gameData.goods.get(jewel.id); - cost.push({ seqId: jewel.seqId, id: jewel.id, count: 1 }); - goods.push(...dicGoods.decomposeItem); - } - - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); // 删掉装备 - if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let result = await addItems(roleId, roleName, sid, goods, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); - return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); - } - - //宝石合成 - public async composeStone(msg: { id: number, count: number }, session: BackendSession) { - let { id, count } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let check = new CheckMeterial(roleId); - let isEnough = await check.composeStone(id, count); - if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let consumes = check.getConsume(); - let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.COMPOSE_STONE); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.COMPOSE_STONE); - - await checkTaskInComposeStone(serverId, roleId, sid, count); - return resResult(STATUS.SUCCESS, { goods }); - } - - - /** - * 玉石一键合成 - * @param msg - * @param session - * @returns - */ - public async composeStoneByItId(msg: { itId: number }, session: BackendSession) { - let { itId } = msg; - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let curItem = await getCurItem(roleId, itId); - if (curItem.size == 0) { - // console.log("---composeStoneByItId-- curItem=%s", curItem); - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - let { allCostItem, allAddItem } = await getComposeStoneCostAndAdd(curItem, itId) - if (!allCostItem || allCostItem.size == 0 || !allAddItem || allAddItem.size == 0) { - // console.log("---composeStoneByItId-- allCostItem=%s, allAddItem=%s", allCostItem, allAddItem); - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - let costResult = await handleCost(roleId, sid, [...allCostItem].map(([id, count]) => ({ id, count })), ITEM_CHANGE_REASON.COMPOSE_STONE); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let arrAddItem = []; - let total = 0; - for (const [id, count] of allAddItem) { - if (count == 0) continue; - arrAddItem.push({ id, count }); - total += count; - } - let goods = await addItems(roleId, roleName, sid, arrAddItem, ITEM_CHANGE_REASON.COMPOSE_STONE); - - await checkTaskInComposeStone(serverId, roleId, sid, total); - return resResult(STATUS.SUCCESS, { goods }); - } - - - public async inheritJewel(msg: { originJewel: number, targetJewel: number }, session: BackendSession) { - let { originJewel: originJewelId, targetJewel: targetJewelId } = msg; - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let originJewel = await JewelModel.findbySeqId(originJewelId); - if (!originJewel || originJewel.roleId != roleId) return resResult(STATUS.JEWEL_IS_NOT_FIND); - if (originJewel.hid > 0) return resResult(STATUS.JEWEL_HAS_EQUPED); - - let targetJewel = await JewelModel.findbySeqId(targetJewelId); - if (!targetJewel || targetJewel.roleId != roleId) return resResult(STATUS.JEWEL_IS_NOT_FIND); - - if (isLocked(targetJewel.randSe)) return resResult(STATUS.JEWEL_LOCKED_CANNOT_INHERIT); - - let dicOldJewel = gameData.jewel.get(originJewel.id); - if (!dicOldJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicJewel = gameData.jewel.get(targetJewel.id); - if (!dicJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicJewel.eplaceId != dicOldJewel.eplaceId || dicJewel.lv < dicOldJewel.lv) { - return resResult(STATUS.JEWEL_CANNOT_INHERIT); - } - - // 消耗 - let consumeResult = await handleCost(roleId, sid, [ - { id: originJewel.id, seqId: originJewel.seqId }, - ...dicJewel.inheritConsume - ], ITEM_CHANGE_REASON.JEWEL_INHERIT); - if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let newRandSe = getRandSeResult(targetJewel.id, targetJewel.randSe, originJewel.randSe, originJewel.id); - let newJewel = await JewelModel.updateInfo(targetJewel.seqId, { previewRandSe: [], randSe: newRandSe }); - // 更新战力 - if (targetJewel.hid > 0) { - const hero = await HeroModel.findByHidAndRole(targetJewel.hid, roleId); - await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE, roleId, serverId, sid, targetJewel.hid, { ePlace: hero.ePlace }, { ePlaceId: targetJewel.ePlaceId, jewel: newJewel, skinId: hero.skinId }); - - } - - await checkTaskInEquipReset(serverId, roleId, sid); - return resResult(STATUS.SUCCESS, { curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); - } - -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE, CONSUME_TYPE, RESONANCE } from "../../../consts"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; + +import { resResult, parseGoodStr } from "@pubUtils/util"; +import { addItems, getJewelRandSe, handleCost } from "../../../services/role/rewardService"; +import { HeroModel, EPlace } from "@db/Hero"; +import { gameData, getEquipByJobClassAndEPlace, getNextEquipQuality, getEquipStarIdByEquipId, getNextEquipStar } from "@pubUtils/data"; +import { BAG, EQUIP } from "@pubUtils/dicParam"; +import { getRandSeResult, updateEplace, updateEplaces, checkJewelCanPutOnEquip, updateStone, checkStoneCanPutOnEquip, isLocked } from "../../../services/equipService"; + +import { clone, isNumber, max, min, pick } from 'underscore'; +import { JewelModel, RandSe } from "@db/Jewel"; +import { checkTaskInComposeEquip, checkTaskInEquipLvUp, checkTaskInComposeStone, checkTaskInEquipReset, checkTaskInEquipQuench, checkTaskInEquipQualityUp, checkTaskInEquipStarUp, checkTaskInPutJewel, checkTaskInPutStone } from '../../../services/task/taskService'; +import { pushEquipQualityMax, pushEquipStarMax } from "../../../services/sysChatService"; +import { addConsumeToHero } from "../../../services/roleService"; +import { CheckMeterial, getComposeStoneCostAndAdd, getCurItem } from "../../../services/role/checkMaterial"; +import { combineItems } from "../../../services/role/util"; +import { calculateCeWithHero } from "../../../services/playerCeService"; +import { ItemModel } from "@db/Item"; +import { index } from "typegoose"; +import { all } from "bluebird"; +import { getResonanceDataMap } from "../../../services/role/resonanceService"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new EquipHandler(app); +} + +export class EquipHandler { + + constructor(private app: Application) { + } + + public async composeEquip(msg: { hid: number, ePlaceId: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { hid, ePlaceId } = msg; + if (!isNumber(ePlaceId) || ePlaceId > 4 || ePlaceId < 1) return resResult(STATUS.WRONG_PARMS); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(equip => equip.id == ePlaceId); + if (curEquip) return resResult(STATUS.EQUIP_HAS_COMPOSE); + + let dicHero = gameData.hero.get(hero.skinId); + let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, ePlaceId); + if (!dicEquip) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let consumeResult = await handleCost(roleId, sid, dicEquip.composeMaterial, ITEM_CHANGE_REASON.EQUIP_COMPOSE); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let newEquip = new EPlace(ePlaceId, dicEquip.id); + let newEplace = [...oldEplace, newEquip]; + + let update = { + ePlace: newEplace, + consumes: addConsumeToHero(hero.consumes, dicEquip.composeMaterial), + } + + await calculateCeWithHero(HERO_SYSTEM_TYPE.COMPOSE_EQUIP, roleId, serverId, sid, hid, update, { ePlaceId, skinId: hero.skinId }); + await checkTaskInComposeEquip(serverId, roleId, sid, oldEplace, newEplace); + + let curHero = { + hid, + ePlace: [newEquip] + } + return resResult(STATUS.SUCCESS, { curHero }); + } + + // 装备栏强化 + public async strengthen(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + // let roleName: string = session.get('roleName'); + const serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + + let { hid, ePlaceId, isOneClick } = msg; + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + if (curEquip.lv >= hero.lv) return resResult(STATUS.ROLE_EQUIP_REACH_MAX); + let fromLv = curEquip.lv; + let toLv = isOneClick ? hero.lv : fromLv + 1; + let newLv = fromLv; + + let check = new CheckMeterial(roleId); + for (let lv = fromLv + 1; lv <= toLv; lv++) { + let dicCost = gameData.equipStrengthenCost.get(lv); + let isEnough = await check.decrease(dicCost.consume); + if (!isEnough) break; // 消耗不足 + newLv = lv; + } + if (newLv == fromLv) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STRENTHEN); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { lv: newLv }); + + let update = { + ePlace: newEplace, + consumes: addConsumeToHero(hero.consumes, consumes) + } + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, serverId, sid, hid, update, { ePlaceIds: [ePlaceId] }); + await checkTaskInEquipLvUp(serverId, roleId, sid, oldEplace, newEplace, [ePlaceId]); + + const curHero = { + hid, + ePlace: updatedEplace + } + return resResult(STATUS.SUCCESS, { curHero }); + + } + + // 装备栏一键强化至相应等级 + public async strengthenAll(msg: { hid: number, lv: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let serverId: number = session.get('serverId'); + let sid: string = session.get('sid'); + + let { hid, lv } = msg; // lv: 升到哪一级 + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let { ePlace, lv: playerLv } = hero; // 装备栏 + let fromLv = Math.min(...ePlace.map(cur => cur.lv)); // 最小的等级 + let toLv = lv < playerLv ? lv : playerLv; + + let eplaceIds = new Map(); // 更新了的装备栏id + let check = new CheckMeterial(roleId); + for (let lv = fromLv + 1; lv <= toLv; lv++) { + let isBreak = false; + for (let equip of ePlace) { + if (equip.lv >= lv) continue; + let dicCost = gameData.equipStrengthenCost.get(lv); + let isEnough = await check.decrease(dicCost.consume); + if (!isEnough) { isBreak = true; break; } // 消耗不足 + + eplaceIds.set(equip.id, { lv }); + } + if (isBreak) break; + } + + if (eplaceIds.size <= 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STRENTHEN); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { newEplace, updatedEplace } = updateEplaces(ePlace, eplaceIds); + + let update = { + ePlace: newEplace, + consumes: addConsumeToHero(hero.consumes, consumes), + } + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, serverId, sid, hid, update, { ePlaceIds: [...eplaceIds.keys()] }); + await checkTaskInEquipLvUp(serverId, roleId, sid, ePlace, newEplace, [...eplaceIds.keys()]); + + const curHero = { + hid, + ePlace: updatedEplace + } + return resResult(STATUS.SUCCESS, { curHero }); + + } + + + // 装备升品 + public async qualityUp(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + const serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + let { hid, ePlaceId, isOneClick } = msg; + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + + let nextEquipQuality = getNextEquipQuality(curEquip.equipId, curEquip.quality, curEquip.qualityStage); + if (!nextEquipQuality) return resResult(STATUS.EQUIP_QUALITY_MAX); + + let equipUpdate = { + quality: curEquip.quality, + qualityStage: curEquip.qualityStage, + } + let check = new CheckMeterial(roleId); + let count = 0; + if (isOneClick) { // 一键升到该品最高点 + if (nextEquipQuality.quality != curEquip.quality) { + return resResult(STATUS.EQUIP_QUALITYSTAGE_IS_MAX); + } + while (nextEquipQuality && nextEquipQuality.quality == curEquip.quality) { + let isEnough = await check.decrease(nextEquipQuality.consume); + if (!isEnough) break; // 消耗不足 + equipUpdate.qualityStage++; + nextEquipQuality = getNextEquipQuality(curEquip.equipId, equipUpdate.quality, equipUpdate.qualityStage); + count++; + } + } else { // 往下一阶,包括满点之后的升品 + let isEnough = await check.decrease(nextEquipQuality.consume); + if (isEnough) { + equipUpdate.quality = nextEquipQuality.quality; + equipUpdate.qualityStage = nextEquipQuality.point; + count++; + } + } + if (equipUpdate.quality == curEquip.quality && equipUpdate.qualityStage == curEquip.qualityStage) { + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_QUALITYUP); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let isUpQuality = equipUpdate.quality != curEquip.quality; + + let { newEplace, updatedEplace, newEquip } = updateEplace(oldEplace, ePlaceId, equipUpdate); + + let update = { + ePlace: newEplace, + consumes: addConsumeToHero(hero.consumes, consumes), + } + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_QUALITY, roleId, serverId, sid, hid, update, { ePlaceId }); + + await checkTaskInEquipQualityUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpQuality, count); + pushEquipQualityMax(roleId, roleName, serverId, hid, newEquip, isUpQuality); + const curHero = { + hid, + isUpQuality, + ePlace: updatedEplace + } + return resResult(STATUS.SUCCESS, { curHero }); + + } + + // 装备升星 + public async starUp(msg: { hid: number, ePlaceId: number, isOneClick: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + const serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + let { hid, ePlaceId, isOneClick } = msg; + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + let incEquipStarSum = 0; + let equipUpdate = { + star: curEquip.star, + starStage: curEquip.starStage, + } + + let check = new CheckMeterial(roleId); + let dicEquipStar = getEquipStarIdByEquipId(curEquip.equipId, curEquip.star); + if (!dicEquipStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let isUpStar = curEquip.starStage == dicEquipStar.count; + let count = 0; + + if (isUpStar) { // 升星 + if (isOneClick) { + return resResult(STATUS.EQUIP_STARSTAGE_IS_MAX); + } else { + let nextEquipStar = getNextEquipStar(curEquip.equipId, curEquip.star); + if (!nextEquipStar) return resResult(STATUS.EQUIP_STAR_MAX); + let dicEquipQualityExtra = gameData.equipQualityExtra.get(curEquip.quality); + if (!dicEquipQualityExtra || dicEquipQualityExtra.star < nextEquipStar.star) { + return resResult(STATUS.EQUIP_QUALITY_NOT_ENOUGH); + } + + let isEnough = await check.decrease(dicEquipStar.subConsume); + if (isEnough) { + equipUpdate.star = nextEquipStar.star; + equipUpdate.starStage = 0; + incEquipStarSum += equipUpdate.star - curEquip.star; + count++; + } + } + } else { // 升小点,包括一键升到满小点和升一个小点 + let toStage = isOneClick ? dicEquipStar.count : curEquip.starStage + 1; + for (let stage = curEquip.starStage + 1; stage <= toStage; stage++) { + let isEnough = await check.decrease(dicEquipStar.mainConsume); + if (!isEnough) break; // 消耗不足 + equipUpdate.starStage = stage; + count++; + } + } + + if (equipUpdate.star == curEquip.star && equipUpdate.starStage == curEquip.starStage) { + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_STARUP); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let { newEplace, updatedEplace, newEquip } = updateEplace(oldEplace, ePlaceId, equipUpdate); + let update = { + ePlace: newEplace, + consumes: addConsumeToHero(hero.consumes, consumes) + } + + // console.log('### incEquipStarSum', incEquipStarSum) + let { curRole } = await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STAR, roleId, serverId, sid, hid, update, { ePlaceId, skinId: hero.skinId, roleIncUpdate: { equipStarSum: incEquipStarSum } }); + + checkTaskInEquipStarUp(serverId, roleId, sid, oldEplace, newEplace, ePlaceId, hid, isUpStar, count, hero.skinId); + pushEquipStarMax(roleId, roleName, serverId, hid, newEquip, isUpStar); + + const curHero = { + hid, + isUpStar, + ePlace: updatedEplace + } + return resResult(STATUS.SUCCESS, { curHero }); + + } + + //镶嵌天晶石 + public async putOnJewel(msg: { hid: number, ePlaceId: number, jewel: number }, session: BackendSession) { + let { hid, ePlaceId, jewel: seqId } = msg; + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid) && RESONANCE.JEWEL) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_IS_NOT_FIND); + if (curEquip.jewel == seqId) return resResult(STATUS.JEWEL_HAS_SUIT); + if (!checkJewelCanPutOnEquip(curEquip, jewel)) { + return resResult(STATUS.EQUIP_NOT_MATCH_JEWEL) + } + + let originHeroResult: { hid: number, ePlace: Partial[] }; + let originJewel = curEquip.jewel ? await JewelModel.findbySeqId(curEquip.jewel) : null; // 原本自己的天晶石 + let canSentMineToOrigin = false; // 自己的能不能塞到对方身上 + if (jewel.hid != 0) { // 如果天晶石原本镶嵌在其他武将身上,把自己的给他 + let originHero = await HeroModel.findByHidAndRole(jewel.hid, roleId); + let originEplace = originHero?.ePlace || []; + let originEquip = originEplace.find(cur => cur.jewel == seqId); + if (originEquip) { + let canChange = originJewel && checkJewelCanPutOnEquip(originEquip, originJewel); + if (canChange) canSentMineToOrigin = true; + let { newEplace, updatedEplace } = updateEplace(originEplace, ePlaceId, { jewel: canChange ? originJewel.seqId : 0 }); + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, jewel.hid, { ePlace: newEplace }, { ePlaceId, jewel: canChange ? originJewel : null, skinId: originHero.skinId }); + await checkTaskInPutJewel(serverId, roleId, sid, jewel.hid, originEplace, newEplace, ePlaceId, jewel, canChange ? originJewel : null); + + originHeroResult = { hid: originHero.hid, ePlace: updatedEplace }; + } + } + if (originJewel) { // 更新自己的天晶石 + originJewel = await JewelModel.putOnOrOff(originJewel.seqId, canSentMineToOrigin ? jewel.hid : 0, canSentMineToOrigin ? ePlaceId : 0); + } + + // 目标镶嵌上 + let curJewel = await JewelModel.putOnOrOff(seqId, hid, ePlaceId); + let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { jewel: seqId }); + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, hid, { ePlace: newEplace }, { ePlaceId, jewel: curJewel, skinId: hero.skinId }); + await checkTaskInPutJewel(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, originJewel, curJewel); + + let curHero = { + hid, + ePlace: updatedEplace + } + + return resResult(STATUS.SUCCESS, { curHero, originHero: originHeroResult, curJewel, originJewel }); + } + + // 卸下天晶石 + public async putOffJewel(msg: { hid: number, ePlaceId: number }, session: BackendSession) { + let { hid, ePlaceId } = msg; + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid) && RESONANCE.JEWEL) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + if (curEquip.jewel == 0) return resResult(STATUS.JEWEL_NOT_SUIT); + + let curJewel = await JewelModel.putOnOrOff(curEquip.jewel, 0, 0); + let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { jewel: 0 }); + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_JEWEL, roleId, serverId, sid, hid, { ePlace: newEplace }, { ePlaceId, jewel: null, skinId: hero.skinId }); + await checkTaskInPutJewel(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, null, curJewel); + + let curHero = { + hid, + ePlace: updatedEplace + } + + return resResult(STATUS.SUCCESS, { curHero, curJewel }); + } + + // 装备或卸载地玉石 + public async putOnOrOffStone(msg: { hid: number, ePlaceId: number, stonesId: number, gid: number }, session: BackendSession) { + let { hid, ePlaceId, stonesId, gid } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid) && RESONANCE.STONE) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let oldEplace = hero.ePlace || []; + let curEquip = oldEplace.find(cur => cur.id == ePlaceId); + if (!curEquip) return resResult(STATUS.EQUIP_NOT_FIND); + + let curStone = curEquip.stones?.find(cur => cur.id == stonesId) || { id: stonesId, stone: 0 }; + if (curStone.stone == gid) { + return resResult(gid == 0 ? STATUS.STONE_NOT_SUIT : STATUS.STONE_HAS_SUIT); + } + if (!checkStoneCanPutOnEquip(curEquip, stonesId, gid)) { // 是否可以镶嵌 + return resResult(STATUS.STONE_CANNOT_SUIT); + } + + let updateConsumes = hero.consumes; + if (gid > 0) { + updateConsumes = addConsumeToHero(updateConsumes, [{ id: gid, count: 1 }]); + let consumeResult = await handleCost(roleId, sid, [{ id: gid, count: 1 }], ITEM_CHANGE_REASON.EQUIP_FILL_HOLE); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + if (curStone.stone > 0) { // 返回石头 + updateConsumes = addConsumeToHero(updateConsumes, [{ id: curStone.stone, count: -1 }]); + await addItems(roleId, roleName, sid, [{ id: curStone.stone, count: 1 }], ITEM_CHANGE_REASON.EQUIP_FILL_HOLE); + } + + let newStone = updateStone(curEquip.stones, stonesId, gid); + let { newEplace, updatedEplace } = updateEplace(oldEplace, ePlaceId, { stones: newStone }); + let jewel = await JewelModel.findbySeqId(curEquip.jewel); + let update = { + ePlace: newEplace, + consumes: updateConsumes, + } + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STONE, roleId, serverId, sid, hid, update, { ePlaceId, jewel, skinId: hero.skinId, stonesId }); + await checkTaskInPutStone(serverId, roleId, sid, hid, oldEplace, newEplace, ePlaceId, jewel); + + let curHero = { + hid, + ePlace: updatedEplace + } + + return resResult(STATUS.SUCCESS, { curHero }); + } + + // 随机属性锁定 + public async lockRandSe(msg: { seqId: number, randSeId: number, type: number }, session: BackendSession) { + let { seqId, randSeId, type } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { randSe } = jewel; + if (!randSe || randSe.length <= 0) { + return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); + } + let curSe = randSe.find(cur => cur.id == randSeId); + if (!curSe || (type == 1 && curSe.locked)) { + return resResult(STATUS.JEWEL_DUPLICATE_LOCK); + } + + if (type == 1) { // 仅在上锁时消耗,根据已有的锁的数量判断消耗 + let lockNum = randSe.filter(cur => cur.locked).length; + let consumes: Array<{ id: number, count: number }> = []; + if (lockNum == 0) { + consumes = parseGoodStr(EQUIP.EQUIP_ONE_LOCKED); + } else if (lockNum == 1) { + consumes = parseGoodStr(EQUIP.EQUIP_TWO_LOCKED); + } else if (lockNum == 2) { + consumes = parseGoodStr(EQUIP.EQUIP_THREE_LOCKED); + } else { + return resResult(STATUS.ROLE_ALL_SE_LOCK); + } + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_LOCK_RANDSE); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + let result = await JewelModel.lock(seqId, randSeId, type == 1); + if (!result) { + return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); + } + return resResult(STATUS.SUCCESS, { curJewel: pick(result, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe']) }); + + } + + // 装备洗炼预览 + public async previewRandSe(msg: { seqId: number }, session: BackendSession) { + + let roleId: string = session.get('roleId'); + // let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + + let { seqId } = msg; + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { id, randSe, previewRandSe } = jewel; + if (previewRandSe.length <= 0) { + + let previewRandSe = getRandSeResult(id, randSe); + if (!previewRandSe) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let lockNum = randSe.reduce((pre, cur) => { + return cur.locked ? pre + 1 : pre; + }, 0); + + if (lockNum >= randSe.length) { + return resResult(STATUS.ROLE_EQUIP_CANNOT_RESTRENGTHEN); + } + // 消耗 + let consumes: Array<{ id: number, count: number }> = []; + if (lockNum == 0) { + consumes = parseGoodStr(EQUIP.EQUIP_ONE_REFORGED); + } else if (lockNum == 1) { + consumes = parseGoodStr(EQUIP.EQUIP_TWO_REFORGED); + } else if (lockNum == 2) { + consumes = parseGoodStr(EQUIP.EQUIP_THREE_REFORGED); + } else { + consumes = parseGoodStr(EQUIP.EQUIP_FOUR_REFORGED); + } + + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.EQUIP_RESTRENGTHEN); + if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + jewel = await JewelModel.updateInfo(seqId, { previewRandSe }); + } + + + return resResult(STATUS.SUCCESS, { curJewel: pick(jewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + + } + + // 装备洗炼 + public async resetRandSe(msg: { seqId: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let serverId: number = session.get('serverId'); + let sid: string = session.get('sid'); + + let { seqId } = msg; + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { randSe, hid, ePlaceId, previewRandSe } = jewel; + if (!previewRandSe || previewRandSe.length <= 0) { // 没预览过 + return resResult(STATUS.EQUIP_RESTRENGTHEN_NOT_PREVIEW); + } + + let newJewel = await JewelModel.updateInfo(seqId, { previewRandSe: [], randSe: previewRandSe }); + // 更新战力 + if (hid > 0) { + const hero = await HeroModel.findByHidAndRole(hid, roleId); + await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE, roleId, serverId, sid, hid, { ePlace: hero.ePlace }, { ePlaceId, jewel: newJewel, skinId: hero.skinId }); + } + + await checkTaskInEquipReset(serverId, roleId, sid); + return resResult(STATUS.SUCCESS, { curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + + } + + // 放弃这条洗练 + public async giveupPreview(msg: { seqId: number }, session: BackendSession) { + + let { seqId } = msg; + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { randSe, previewRandSe } = jewel; + if (!randSe || randSe.length <= 0) { + return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); + } + + if (!previewRandSe) { // 没预览过 + return resResult(STATUS.JEWEL_NOT_PREVIEW); + } + + let jewelResult = await JewelModel.updateInfo(seqId, { previewRandSe: [] }) + + return resResult(STATUS.SUCCESS, { curJewel: pick(jewelResult, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + + } + + // 选择淬炼的那一条 + public async chooseQuench(msg: { seqId: number, randSeId: number }, session: BackendSession) { + + let { seqId, randSeId } = msg; + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { randSe } = jewel; + if (!randSe || randSe.length <= 0) { + return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); + } + + let quenchedSe = randSe.find(cur => cur.quenched); + if (!!quenchedSe) return resResult(STATUS.JEWEL_HAS_CHOOSEN_QUENCH); + + let curRandSe = randSe.find(cur => cur.id == randSeId); + if (!curRandSe) return resResult(STATUS.JEWEL_HAVE_NO_CUR_RANDSE); + + let jewelResult = await JewelModel.chooseQuench(seqId, randSeId); + + return resResult(STATUS.SUCCESS, { curJewel: pick(jewelResult, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + } + + // 淬火 + public async quench(msg: { seqId: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let serverId: number = session.get('serverId'); + let sid: string = session.get('sid'); + + let { seqId } = msg; + let jewel = await JewelModel.findbySeqId(seqId); + if (!jewel) return resResult(STATUS.JEWEL_NOT_FOUND); + + let { randSe, hid, ePlaceId } = jewel; + if (!randSe || randSe.length <= 0) { + return resResult(STATUS.JEWEL_HAVE_NO_RANDSE); + } + let quenchedSe = randSe.find(cur => cur.quenched); + if (!quenchedSe) return resResult(STATUS.JEWEL_NOT_CHOOSEN_QUENCH); + + let dicJewel = gameData.jewel.get(jewel.id); + if (!dicJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let consumeResult = await handleCost(roleId, sid, dicJewel.quenchConsume, ITEM_CHANGE_REASON.EQUIP_QUENCH); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let newRandSe = getJewelRandSe(quenchedSe.id, quenchedSe.seid); + let isSuccess = newRandSe.rand >= quenchedSe.rand; + let newJewel = await JewelModel.quench(seqId, isSuccess, newRandSe.rand); + // 更新战力 + if (isSuccess && hid > 0) { + const hero = await HeroModel.findByHidAndRole(hid, roleId); + await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_QUENCH, roleId, serverId, sid, hid, { ePlace: hero.ePlace }, { ePlaceId, jewel: newJewel, skinId: hero.skinId }); + } + + await checkTaskInEquipQuench(serverId, roleId, sid, isSuccess); + return resResult(STATUS.SUCCESS, { isSuccess, curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + + } + + // 地玉石和图纸分解 + public async decomposeItem(msg: { origin: { id: number, count: number }[] }, session: BackendSession) { + let { origin } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let goods: ItemInter[] = []; + + for (let { id, count } of origin) { + let dicGoods = gameData.goods.get(id); + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (!dicGoods.decomposeItem || dicGoods.decomposeItem.length <= 0) return resResult(STATUS.CONSUME_TYPE_ERR); + if (count < 0) return resResult(STATUS.WRONG_PARMS); + + for (let result of dicGoods.decomposeItem) { + goods.push({ id: result.id, count: result.count * count }); + } + } + + let costResult = await handleCost(roleId, sid, origin, ITEM_CHANGE_REASON.EQUIP_PIECE_DECOMPOSE); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let result = await addItems(roleId, roleName, sid, goods, ITEM_CHANGE_REASON.EQUIP_PIECE_DECOMPOSE); + return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); + } + + //分解装备 + public async decomposeJewel(msg: { origin: number[] }, session: BackendSession) { + let { origin } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + if (origin.length > BAG.BAG_RESOLVE_UPLIMITED) { + return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT); + } + let jewels = await JewelModel.findbySeqIds(origin); + if (jewels.length < origin.length) return resResult(STATUS.JEWEL_IS_NOT_FIND); + + let goods: RewardInter[] = []; + let cost: ItemInter[] = []; + + for (let jewel of jewels) { + if (jewel.hid > 0) { + return resResult(STATUS.JEWEL_IS_EQUIPED); + } + let dicGoods = gameData.goods.get(jewel.id); + cost.push({ seqId: jewel.seqId, id: jewel.id, count: 1 }); + goods.push(...dicGoods.decomposeItem); + } + + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); // 删掉装备 + if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let result = await addItems(roleId, roleName, sid, goods, ITEM_CHANGE_REASON.EQUIP_DECOMPOSE); + return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); + } + + //宝石合成 + public async composeStone(msg: { id: number, count: number }, session: BackendSession) { + let { id, count } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let check = new CheckMeterial(roleId); + let isEnough = await check.composeStone(id, count); + if (!isEnough) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let consumes = check.getConsume(); + let costResult = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.COMPOSE_STONE); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.COMPOSE_STONE); + + await checkTaskInComposeStone(serverId, roleId, sid, count); + return resResult(STATUS.SUCCESS, { goods }); + } + + + /** + * 玉石一键合成 + * @param msg + * @param session + * @returns + */ + public async composeStoneByItId(msg: { itId: number }, session: BackendSession) { + let { itId } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let curItem = await getCurItem(roleId, itId); + if (curItem.size == 0) { + // console.log("---composeStoneByItId-- curItem=%s", curItem); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + let { allCostItem, allAddItem } = await getComposeStoneCostAndAdd(curItem, itId) + if (!allCostItem || allCostItem.size == 0 || !allAddItem || allAddItem.size == 0) { + // console.log("---composeStoneByItId-- allCostItem=%s, allAddItem=%s", allCostItem, allAddItem); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + let costResult = await handleCost(roleId, sid, [...allCostItem].map(([id, count]) => ({ id, count })), ITEM_CHANGE_REASON.COMPOSE_STONE); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let arrAddItem = []; + let total = 0; + for (const [id, count] of allAddItem) { + if (count == 0) continue; + arrAddItem.push({ id, count }); + total += count; + } + let goods = await addItems(roleId, roleName, sid, arrAddItem, ITEM_CHANGE_REASON.COMPOSE_STONE); + + await checkTaskInComposeStone(serverId, roleId, sid, total); + return resResult(STATUS.SUCCESS, { goods }); + } + + + public async inheritJewel(msg: { originJewel: number, targetJewel: number }, session: BackendSession) { + let { originJewel: originJewelId, targetJewel: targetJewelId } = msg; + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let originJewel = await JewelModel.findbySeqId(originJewelId); + if (!originJewel || originJewel.roleId != roleId) return resResult(STATUS.JEWEL_IS_NOT_FIND); + if (originJewel.hid > 0) return resResult(STATUS.JEWEL_HAS_EQUPED); + + let targetJewel = await JewelModel.findbySeqId(targetJewelId); + if (!targetJewel || targetJewel.roleId != roleId) return resResult(STATUS.JEWEL_IS_NOT_FIND); + + if (isLocked(targetJewel.randSe)) return resResult(STATUS.JEWEL_LOCKED_CANNOT_INHERIT); + + let dicOldJewel = gameData.jewel.get(originJewel.id); + if (!dicOldJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicJewel = gameData.jewel.get(targetJewel.id); + if (!dicJewel) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicJewel.eplaceId != dicOldJewel.eplaceId || dicJewel.lv < dicOldJewel.lv) { + return resResult(STATUS.JEWEL_CANNOT_INHERIT); + } + + // 消耗 + let consumeResult = await handleCost(roleId, sid, [ + { id: originJewel.id, seqId: originJewel.seqId }, + ...dicJewel.inheritConsume + ], ITEM_CHANGE_REASON.JEWEL_INHERIT); + if (!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let newRandSe = getRandSeResult(targetJewel.id, targetJewel.randSe, originJewel.randSe, originJewel.id); + let newJewel = await JewelModel.updateInfo(targetJewel.seqId, { previewRandSe: [], randSe: newRandSe }); + // 更新战力 + if (targetJewel.hid > 0) { + const hero = await HeroModel.findByHidAndRole(targetJewel.hid, roleId); + await calculateCeWithHero(HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE, roleId, serverId, sid, targetJewel.hid, { ePlace: hero.ePlace }, { ePlaceId: targetJewel.ePlaceId, jewel: newJewel, skinId: hero.skinId }); + + } + + await checkTaskInEquipReset(serverId, roleId, sid); + return resResult(STATUS.SUCCESS, { curJewel: pick(newJewel, ['seqId', 'id', 'hid', 'ePlaceId', 'randSe', 'previewRandSe']) }); + } + +} + diff --git a/game-server/app/servers/role/handler/friendHandler.ts b/game-server/app/servers/role/handler/friendHandler.ts index 6883df444..9d60d87a4 100644 --- a/game-server/app/servers/role/handler/friendHandler.ts +++ b/game-server/app/servers/role/handler/friendHandler.ts @@ -1,792 +1,793 @@ -import { Application, BackendSession, ChannelService, HandlerService, } from "pinus"; -import { resResult, getRandEelm, getResStr, shouldRefresh, sortArrRandom, checkRoleIsRobot, getRobotSysType, makeRobotId, parseNumberList } from "../../../pubUtils/util"; -import { STATUS, ROLE_SELECT, FRIEND_DROP_TYPE, FRIEND_RELATION_TYPE, POPULATE_TYPE, BLOCK_OPEATE, CONSUME_TYPE, ITID, HERO_SELECT, REDIS_KEY, MSG_SOURCE, MSG_TYPE, TASK_TYPE, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, PUSH_ROUTE } from "../../../consts"; -import { RoleModel, RoleType } from "../../../db/Role"; -import { getTimeFun, getZeroPointD } from "../../../pubUtils/timeUtil"; -import { FriendApplyModel } from "../../../db/FriendApply"; -import { FriendListParam, FriendRecommendParams, BlackListParam, FriendValueListParam, HeroDetailParam } from "../../../domain/roleField/friend"; -import { FriendShipModel, FriendShipType } from "../../../db/FriendShip"; -import { FriendRelationModel, Relation } from "../../../db/FriendRelation"; -import { isRoleOnline, getServerName, getRoleOnlineInfo } from "../../../services/redisService"; -import { increaseFrdCnt, getRecommendType, sortByBeSentHeart, getApplyList, getFriendList, getMyApplyParam, getMyParamAsFriend } from "../../../services/friendService"; -import { FriendPointModel } from "../../../db/FriendPoint"; -import { gameData, getDicFriendByLv } from "../../../pubUtils/data"; -import { addItems, getFriendPointObject, handleCost } from "../../../services/role/rewardService"; -import { RewardInter } from "../../../pubUtils/interface"; -import { FriendPresentLogModel } from '../../../db/FriendPresentLog'; -import { HeroModel, EPlace } from "../../../db/Hero"; -import { FRIEND } from "../../../pubUtils/dicParam"; -import { PlayerDetail, PlayerDetailHero } from "../../../domain/battleField/guild"; -import { createPrivateMsg, delPrivateMsg, privateRoomId, pushMsgToRole, pushPresent } from "../../../services/chatService"; -import { Rank } from "../../../services/rankService"; -import { checkTaskWithRoles, checkTask } from "../../../services/task/taskService"; -import { ComBattleTeamModel } from "../../../db/ComBattleTeam"; -import { JewelModel } from "../../../db/Jewel"; -import { getHeroesAttributes } from "../../../services/playerCeService"; -import { sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from "../../../services/pushService"; -import { PrivateMessageModel } from "../../../db/PrivateMessage"; -import { RoleCeModel } from "../../../db/RoleCe"; -import { CalCe } from "../../../services/role/calCe"; -import { getSchoolPoint } from "../../../services/roleService"; -import { LadderMatchModel } from "../../../db/LadderMatch"; -import { ArtifactModel } from "../../../db/Artifact"; -import { AuthorBookModel } from "../../../db/AuthorBook"; -import { getIsExistLadderDefense } from "../../../services/ladderService"; - - -export default function (app: Application) { - new HandlerService(app, {}); - return new FriendHandler(app); -} - -export class FriendHandler { - channelService: ChannelService; - - constructor(private app: Application) { - this.channelService = this.app.get('channelService'); - } - - // 获取推荐好友列表 - public async getRecommend(msg: {}, session: BackendSession) { - let roleId: string = session.get('roleId'); - - const day = getTimeFun().getBeforeHour(FRIEND.FRIEND_RECONMMEND_ACTIVETIME); - - const { lv, serverId: myServerId } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_MY_SERVER); - let nums = parseNumberList(FRIEND.FRIEND_RECONMMEND_LEVEL); - // let max = Math.max(...nums); - let recommendList = await RoleModel.find({ loginTime: { $gt: day }, hasInit: true }).limit(200).lean({ getters: true, virtuals: true }) - let allList: RoleType[] = [] - let sortedNum = nums.sort((a, b) => a - b); - for(let num of sortedNum) { - allList = recommendList.filter(cur => { return cur.lv >= lv - num && cur.lv <= lv + num }); - if(allList.length > FRIEND.FRIEND_RECONMMEND_NUM) break; - } - - // 筛掉自己今天申请过的人 - let applyList = await FriendApplyModel.getSentApplyList(roleId, getZeroPointD()); - allList = allList.filter(cur => { - return !applyList.find(ccur => ccur.roleId == cur.roleId); - }); - - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - - let myServerList = new Array(); - let otherServerList = new Array(); - for (let role of allList) { - let type = getRecommendType(myFriendRelation, roleId, role.roleId); - if (type == FRIEND_RELATION_TYPE.NORMAL) { - let param = new FriendRecommendParams(role); - param.setType(type); - - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - if (myServerId == serverId) { - myServerList.push(param); - } else { - otherServerList.push(param); - } - - } - } - - // 前4个是本服的,后4个随意,优先本服,其他补上 - let myServerLen = myServerList.length > FRIEND.FRIEND_RECONMMEND_SERVICE ? FRIEND.FRIEND_RECONMMEND_SERVICE : myServerList.length; - let list1: FriendRecommendParams[] = getRandEelm(myServerList, myServerLen); - - let otherServerLen = otherServerList.length > FRIEND.FRIEND_RECONMMEND_NUM - myServerLen ? FRIEND.FRIEND_RECONMMEND_NUM - myServerLen : otherServerList.length; - let list2: FriendRecommendParams[] = getRandEelm(otherServerList, otherServerLen); - - if (list2.length < FRIEND.FRIEND_RECONMMEND_NUM - myServerLen) { - if (myServerList.length <= FRIEND.FRIEND_RECONMMEND_NUM - list2.length) { - list1 = myServerList; - } else { - list1 = getRandEelm(myServerList, FRIEND.FRIEND_RECONMMEND_NUM - list2.length); - } - } - list1 = sortArrRandom(list1); - list2 = sortArrRandom(list2); - - let list = list1.concat(list2); - - return resResult(STATUS.SUCCESS, { list }); - } - - // 搜索好友 - public async searchUser(msg: { value: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - - let { value } = msg; - let allList = await RoleModel.searchByNameOrId(value); - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - - let list = new Array(); - for (let role of allList) { - let type = getRecommendType(myFriendRelation, roleId, role.roleId); - let param = new FriendRecommendParams(role); - param.setType(type); - - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - list.push(param); - } - - return resResult(STATUS.SUCCESS, { list }); - } - - // 申请 - public async applyFriend(msg: { roleIds: string[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleIds = msg.roleIds; - - const role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_ROLE_ID); - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - - let str = '', resultRoleIds = new Array(); - for (let hisRoleId of roleIds) { - let type = getRecommendType(myFriendRelation, roleId, hisRoleId); - if (type == FRIEND_RELATION_TYPE.HAS_FRIEND) { - str = getResStr(STATUS.FRIEND_HAS_ADD); continue; - } else if (type == FRIEND_RELATION_TYPE.HAS_BLOCKED) { - str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue; - } else if (type == FRIEND_RELATION_TYPE.MYSELF) { - str = getResStr(STATUS.FRIEND_YOURSELF); continue; - } - let hisRelation = await FriendRelationModel.findFriendByRole(hisRoleId, POPULATE_TYPE.NOT); - let hisType = getRecommendType(hisRelation, hisRoleId, roleId); - if(hisType == FRIEND_RELATION_TYPE.NORMAL) { - let incResult = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); - if (!incResult) { - str = getResStr(STATUS.FRIEND_HIS_APPLY_MAX); continue; - } - - let apply = await FriendApplyModel.createApply(hisRoleId, role); - resultRoleIds.push(hisRoleId); - let hisOnlineInfo = await getRoleOnlineInfo(hisRoleId); - if (hisOnlineInfo.isOnline) { - let myApply = await getMyApplyParam(apply.applyCode, role); - sendMessageToUserWithSuc(hisRoleId, PUSH_ROUTE.FRIEND_APPLY, { apply: myApply }, hisOnlineInfo.sid); - } - } - } - - return resResult(STATUS.SUCCESS, { - isSuccess: str == '', - msg: str, - roleIds: resultRoleIds - }); - } - - // 获取申请列表 - public async getApplyList(msg: {}, session: BackendSession) { - - let roleId: string = session.get('roleId'); - let result = await getApplyList(roleId); - return resResult(STATUS.SUCCESS, { - list: result - }); - } - - // (一键)同意/拒绝申请 - public async handleApply(msg: { applyCodeList: string[], isPass: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - - const serverId = session.get('serverId'); - - let { applyCodeList, isPass } = msg; - - let role = await RoleModel.findByRoleId(roleId); - let roles = new Array(); - let friendCnt = role.friendCnt; - - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - - let applyList = await FriendApplyModel.getApplyListByCode(applyCodeList); - let list = new Array(); - - let str = '', resultApplyCodeList = new Array(); - if (isPass) { - for (let apply of applyList) { - let type = getRecommendType(myFriendRelation, roleId, apply.frdRoleId); - if (type == FRIEND_RELATION_TYPE.HAS_FRIEND) { - str = getResStr(STATUS.FRIEND_HAS_ADD); - resultApplyCodeList.push(apply.applyCode); continue; - } else if (type == FRIEND_RELATION_TYPE.HAS_BLOCKED) { - resultApplyCodeList.push(apply.applyCode); - str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue; - } else if (type == FRIEND_RELATION_TYPE.MYSELF) { - resultApplyCodeList.push(apply.applyCode); - str = getResStr(STATUS.FRIEND_YOURSELF); continue; - } - - // 好友数量校验 - let friend = apply.friend; - str = await increaseFrdCnt(role, friend, friendCnt); - if (str != '') continue; - roles.push(friend); - - // 创建friendShip - let friendShip = await FriendShipModel.createFriendShip([roleId, friend.roleId]); - if (!friendShip) { - str = getResStr(STATUS.FRIEND_SHIP_CREATE_ERROR); continue; - } - - await FriendRelationModel.addFriend(roleId, friend, friendShip); - await FriendRelationModel.addFriend(friend.roleId, role, friendShip); - - let param = new FriendListParam(friend, roleId, friendShip); - let hisOnlineInfo = await getRoleOnlineInfo(friend.roleId); - param.setOnline(hisOnlineInfo.isOnline); - - let { serverId } = friend; - let serverName = await getServerName( serverId); - param.setServerName(serverId, serverName); - - param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); - list.push(param); - if (hisOnlineInfo.isOnline) { - let myParam = await getMyParamAsFriend(friendShip, role, friend.roleId); - sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.FRIEND_ADD, { friend: myParam }, hisOnlineInfo.sid); - } - - resultApplyCodeList.push(apply.applyCode); - } - } else { - resultApplyCodeList = applyCodeList; - } - - let deleteCount = await FriendApplyModel.deleteApply(resultApplyCodeList); - role = await RoleModel.increaseFriendApplyCnt(roleId, -1 * deleteCount, FRIEND.FRIEND_MANAGE_APPLICATION); - roles.push(role); - // 任务 - await checkTaskWithRoles(roleId, sid, TASK_TYPE.FRIEND_NUM, roles); - - // 特殊处理:如果他点一键同意,有很多人,这个单独的人就不做这个额外的提示,直接把他好友申请删掉就好 - if (str == getResStr(STATUS.FRIEND_HAS_ADD) && resultApplyCodeList.length > 1) str = ''; - - return resResult(STATUS.SUCCESS, { - isSuccess: str == '', - msg: str, - applyCodeList: resultApplyCodeList, - list, - friendCnt - }); - } - - // 获取好友列表 - public async getFriendList(msg: {}, session: BackendSession) { - let roleId: string = session.get('roleId'); - - let role = await RoleModel.findByRoleId(roleId); - let res = await getFriendList(role); - - return resResult(STATUS.SUCCESS, res); - } - - // 获取黑名单 - public async getBlackList(msg: {}, session: BackendSession) { - let roleId: string = session.get('roleId'); - - let role = await RoleModel.findByRoleId(roleId); - let list = new Array(); - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.BLACKLIST); - let blacklist = myRelation ? myRelation.blacklist : []; - for (let bl of blacklist) { - let friendRole = bl.role; - if (!friendRole) continue; - let param = new BlackListParam(friendRole); - let isOnline = await isRoleOnline(friendRole.roleId); - param.setOnline(isOnline); - - let { serverId } = friendRole; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - param.setType(FRIEND_RELATION_TYPE.HAS_BLOCKED); - - list.push(param); - - } - - let { friendCnt = 0, blockCnt = 0 } = role; - - return resResult(STATUS.SUCCESS, { - list, - friendCnt, blockCnt - }); - } - - - // 拉黑/移除 - public async setBlackList(msg: { roleId: string, type: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - - const serverId = session.get('serverId'); - let { roleId: hisRoleId, type } = msg; - - let role = await RoleModel.findByRoleId(roleId); - let friend: RoleType; - - let str = '', list = new Array(), frdRoleIds = new Array(), blackRoleIds = new Array(); - if (type == BLOCK_OPEATE.ADD) { // 拉黑 - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); - let friends = myRelation ? myRelation.friends : []; - let blacklist = myRelation ? myRelation.blacklist : []; - let curFriend = friends.find(cur => cur.roleId == hisRoleId); - let curBlack = blacklist.find(cur => cur.roleId == hisRoleId); - if (curBlack) { - return resResult(STATUS.FRIEND_BLACK_HAS_ADD); - } - - role = await RoleModel.increaseBlockCnt(roleId, 1, curFriend ? -1 : 0, FRIEND.FRIEND_BLACKLIST_MAX); // 增加黑名单人数 - if (!role) { - return resResult(STATUS.FRIEND_BLACK_MAX) - } - friend = await RoleModel.increaseFriendCnt(hisRoleId, curFriend ? -1 : 0); // 对方好友减少 - - let friendShip: FriendShipType; - if (!!curFriend) { - await FriendShipModel.clearValue([roleId, hisRoleId]); - friendShip = curFriend.friendShip; - } - - await FriendRelationModel.moveFromFriend(hisRoleId, role, friendShip, false, !!curFriend); //从对方好友删除 - await FriendRelationModel.moveFromFriend(roleId, friend, friendShip, true, !!curFriend); // 删除好友关系并拉黑 - await PrivateMessageModel.blockMsg(privateRoomId(roleId, hisRoleId)); // 屏蔽掉双方对话 - await delPrivateMsg(roleId, hisRoleId); - - let { myRecApplyCount, hisRecApplyCount } = await FriendApplyModel.deleteApplyByRoles(roleId, hisRoleId); // 删除双方的申请 - if(myRecApplyCount > 0) await RoleModel.increaseFriendApplyCnt(roleId, -1 * myRecApplyCount, FRIEND.FRIEND_MANAGE_APPLICATION); - if(hisRecApplyCount > 0) await RoleModel.increaseFriendApplyCnt(roleId, -1 * hisRecApplyCount, FRIEND.FRIEND_MANAGE_APPLICATION); - - let param = new BlackListParam(friend); - let { isOnline, sid } = await getRoleOnlineInfo(friend.roleId); - - if(isOnline && (!!curFriend || myRecApplyCount > 0 || hisRecApplyCount > 0)) { // 当你们双方为好友,或者你申请过她的好友,拉黑的时候通知一下他删列表 - await sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.SET_BLACK, { blackRoleIds: [roleId] }, sid); - } - - - param.setOnline(isOnline); - - let { serverId } = friend; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - param.setType(FRIEND_RELATION_TYPE.HAS_BLOCKED); - list.push(param); - frdRoleIds.push(hisRoleId); - } else if (type == BLOCK_OPEATE.REMOVE_FRIEND) { // 仅移除 - - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); - let friends = myRelation ? myRelation.friends : []; - let curFriend = friends.find(cur => cur.roleId == hisRoleId); - if (!curFriend) { - return resResult(STATUS.FRIEND_NOT_FOUND); - } - - role = await RoleModel.increaseFriendCnt(roleId, -1); // 减少好友 - if (!role) { - return resResult(STATUS.FRIEND_NOT_FOUND) - } - friend = await RoleModel.increaseFriendCnt(hisRoleId, -1); // 对方好友减少 - - let friendShip: FriendShipType; - - await FriendShipModel.clearValue([roleId, hisRoleId]); - friendShip = curFriend.friendShip; - - await FriendRelationModel.moveFromFriend(hisRoleId, role, friendShip, false, !!curFriend); //从对方好友删除 - await FriendRelationModel.moveFromFriend(roleId, friend, friendShip, false, !!curFriend); // 删除好友关系并拉黑 - - frdRoleIds.push(hisRoleId); - - } else if (type == BLOCK_OPEATE.REMOVE_BLACK || type == BLOCK_OPEATE.REMOVE_AND_APPLY) { - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.BLACKLIST); - let blacklist = myRelation ? myRelation.blacklist : []; - - let curFriend = blacklist.find(cur => cur.roleId == hisRoleId); - if (!curFriend) { - return resResult(STATUS.FRIEND_BLACK_NOT_FOUND); - } - - role = await RoleModel.increaseBlockCnt(roleId, -1, 0, 100); // 黑名单人数减 - if (!role) { - return resResult(STATUS.FRIEND_BLACK_MAX) - } - await FriendRelationModel.removeFromBlack(roleId, hisRoleId); - - if (type == BLOCK_OPEATE.REMOVE_AND_APPLY) { - // 申请好友 - friend = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); - if (!friend) { - str = getResStr(STATUS.FRIEND_HIS_APPLY_MAX); - } else { - let hisRelation = await FriendRelationModel.findFriendByRole(hisRoleId, POPULATE_TYPE.NOT); - let hisType = getRecommendType(hisRelation, hisRoleId, roleId); - if(hisType == FRIEND_RELATION_TYPE.NORMAL) { - let incResult = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); - if (incResult) { - let apply = await FriendApplyModel.createApply(hisRoleId, role); - let hisOnlineInfo = await getRoleOnlineInfo(hisRoleId); - if(hisOnlineInfo) { - let myApply = await getMyApplyParam(apply.applyCode, role); - sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.FRIEND_APPLY, { apply: myApply }, hisOnlineInfo.sid); - } - } - } - } - } - blackRoleIds.push(hisRoleId); - - } else { - return resResult(STATUS.WRONG_PARMS); - } - - let { friendCnt = 0, blockCnt = 0 } = role; - - // 任务 - await checkTaskWithRoles(roleId, sid, TASK_TYPE.FRIEND_NUM, [role, friend]); - return resResult(STATUS.SUCCESS, { - frdRoleIds, blackRoleIds, - isSuccess: str == '', - msg: str, - list, - friendCnt, blockCnt - }); - } - - // 赠送爱心/一键赠送 - public async sendHeart(msg: { roleId: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - - let { roleId: hisRoleId } = msg; - - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); // 好友关系,只有friendship被populate了 - let friends = myRelation ? myRelation.friends : []; - let arr = new Array(); - if (hisRoleId != '') { - let cur = friends.find(cur => cur.roleId == hisRoleId); - if (!cur) return resResult(STATUS.FRIEND_NOT_FOUND); - - arr.push(cur); - } else { - arr = friends; - } - let canSendList = await sortByBeSentHeart(roleId, arr); - - let { lv } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_LV); - let dicFriendLv = getDicFriendByLv(lv); - if (!dicFriendLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 情谊值有上限,送到上限为止 - let max = dicFriendLv.sendMax; - let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); - let { sendCnt: todaySendCnt = 0 } = frdPointRec || {}; - - let todaySendInc = 0; - let list = new Array(); - - let uids = []; - for (let relation of canSendList) { - - if (todaySendCnt + FRIEND.FRIEND_FRIENDPOINT_ADD > max) break; - let fs = relation.friendShip; - let ref = shouldRefresh(fs.refTime, new Date()); - let sendHeartRec = await FriendShipModel.sendHeart(roleId, relation.roleId, 1, FRIEND.FRIEND_RECEIVE_SINGLE, ref); - if (!sendHeartRec) continue; - - let param = new FriendValueListParam(relation.roleId, roleId, sendHeartRec); - list.push(param); - - todaySendCnt += FRIEND.FRIEND_FRIENDPOINT_ADD; - todaySendInc += FRIEND.FRIEND_FRIENDPOINT_ADD; - - let hisOnlineInfo = await getRoleOnlineInfo(relation.roleId); - if (hisOnlineInfo.isOnline) { - uids.push({ uid: relation.roleId, sid: hisOnlineInfo.sid }); - } - } - - sendMessageToUsersWithSuc(PUSH_ROUTE.FRIEND_SEND_HEART, { roleId }, uids); - if (todaySendInc <= 0) return resResult(STATUS.FRIEND_HAS_SENT); - - // 更新情谊值 - frdPointRec = await FriendPointModel.updateSendCntToday(roleId, roleName, todaySendInc, max, FRIEND_DROP_TYPE.SEND_GIFT); - // 活动任务 - if (todaySendInc > 0) { - await checkTask(serverId, roleId, sid, TASK_TYPE.FRIEND_SEND_HEART, { count: todaySendInc }); - } - - return resResult(STATUS.SUCCESS, { - todaySendCnt, list - }) - } - - - // 领取爱心/一键领取 - public async receiveHeart(msg: { roleId: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - - let { roleId: hisRoleId } = msg; - - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); // 好友关系,只有friendship被populate了 - let friends = myRelation ? myRelation.friends : []; - let arr = new Array(); - if (hisRoleId != '') { - let cur = friends.find(cur => cur.roleId == hisRoleId); - if (!cur) return resResult(STATUS.FRIEND_NOT_FOUND); - - arr.push(cur); - } else { - arr = friends; - } - let canReceiveList = await sortByBeSentHeart(roleId, arr); - - let { lv } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_LV); - let dicFriendLv = getDicFriendByLv(lv); - if (!dicFriendLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 情谊值有上限,到上限为止 - let max = dicFriendLv.receiveMax; - let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); - let { cnt: todayReceiveCnt = 0 } = frdPointRec || {}; - - let todayReceiveInc = 0; - let list = new Array(); - for (let relation of canReceiveList) { - if (relation.beSentHeart > 0) { - if (todayReceiveCnt + FRIEND.FRIEND_FRIENDPOINT_ADD > max) break; - - // 收取爱心 - let fs = relation.friendShip; - let ref = shouldRefresh(fs.refTime, new Date()); - let receiveHeartRec = await FriendShipModel.receiveHeart(roleId, relation.roleId, 1, relation.beSentHeart, ref); - if (!receiveHeartRec) continue; - - let param = new FriendValueListParam(relation.roleId, roleId, receiveHeartRec); - list.push(param); - - todayReceiveCnt += FRIEND.FRIEND_FRIENDPOINT_ADD; - todayReceiveInc += FRIEND.FRIEND_FRIENDPOINT_ADD; - } - } - if (todayReceiveInc <= 0) return resResult(STATUS.FRIEND_HAS_RECEIVE); - let fp = getFriendPointObject(todayReceiveInc); - let goods = await addItems(roleId, roleName, sid, [fp], ITEM_CHANGE_REASON.RECEIVE_FRIEND_HEART) - - frdPointRec = await FriendPointModel.updatePointToday(roleId, roleName, todayReceiveInc, max, FRIEND_DROP_TYPE.SEND_GIFT); - - return resResult(STATUS.SUCCESS, { - simpleGoods: goods, - todayReceiveCnt, list - }) - } - - // 赠送礼物 - public async sendPresent(msg: { roleId: string, items: RewardInter[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: string = session.get('serverId'); - - let { roleId: hisRoleId, items } = msg; - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND_NAME_ONLY); - let friends = myRelation ? myRelation.friends : []; - let curFriend = friends.find(cur => cur.roleId == hisRoleId); - if (!curFriend) return resResult(STATUS.FRIEND_NOT_FOUND); - - let friendValueInc = 0; - for (let { id, count } of items) { - let dicGood = gameData.goods.get(id); - if (!dicGood) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - - let dicItid = ITID.get(dicGood.itid); - if (dicItid.type == CONSUME_TYPE.FRIEND_FAVOUR) { - friendValueInc += dicGood.value * count; - } else { - return resResult(STATUS.WRONG_PARMS); - } - } - - let costResult = await handleCost(roleId, sid, items, ITEM_CHANGE_REASON.FRIEND_SEND_PRESENT); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let result = await FriendShipModel.addFriendValue(roleId, hisRoleId, friendValueInc); - if (!result) return resResult(STATUS.FRIEND_NOT_FOUND); - - await FriendPresentLogModel.createRecord(roleId, hisRoleId, items); - for (let { id, count } of items) { - let relation = getRecommendType(myRelation, roleId, hisRoleId); - const msgData = await createPrivateMsg(roleId, roleName, MSG_TYPE.RICH_TEXT, MSG_SOURCE.PRIVATE_SEND_GIFT, JSON.stringify({ id, count }), hisRoleId, null, relation); - await pushMsgToRole(msgData); - // let hisRole = curFriend.role; - // await pushPresent(roleId, roleName, serverId, hisRole.roleName, id); - } - - return resResult(STATUS.SUCCESS, { - roleId: hisRoleId, - ...result - }); - } - - async getPlayerSimpleInfo(msg: { roleId: string }, session: BackendSession) { - - let roleId: string = session.get('roleId'); - - let { roleId: targetRoleId } = msg; - let isRobot = checkRoleIsRobot(targetRoleId); - if(isRobot) { - let role = await RoleModel.findByRoleId(roleId, null, true); - let sysType = getRobotSysType(targetRoleId); - let addObj: any = { roleId: makeRobotId(''), roleName: '', guildName: '' }; - if(sysType == ROBOT_SYS_TYPE.COM_BTL) { - let comBattle = await ComBattleTeamModel.findByRoleId(targetRoleId); - if(comBattle) { - addObj = comBattle.roleStatus.find(cur => cur.roleId == targetRoleId)||{}; - } - } - let param = new FriendRecommendParams({...role, ...addObj}); - param.setType(FRIEND_RELATION_TYPE.ROBOT); - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - return resResult(STATUS.SUCCESS, {...param, isRobot }); - } else { - - let role = await RoleModel.findByRoleId(targetRoleId, null, true); - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - - let type = getRecommendType(myFriendRelation, roleId, role.roleId); - let param = new FriendRecommendParams(role); - param.setType(type); - - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - return resResult(STATUS.SUCCESS, {...param, isRobot, isExistLadderDefense: await getIsExistLadderDefense(targetRoleId) }); - } - - } - - async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { - - // let roleId = session.get('roleId'); - let { roleId: oppoRoleId } = msg; - - let result: PlayerDetail; - - let dbHeroes = await HeroModel.findAndSortByCe(oppoRoleId); - let role = await RoleModel.findByRoleId(oppoRoleId, null, true); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let { topLineupCe, towerLv, showLineup } = role; - - let heroes = new Array(); - for (let curHero of dbHeroes.slice(0, 18)) { - let hero = new PlayerDetailHero(); - hero.setByDbHero(curHero); - heroes.push(hero); - } - - result = new PlayerDetail(oppoRoleId, heroes); - if (showLineup) { // 设置过展示阵容 - let heroes = new Array(); - for (let hid of showLineup) { - let curHero = dbHeroes.find(cur => cur.hid == hid); - if (curHero) { - let hero = new PlayerDetailHero(); - hero.setByDbHero(curHero); - heroes.push(hero); - } - } - result.setShowLineup(heroes); - } - - result.setPlayer(role); - result.setCe(topLineupCe); - - let ladder = await LadderMatchModel.findByRoleId(oppoRoleId); - result.setWarStar(role.warStar, ladder?.rank||0, towerLv - 1); - - return resResult(STATUS.SUCCESS, result); - } - - // 查看对象武将详细 - public async getHeroDetail(msg: { roleId: string, hids: number[] }, session: BackendSession) { - let roleId: string = session.get('roleId'); - // let sid: string = session.get('sid'); - - let { roleId: hisRoleId, hids } = msg; - - let role = await RoleModel.findByRoleId(hisRoleId, 'title'); - if (!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let roleCe = await RoleCeModel.findByRoleId(hisRoleId); - if (!roleCe) return resResult(STATUS.ROLE_NOT_FOUND); - - let heroList = await HeroModel.findByHidRange(hids, hisRoleId, HERO_SELECT.HERO_DETAIL, true); - if (heroList.length <= 0) return resResult(STATUS.HERO_NOT_FIND); - - let jewels = await JewelModel.findMapbyRoleAndHids(hisRoleId, hids); - - let school = await getSchoolPoint(hisRoleId); - - let authorBooks = await AuthorBookModel.findByRoleId(hisRoleId, '-_id bookId progress'); - - let myRoleCe = await RoleCeModel.findByRoleId(roleId); - if (!myRoleCe) return resResult(STATUS.ROLE_NOT_FOUND); - let mycalCe = new CalCe(roleId); - mycalCe.setRoleCe(myRoleCe); - - let calCe = new CalCe(hisRoleId); - calCe.setRoleCe(roleCe); - let attrByHid = await getHeroesAttributes(hisRoleId); - let list: HeroDetailParam[] = []; - for (let hero of heroList) { - let attr = attrByHid.get(hero.hid); - if(!attr) continue; - let attributes = attr.getMainAttributes(); - let heroParam = new HeroDetailParam(hero); - heroParam.setAttributes(attributes); - heroParam.setJewels(jewels); - if(hero.artifact) { - let artifact = await ArtifactModel.findbySeqId(hisRoleId, hero.artifact); - if(artifact) heroParam.setArtifact(artifact); - } - - heroParam.setRole( - role.title, - calCe.calSingleGlobalPartCe(hero.hid, 'scroll'), - calCe.calSingleGlobalPartCe(hero.hid, 'teraph'), - school - ); - heroParam.setMyRole( - mycalCe.calSingleGlobalPartCe(hero.hid, 'scroll'), - mycalCe.calSingleGlobalPartCe(hero.hid, 'teraph') - ) - heroParam.setAuthorBook(authorBooks); - - list.push(heroParam); - } - - - return resResult(STATUS.SUCCESS, { list }); - } - -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService, } from "pinus"; +import { resResult, getRandEelm, getResStr, shouldRefresh, sortArrRandom, checkRoleIsRobot, getRobotSysType, makeRobotId, parseNumberList } from "@pubUtils/util"; +import { STATUS, ROLE_SELECT, FRIEND_DROP_TYPE, FRIEND_RELATION_TYPE, POPULATE_TYPE, BLOCK_OPEATE, CONSUME_TYPE, ITID, HERO_SELECT, REDIS_KEY, MSG_SOURCE, MSG_TYPE, TASK_TYPE, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, PUSH_ROUTE } from "../../../consts"; +import { RoleModel, RoleType } from "@db/Role"; +import { getTimeFun, getZeroPointD } from "@pubUtils/timeUtil"; +import { FriendApplyModel } from "@db/FriendApply"; +import { FriendListParam, FriendRecommendParams, BlackListParam, FriendValueListParam, HeroDetailParam } from "@domain/roleField/friend"; +import { FriendShipModel, FriendShipType } from "@db/FriendShip"; +import { FriendRelationModel, Relation } from "@db/FriendRelation"; +import { isRoleOnline, getServerName, getRoleOnlineInfo } from "../../../services/redisService"; +import { increaseFrdCnt, getRecommendType, sortByBeSentHeart, getApplyList, getFriendList, getMyApplyParam, getMyParamAsFriend } from "../../../services/friendService"; +import { FriendPointModel } from "@db/FriendPoint"; +import { gameData, getDicFriendByLv } from "@pubUtils/data"; +import { addItems, getFriendPointObject, handleCost } from "../../../services/role/rewardService"; +import { RewardInter } from "@pubUtils/interface"; +import { FriendPresentLogModel } from '@db/FriendPresentLog'; +import { HeroModel, EPlace } from "@db/Hero"; +import { FRIEND } from "@pubUtils/dicParam"; +import { PlayerDetail, PlayerDetailHero } from "@domain/battleField/guild"; +import { createPrivateMsg, delPrivateMsg, privateRoomId, pushMsgToRole, pushPresent } from "../../../services/chatService"; +import { Rank } from "../../../services/rankService"; +import { checkTaskWithRoles, checkTask } from "../../../services/task/taskService"; +import { ComBattleTeamModel } from "@db/ComBattleTeam"; +import { JewelModel } from "@db/Jewel"; +import { getHeroesAttributes } from "../../../services/playerCeService"; +import { sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from "../../../services/pushService"; +import { PrivateMessageModel } from "@db/PrivateMessage"; +import { RoleCeModel } from "@db/RoleCe"; +import { CalCe } from "../../../services/role/calCe"; +import { getSchoolPoint } from "../../../services/roleService"; +import { LadderMatchModel } from "@db/LadderMatch"; +import { ArtifactModel } from "@db/Artifact"; +import { AuthorBookModel } from "@db/AuthorBook"; +import { getIsExistLadderDefense } from "../../../services/ladderService"; + + +export default function (app: Application) { + new HandlerService(app, {}); + return new FriendHandler(app); +} + +export class FriendHandler { + channelService: ChannelService; + + constructor(private app: Application) { + this.channelService = this.app.get('channelService'); + } + + // 获取推荐好友列表 + public async getRecommend(msg: {}, session: BackendSession) { + let roleId: string = session.get('roleId'); + + const day = getTimeFun().getBeforeHour(FRIEND.FRIEND_RECONMMEND_ACTIVETIME); + + const { lv, serverId: myServerId } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_MY_SERVER); + let nums = parseNumberList(FRIEND.FRIEND_RECONMMEND_LEVEL); + // let max = Math.max(...nums); + let recommendList = await RoleModel.find({ loginTime: { $gt: day }, hasInit: true }).limit(200).lean({ getters: true, virtuals: true }) + let allList: RoleType[] = [] + let sortedNum = nums.sort((a, b) => a - b); + for(let num of sortedNum) { + allList = recommendList.filter(cur => { return cur.lv >= lv - num && cur.lv <= lv + num }); + if(allList.length > FRIEND.FRIEND_RECONMMEND_NUM) break; + } + + // 筛掉自己今天申请过的人 + let applyList = await FriendApplyModel.getSentApplyList(roleId, getZeroPointD()); + allList = allList.filter(cur => { + return !applyList.find(ccur => ccur.roleId == cur.roleId); + }); + + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + + let myServerList = new Array(); + let otherServerList = new Array(); + for (let role of allList) { + let type = getRecommendType(myFriendRelation, roleId, role.roleId); + if (type == FRIEND_RELATION_TYPE.NORMAL) { + let param = new FriendRecommendParams(role); + param.setType(type); + + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + if (myServerId == serverId) { + myServerList.push(param); + } else { + otherServerList.push(param); + } + + } + } + + // 前4个是本服的,后4个随意,优先本服,其他补上 + let myServerLen = myServerList.length > FRIEND.FRIEND_RECONMMEND_SERVICE ? FRIEND.FRIEND_RECONMMEND_SERVICE : myServerList.length; + let list1: FriendRecommendParams[] = getRandEelm(myServerList, myServerLen); + + let otherServerLen = otherServerList.length > FRIEND.FRIEND_RECONMMEND_NUM - myServerLen ? FRIEND.FRIEND_RECONMMEND_NUM - myServerLen : otherServerList.length; + let list2: FriendRecommendParams[] = getRandEelm(otherServerList, otherServerLen); + + if (list2.length < FRIEND.FRIEND_RECONMMEND_NUM - myServerLen) { + if (myServerList.length <= FRIEND.FRIEND_RECONMMEND_NUM - list2.length) { + list1 = myServerList; + } else { + list1 = getRandEelm(myServerList, FRIEND.FRIEND_RECONMMEND_NUM - list2.length); + } + } + list1 = sortArrRandom(list1); + list2 = sortArrRandom(list2); + + let list = list1.concat(list2); + + return resResult(STATUS.SUCCESS, { list }); + } + + // 搜索好友 + public async searchUser(msg: { value: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + + let { value } = msg; + let allList = await RoleModel.searchByNameOrId(value); + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + + let list = new Array(); + for (let role of allList) { + let type = getRecommendType(myFriendRelation, roleId, role.roleId); + let param = new FriendRecommendParams(role); + param.setType(type); + + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + list.push(param); + } + + return resResult(STATUS.SUCCESS, { list }); + } + + // 申请 + public async applyFriend(msg: { roleIds: string[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleIds = msg.roleIds; + + const role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_ROLE_ID); + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + + let str = '', resultRoleIds = new Array(); + for (let hisRoleId of roleIds) { + let type = getRecommendType(myFriendRelation, roleId, hisRoleId); + if (type == FRIEND_RELATION_TYPE.HAS_FRIEND) { + str = getResStr(STATUS.FRIEND_HAS_ADD); continue; + } else if (type == FRIEND_RELATION_TYPE.HAS_BLOCKED) { + str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue; + } else if (type == FRIEND_RELATION_TYPE.MYSELF) { + str = getResStr(STATUS.FRIEND_YOURSELF); continue; + } + let hisRelation = await FriendRelationModel.findFriendByRole(hisRoleId, POPULATE_TYPE.NOT); + let hisType = getRecommendType(hisRelation, hisRoleId, roleId); + if(hisType == FRIEND_RELATION_TYPE.NORMAL) { + let incResult = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); + if (!incResult) { + str = getResStr(STATUS.FRIEND_HIS_APPLY_MAX); continue; + } + + let apply = await FriendApplyModel.createApply(hisRoleId, role); + resultRoleIds.push(hisRoleId); + let hisOnlineInfo = await getRoleOnlineInfo(hisRoleId); + if (hisOnlineInfo.isOnline) { + let myApply = await getMyApplyParam(apply.applyCode, role); + sendMessageToUserWithSuc(hisRoleId, PUSH_ROUTE.FRIEND_APPLY, { apply: myApply }, hisOnlineInfo.sid); + } + } + } + + return resResult(STATUS.SUCCESS, { + isSuccess: str == '', + msg: str, + roleIds: resultRoleIds + }); + } + + // 获取申请列表 + public async getApplyList(msg: {}, session: BackendSession) { + + let roleId: string = session.get('roleId'); + let result = await getApplyList(roleId); + return resResult(STATUS.SUCCESS, { + list: result + }); + } + + // (一键)同意/拒绝申请 + public async handleApply(msg: { applyCodeList: string[], isPass: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + + const serverId = session.get('serverId'); + + let { applyCodeList, isPass } = msg; + + let role = await RoleModel.findByRoleId(roleId); + let roles = new Array(); + let friendCnt = role.friendCnt; + + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + + let applyList = await FriendApplyModel.getApplyListByCode(applyCodeList); + let list = new Array(); + + let str = '', resultApplyCodeList = new Array(); + if (isPass) { + for (let apply of applyList) { + let type = getRecommendType(myFriendRelation, roleId, apply.frdRoleId); + if (type == FRIEND_RELATION_TYPE.HAS_FRIEND) { + str = getResStr(STATUS.FRIEND_HAS_ADD); + resultApplyCodeList.push(apply.applyCode); continue; + } else if (type == FRIEND_RELATION_TYPE.HAS_BLOCKED) { + resultApplyCodeList.push(apply.applyCode); + str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue; + } else if (type == FRIEND_RELATION_TYPE.MYSELF) { + resultApplyCodeList.push(apply.applyCode); + str = getResStr(STATUS.FRIEND_YOURSELF); continue; + } + + // 好友数量校验 + let friend = apply.friend; + str = await increaseFrdCnt(role, friend, friendCnt); + if (str != '') continue; + roles.push(friend); + + // 创建friendShip + let friendShip = await FriendShipModel.createFriendShip([roleId, friend.roleId]); + if (!friendShip) { + str = getResStr(STATUS.FRIEND_SHIP_CREATE_ERROR); continue; + } + + await FriendRelationModel.addFriend(roleId, friend, friendShip); + await FriendRelationModel.addFriend(friend.roleId, role, friendShip); + + let param = new FriendListParam(friend, roleId, friendShip); + let hisOnlineInfo = await getRoleOnlineInfo(friend.roleId); + param.setOnline(hisOnlineInfo.isOnline); + + let { serverId } = friend; + let serverName = await getServerName( serverId); + param.setServerName(serverId, serverName); + + param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); + list.push(param); + if (hisOnlineInfo.isOnline) { + let myParam = await getMyParamAsFriend(friendShip, role, friend.roleId); + sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.FRIEND_ADD, { friend: myParam }, hisOnlineInfo.sid); + } + + resultApplyCodeList.push(apply.applyCode); + } + } else { + resultApplyCodeList = applyCodeList; + } + + let deleteCount = await FriendApplyModel.deleteApply(resultApplyCodeList); + role = await RoleModel.increaseFriendApplyCnt(roleId, -1 * deleteCount, FRIEND.FRIEND_MANAGE_APPLICATION); + roles.push(role); + // 任务 + await checkTaskWithRoles(roleId, sid, TASK_TYPE.FRIEND_NUM, roles); + + // 特殊处理:如果他点一键同意,有很多人,这个单独的人就不做这个额外的提示,直接把他好友申请删掉就好 + if (str == getResStr(STATUS.FRIEND_HAS_ADD) && resultApplyCodeList.length > 1) str = ''; + + return resResult(STATUS.SUCCESS, { + isSuccess: str == '', + msg: str, + applyCodeList: resultApplyCodeList, + list, + friendCnt + }); + } + + // 获取好友列表 + public async getFriendList(msg: {}, session: BackendSession) { + let roleId: string = session.get('roleId'); + + let role = await RoleModel.findByRoleId(roleId); + let res = await getFriendList(role); + + return resResult(STATUS.SUCCESS, res); + } + + // 获取黑名单 + public async getBlackList(msg: {}, session: BackendSession) { + let roleId: string = session.get('roleId'); + + let role = await RoleModel.findByRoleId(roleId); + let list = new Array(); + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.BLACKLIST); + let blacklist = myRelation ? myRelation.blacklist : []; + for (let bl of blacklist) { + let friendRole = bl.role; + if (!friendRole) continue; + let param = new BlackListParam(friendRole); + let isOnline = await isRoleOnline(friendRole.roleId); + param.setOnline(isOnline); + + let { serverId } = friendRole; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + param.setType(FRIEND_RELATION_TYPE.HAS_BLOCKED); + + list.push(param); + + } + + let { friendCnt = 0, blockCnt = 0 } = role; + + return resResult(STATUS.SUCCESS, { + list, + friendCnt, blockCnt + }); + } + + + // 拉黑/移除 + public async setBlackList(msg: { roleId: string, type: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + + const serverId = session.get('serverId'); + let { roleId: hisRoleId, type } = msg; + + let role = await RoleModel.findByRoleId(roleId); + let friend: RoleType; + + let str = '', list = new Array(), frdRoleIds = new Array(), blackRoleIds = new Array(); + if (type == BLOCK_OPEATE.ADD) { // 拉黑 + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); + let friends = myRelation ? myRelation.friends : []; + let blacklist = myRelation ? myRelation.blacklist : []; + let curFriend = friends.find(cur => cur.roleId == hisRoleId); + let curBlack = blacklist.find(cur => cur.roleId == hisRoleId); + if (curBlack) { + return resResult(STATUS.FRIEND_BLACK_HAS_ADD); + } + + role = await RoleModel.increaseBlockCnt(roleId, 1, curFriend ? -1 : 0, FRIEND.FRIEND_BLACKLIST_MAX); // 增加黑名单人数 + if (!role) { + return resResult(STATUS.FRIEND_BLACK_MAX) + } + friend = await RoleModel.increaseFriendCnt(hisRoleId, curFriend ? -1 : 0); // 对方好友减少 + + let friendShip: FriendShipType; + if (!!curFriend) { + await FriendShipModel.clearValue([roleId, hisRoleId]); + friendShip = curFriend.friendShip; + } + + await FriendRelationModel.moveFromFriend(hisRoleId, role, friendShip, false, !!curFriend); //从对方好友删除 + await FriendRelationModel.moveFromFriend(roleId, friend, friendShip, true, !!curFriend); // 删除好友关系并拉黑 + await PrivateMessageModel.blockMsg(privateRoomId(roleId, hisRoleId)); // 屏蔽掉双方对话 + await delPrivateMsg(roleId, hisRoleId); + + let { myRecApplyCount, hisRecApplyCount } = await FriendApplyModel.deleteApplyByRoles(roleId, hisRoleId); // 删除双方的申请 + if(myRecApplyCount > 0) await RoleModel.increaseFriendApplyCnt(roleId, -1 * myRecApplyCount, FRIEND.FRIEND_MANAGE_APPLICATION); + if(hisRecApplyCount > 0) await RoleModel.increaseFriendApplyCnt(roleId, -1 * hisRecApplyCount, FRIEND.FRIEND_MANAGE_APPLICATION); + + let param = new BlackListParam(friend); + let { isOnline, sid } = await getRoleOnlineInfo(friend.roleId); + + if(isOnline && (!!curFriend || myRecApplyCount > 0 || hisRecApplyCount > 0)) { // 当你们双方为好友,或者你申请过她的好友,拉黑的时候通知一下他删列表 + await sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.SET_BLACK, { blackRoleIds: [roleId] }, sid); + } + + + param.setOnline(isOnline); + + let { serverId } = friend; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + param.setType(FRIEND_RELATION_TYPE.HAS_BLOCKED); + list.push(param); + frdRoleIds.push(hisRoleId); + } else if (type == BLOCK_OPEATE.REMOVE_FRIEND) { // 仅移除 + + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); + let friends = myRelation ? myRelation.friends : []; + let curFriend = friends.find(cur => cur.roleId == hisRoleId); + if (!curFriend) { + return resResult(STATUS.FRIEND_NOT_FOUND); + } + + role = await RoleModel.increaseFriendCnt(roleId, -1); // 减少好友 + if (!role) { + return resResult(STATUS.FRIEND_NOT_FOUND) + } + friend = await RoleModel.increaseFriendCnt(hisRoleId, -1); // 对方好友减少 + + let friendShip: FriendShipType; + + await FriendShipModel.clearValue([roleId, hisRoleId]); + friendShip = curFriend.friendShip; + + await FriendRelationModel.moveFromFriend(hisRoleId, role, friendShip, false, !!curFriend); //从对方好友删除 + await FriendRelationModel.moveFromFriend(roleId, friend, friendShip, false, !!curFriend); // 删除好友关系并拉黑 + + frdRoleIds.push(hisRoleId); + + } else if (type == BLOCK_OPEATE.REMOVE_BLACK || type == BLOCK_OPEATE.REMOVE_AND_APPLY) { + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.BLACKLIST); + let blacklist = myRelation ? myRelation.blacklist : []; + + let curFriend = blacklist.find(cur => cur.roleId == hisRoleId); + if (!curFriend) { + return resResult(STATUS.FRIEND_BLACK_NOT_FOUND); + } + + role = await RoleModel.increaseBlockCnt(roleId, -1, 0, 100); // 黑名单人数减 + if (!role) { + return resResult(STATUS.FRIEND_BLACK_MAX) + } + await FriendRelationModel.removeFromBlack(roleId, hisRoleId); + + if (type == BLOCK_OPEATE.REMOVE_AND_APPLY) { + // 申请好友 + friend = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); + if (!friend) { + str = getResStr(STATUS.FRIEND_HIS_APPLY_MAX); + } else { + let hisRelation = await FriendRelationModel.findFriendByRole(hisRoleId, POPULATE_TYPE.NOT); + let hisType = getRecommendType(hisRelation, hisRoleId, roleId); + if(hisType == FRIEND_RELATION_TYPE.NORMAL) { + let incResult = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, FRIEND.FRIEND_MANAGE_APPLICATION); + if (incResult) { + let apply = await FriendApplyModel.createApply(hisRoleId, role); + let hisOnlineInfo = await getRoleOnlineInfo(hisRoleId); + if(hisOnlineInfo) { + let myApply = await getMyApplyParam(apply.applyCode, role); + sendMessageToUserWithSuc(friend.roleId, PUSH_ROUTE.FRIEND_APPLY, { apply: myApply }, hisOnlineInfo.sid); + } + } + } + } + } + blackRoleIds.push(hisRoleId); + + } else { + return resResult(STATUS.WRONG_PARMS); + } + + let { friendCnt = 0, blockCnt = 0 } = role; + + // 任务 + await checkTaskWithRoles(roleId, sid, TASK_TYPE.FRIEND_NUM, [role, friend]); + return resResult(STATUS.SUCCESS, { + frdRoleIds, blackRoleIds, + isSuccess: str == '', + msg: str, + list, + friendCnt, blockCnt + }); + } + + // 赠送爱心/一键赠送 + public async sendHeart(msg: { roleId: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + + let { roleId: hisRoleId } = msg; + + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); // 好友关系,只有friendship被populate了 + let friends = myRelation ? myRelation.friends : []; + let arr = new Array(); + if (hisRoleId != '') { + let cur = friends.find(cur => cur.roleId == hisRoleId); + if (!cur) return resResult(STATUS.FRIEND_NOT_FOUND); + + arr.push(cur); + } else { + arr = friends; + } + let canSendList = await sortByBeSentHeart(roleId, arr); + + let { lv } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_LV); + let dicFriendLv = getDicFriendByLv(lv); + if (!dicFriendLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 情谊值有上限,送到上限为止 + let max = dicFriendLv.sendMax; + let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); + let { sendCnt: todaySendCnt = 0 } = frdPointRec || {}; + + let todaySendInc = 0; + let list = new Array(); + + let uids = []; + for (let relation of canSendList) { + + if (todaySendCnt + FRIEND.FRIEND_FRIENDPOINT_ADD > max) break; + let fs = relation.friendShip; + let ref = shouldRefresh(fs.refTime, new Date()); + let sendHeartRec = await FriendShipModel.sendHeart(roleId, relation.roleId, 1, FRIEND.FRIEND_RECEIVE_SINGLE, ref); + if (!sendHeartRec) continue; + + let param = new FriendValueListParam(relation.roleId, roleId, sendHeartRec); + list.push(param); + + todaySendCnt += FRIEND.FRIEND_FRIENDPOINT_ADD; + todaySendInc += FRIEND.FRIEND_FRIENDPOINT_ADD; + + let hisOnlineInfo = await getRoleOnlineInfo(relation.roleId); + if (hisOnlineInfo.isOnline) { + uids.push({ uid: relation.roleId, sid: hisOnlineInfo.sid }); + } + } + + sendMessageToUsersWithSuc(PUSH_ROUTE.FRIEND_SEND_HEART, { roleId }, uids); + if (todaySendInc <= 0) return resResult(STATUS.FRIEND_HAS_SENT); + + // 更新情谊值 + frdPointRec = await FriendPointModel.updateSendCntToday(roleId, roleName, todaySendInc, max, FRIEND_DROP_TYPE.SEND_GIFT); + // 活动任务 + if (todaySendInc > 0) { + await checkTask(serverId, roleId, sid, TASK_TYPE.FRIEND_SEND_HEART, { count: todaySendInc }); + } + + return resResult(STATUS.SUCCESS, { + todaySendCnt, list + }) + } + + + // 领取爱心/一键领取 + public async receiveHeart(msg: { roleId: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + + let { roleId: hisRoleId } = msg; + + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); // 好友关系,只有friendship被populate了 + let friends = myRelation ? myRelation.friends : []; + let arr = new Array(); + if (hisRoleId != '') { + let cur = friends.find(cur => cur.roleId == hisRoleId); + if (!cur) return resResult(STATUS.FRIEND_NOT_FOUND); + + arr.push(cur); + } else { + arr = friends; + } + let canReceiveList = await sortByBeSentHeart(roleId, arr); + + let { lv } = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_LV); + let dicFriendLv = getDicFriendByLv(lv); + if (!dicFriendLv) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 情谊值有上限,到上限为止 + let max = dicFriendLv.receiveMax; + let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); + let { cnt: todayReceiveCnt = 0 } = frdPointRec || {}; + + let todayReceiveInc = 0; + let list = new Array(); + for (let relation of canReceiveList) { + if (relation.beSentHeart > 0) { + if (todayReceiveCnt + FRIEND.FRIEND_FRIENDPOINT_ADD > max) break; + + // 收取爱心 + let fs = relation.friendShip; + let ref = shouldRefresh(fs.refTime, new Date()); + let receiveHeartRec = await FriendShipModel.receiveHeart(roleId, relation.roleId, 1, relation.beSentHeart, ref); + if (!receiveHeartRec) continue; + + let param = new FriendValueListParam(relation.roleId, roleId, receiveHeartRec); + list.push(param); + + todayReceiveCnt += FRIEND.FRIEND_FRIENDPOINT_ADD; + todayReceiveInc += FRIEND.FRIEND_FRIENDPOINT_ADD; + } + } + if (todayReceiveInc <= 0) return resResult(STATUS.FRIEND_HAS_RECEIVE); + let fp = getFriendPointObject(todayReceiveInc); + let goods = await addItems(roleId, roleName, sid, [fp], ITEM_CHANGE_REASON.RECEIVE_FRIEND_HEART) + + frdPointRec = await FriendPointModel.updatePointToday(roleId, roleName, todayReceiveInc, max, FRIEND_DROP_TYPE.SEND_GIFT); + + return resResult(STATUS.SUCCESS, { + simpleGoods: goods, + todayReceiveCnt, list + }) + } + + // 赠送礼物 + public async sendPresent(msg: { roleId: string, items: RewardInter[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: string = session.get('serverId'); + + let { roleId: hisRoleId, items } = msg; + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND_NAME_ONLY); + let friends = myRelation ? myRelation.friends : []; + let curFriend = friends.find(cur => cur.roleId == hisRoleId); + if (!curFriend) return resResult(STATUS.FRIEND_NOT_FOUND); + + let friendValueInc = 0; + for (let { id, count } of items) { + let dicGood = gameData.goods.get(id); + if (!dicGood) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + + let dicItid = ITID.get(dicGood.itid); + if (dicItid.type == CONSUME_TYPE.FRIEND_FAVOUR) { + friendValueInc += dicGood.value * count; + } else { + return resResult(STATUS.WRONG_PARMS); + } + } + + let costResult = await handleCost(roleId, sid, items, ITEM_CHANGE_REASON.FRIEND_SEND_PRESENT); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let result = await FriendShipModel.addFriendValue(roleId, hisRoleId, friendValueInc); + if (!result) return resResult(STATUS.FRIEND_NOT_FOUND); + + await FriendPresentLogModel.createRecord(roleId, hisRoleId, items); + for (let { id, count } of items) { + let relation = getRecommendType(myRelation, roleId, hisRoleId); + const msgData = await createPrivateMsg(roleId, roleName, MSG_TYPE.RICH_TEXT, MSG_SOURCE.PRIVATE_SEND_GIFT, JSON.stringify({ id, count }), hisRoleId, null, relation); + await pushMsgToRole(msgData); + // let hisRole = curFriend.role; + // await pushPresent(roleId, roleName, serverId, hisRole.roleName, id); + } + + return resResult(STATUS.SUCCESS, { + roleId: hisRoleId, + ...result + }); + } + + async getPlayerSimpleInfo(msg: { roleId: string }, session: BackendSession) { + + let roleId: string = session.get('roleId'); + + let { roleId: targetRoleId } = msg; + let isRobot = checkRoleIsRobot(targetRoleId); + if(isRobot) { + let role = await RoleModel.findByRoleId(roleId, null, true); + let sysType = getRobotSysType(targetRoleId); + let addObj: any = { roleId: makeRobotId(''), roleName: '', guildName: '' }; + if(sysType == ROBOT_SYS_TYPE.COM_BTL) { + let comBattle = await ComBattleTeamModel.findByRoleId(targetRoleId); + if(comBattle) { + addObj = comBattle.roleStatus.find(cur => cur.roleId == targetRoleId)||{}; + } + } + let param = new FriendRecommendParams({...role, ...addObj}); + param.setType(FRIEND_RELATION_TYPE.ROBOT); + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + return resResult(STATUS.SUCCESS, {...param, isRobot }); + } else { + + let role = await RoleModel.findByRoleId(targetRoleId, null, true); + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + + let type = getRecommendType(myFriendRelation, roleId, role.roleId); + let param = new FriendRecommendParams(role); + param.setType(type); + + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + return resResult(STATUS.SUCCESS, {...param, isRobot, isExistLadderDefense: await getIsExistLadderDefense(targetRoleId) }); + } + + } + + async getPlayerDetail(msg: { roleId: string }, session: BackendSession) { + + // let roleId = session.get('roleId'); + let { roleId: oppoRoleId } = msg; + + let result: PlayerDetail; + + let dbHeroes = await HeroModel.findAndSortByCe(oppoRoleId); + let role = await RoleModel.findByRoleId(oppoRoleId, null, true); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let { topLineupCe, towerLv, showLineup } = role; + + let heroes = new Array(); + for (let curHero of dbHeroes.slice(0, 18)) { + let hero = new PlayerDetailHero(); + hero.setByDbHero(curHero); + heroes.push(hero); + } + + result = new PlayerDetail(oppoRoleId, heroes); + if (showLineup) { // 设置过展示阵容 + let heroes = new Array(); + for (let hid of showLineup) { + let curHero = dbHeroes.find(cur => cur.hid == hid); + if (curHero) { + let hero = new PlayerDetailHero(); + hero.setByDbHero(curHero); + heroes.push(hero); + } + } + result.setShowLineup(heroes); + } + + result.setPlayer(role); + result.setCe(topLineupCe); + + let ladder = await LadderMatchModel.findByRoleId(oppoRoleId); + result.setWarStar(role.warStar, ladder?.rank||0, towerLv - 1); + + return resResult(STATUS.SUCCESS, result); + } + + // 查看对象武将详细 + public async getHeroDetail(msg: { roleId: string, hids: number[] }, session: BackendSession) { + let roleId: string = session.get('roleId'); + // let sid: string = session.get('sid'); + + let { roleId: hisRoleId, hids } = msg; + + let role = await RoleModel.findByRoleId(hisRoleId, 'title'); + if (!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let roleCe = await RoleCeModel.findByRoleId(hisRoleId); + if (!roleCe) return resResult(STATUS.ROLE_NOT_FOUND); + + let heroList = await HeroModel.findByHidRange(hids, hisRoleId, HERO_SELECT.HERO_DETAIL, true); + if (heroList.length <= 0) return resResult(STATUS.HERO_NOT_FIND); + + let jewels = await JewelModel.findMapbyRoleAndHids(hisRoleId, hids); + + let school = await getSchoolPoint(hisRoleId); + + let authorBooks = await AuthorBookModel.findByRoleId(hisRoleId, '-_id bookId progress'); + + let myRoleCe = await RoleCeModel.findByRoleId(roleId); + if (!myRoleCe) return resResult(STATUS.ROLE_NOT_FOUND); + let mycalCe = new CalCe(roleId); + mycalCe.setRoleCe(myRoleCe); + + let calCe = new CalCe(hisRoleId); + calCe.setRoleCe(roleCe); + let attrByHid = await getHeroesAttributes(hisRoleId); + let list: HeroDetailParam[] = []; + for (let hero of heroList) { + let attr = attrByHid.get(hero.hid); + if(!attr) continue; + let attributes = attr.getMainAttributes(); + let heroParam = new HeroDetailParam(hero); + heroParam.setAttributes(attributes); + heroParam.setJewels(jewels); + if(hero.artifact) { + let artifact = await ArtifactModel.findbySeqId(hisRoleId, hero.artifact); + if(artifact) heroParam.setArtifact(artifact); + } + + heroParam.setRole( + role.title, + calCe.calSingleGlobalPartCe(hero.hid, 'scroll'), + calCe.calSingleGlobalPartCe(hero.hid, 'teraph'), + school + ); + heroParam.setMyRole( + mycalCe.calSingleGlobalPartCe(hero.hid, 'scroll'), + mycalCe.calSingleGlobalPartCe(hero.hid, 'teraph') + ) + heroParam.setAuthorBook(authorBooks); + + list.push(heroParam); + } + + + return resResult(STATUS.SUCCESS, { list }); + } + +} + diff --git a/game-server/app/servers/role/handler/heroHandler.ts b/game-server/app/servers/role/handler/heroHandler.ts index d399b5612..c0455c106 100644 --- a/game-server/app/servers/role/handler/heroHandler.ts +++ b/game-server/app/servers/role/handler/heroHandler.ts @@ -1,1025 +1,1026 @@ -import { Application, BackendSession, ChannelService, HandlerService, } from 'pinus'; -import { handleCost, addItems, unlockFigure, getCoinObject, getGoldObject } from '../../../services/role/rewardService'; -import { resResult, deepCopy, parseGoodStr, swapFields } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { HeroModel, Connect, HeroSkin, HeroUpdate, EPlace, Talent, HeroType } from '../../../db/Hero'; -import { CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ABI_STAGE, DEBUG_MAGIC_WORD, HERO_INITIAL_QUALITY, REDIS_KEY, TASK_TYPE, ITEM_CHANGE_REASON, CHECK_HERO_CONSUME } from '../../../consts'; -import { RoleModel } from '../../../db/Role'; -import { ItemModel } from '../../../db/Item'; -import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, getHeroLvByExp, getMaxGradeByjobClass, getJobByGradeAndClass, getConnectLvByExp, getEquipByJobClassAndEPlace, getScollByStar, getExpByLv, getConnectMaxLv, getFriendShipByIdAndLv } from '../../../pubUtils/data'; -import { ItemInter, RewardInter } from '../../../pubUtils/interface'; -import { getDropItems, FIGURE_UNLOCK_CONDITION, ITID, DELICACY_GID, REBORN_ITEM } from '../../../consts/constModules/itemConst' -import { pushHeroStarMax, pushHeroWakeUp } from '../../../services/chatService'; -import { PvpDefenseModel } from '../../../db/PvpDefense'; -import { checkTask, checkTaskInHeroGiveFavor, checkTaskInHeroQUalityUp, checkTaskInHeroStarUp, checkTaskInHeroTrain, checkTaskInHeroWakeUp } from '../../../services/task/taskService'; -import { isNumber, pick } from 'underscore'; -import { updateEplaces } from '../../../services/equipService'; -import { addConnect, addConsumeToHero, calStarUpConsume, checkUnlockTalentCondition, getHeroNewEplace, getNewJob, initSkinTalent, updateSkinTalent } from '../../../services/roleService'; -import { JewelModel, JewelType, jewelUpdate } from '../../../db/Jewel'; -import { HERO, REBORN } from '../../../pubUtils/dicParam'; -import { createHero, createHeroes } from '../../../services/role/createHero'; -import { CheckMeterial } from '../../../services/role/checkMaterial'; -import { HeroParam } from '../../../domain/roleField/hero'; -import { calculateCeWithHero, calculateCeWithHeroes, calculateCeWithRole } from '../../../services/playerCeService'; -import { SchoolModel } from '../../../db/School'; -import { SkinModel } from '../../../db/Skin'; -import { RoleCeModel } from '../../../db/RoleCe'; -import { saveRebirthLog } from '../../../pubUtils/logUtil'; -import { isGoodsHidden, isHeroHidden } from '../../../services/dataService'; -import { LadderMatchModel } from '../../../db/LadderMatch'; -import { PvpSaveDataModel } from '../../../db/PvpSaveData'; -import { ArtifactModel } from '../../../db/Artifact'; -import { GVGVestigeRankModel } from '../../../db/GVGVestigeRank'; -import { GVGTeamModel } from '../../../db/GVGTeam'; -import { getResonanceDataMap } from '../../../services/role/resonanceService'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new HeroHandler(app); -} - -export class HeroHandler { - constructor(private app: Application) { - } - - // 武将碎片合成 - public async compose(msg: { hid: number }, session: BackendSession) { - - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { hid } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 检查是否存在武将 - let hasHero = await HeroModel.findByHidAndRole(hid, roleId); - if (hasHero) return resResult(STATUS.ROLE_HERO_EXISTS); - // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 - let { pieceId, pieceCount } = dicHero; - // 碎片数量是否足够 - let costResult = await handleCost(roleId, sid, [{ id: pieceId, count: pieceCount }], ITEM_CHANGE_REASON.COMPOSE_HERO); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - // createHero - let { heroes, resultHeroes } = await createHero(roleId, roleName, sid, serverId, { hid, count: 1 }); - - return resResult(STATUS.SUCCESS, { curHero: {hid}, addHeros: heroes }); - } - - // 武将升级 - public async lvUp(msg: { hid: number, type: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - - const serverId = session.get('serverId'); - - let { hid, type } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let addLv = 0; - if (type == 1) { - addLv = 1; - } else if (type == 5) { - addLv = 5; - } else { - return resResult(STATUS.ROLE_HERO_LV_TYPE_ERROR); - } - // 计算武将可以升的级数 - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - let { lv: playerLv } = await RoleModel.findByRoleId(roleId); - let { lv: oldLv, exp: oldExp } = hero; - if (oldLv >= playerLv) return resResult(STATUS.ROLE_HERO_LV_OVER); - if (oldLv + addLv > playerLv) addLv = playerLv - oldLv; - - let nextExp = getHeroExpByLv(oldLv + addLv - 1); - // console.log('nextExp', nextExp, oldLv + addLv - 1, oldExp) - let needExp = nextExp - oldExp; - let newExp = oldExp; - - // 计算得材料可转换的经验 - let originalConsumes = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.EXP); - let material = new Array(); - for (let { id, count } of originalConsumes) { - let dicGoods = gameData.goods.get(id); - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if(needExp < 0) break; - let _count = Math.ceil(needExp / dicGoods.value); - if (_count < count) { - material.push({ id, count: _count }); - newExp += dicGoods.value * _count; - needExp -= dicGoods.value * _count; - break; - } else { - if(count > 0) { - material.push({ id, count }); - newExp += dicGoods.value * count; - needExp -= dicGoods.value * count; - } - } - } - - if (newExp == oldExp) { - return resResult(STATUS.ROLE_EXP_NOT_ENOUGH); - } - - let newLv = getHeroLvByExp(newExp); - - let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_LV_UP); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let update = { - lv: newLv, - exp: newExp, - consumes: addConsumeToHero(hero.consumes, material) - } - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.LVUP, roleId, serverId, sid, hid, update); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.HERO_LV, { oldLv, hero: curHero }); - return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'lv', 'exp']), cost: material }); - - } - - // 武将升星 - public async starUp(msg: { hid: number, star: number, starStage: number, isOneClick: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - const serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - let { hid, star, starStage, isOneClick } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let { pieceId, jobid } = dicHero; - let dicJob = gameData.job.get(jobid); - if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - - let { star: oldStar, starStage: oldStarStage, quality } = hero; - // if (oldStar != star || oldStarStage != starStage) { - // return resResult(STATUS.WRONG_PARMS, { oldStarStage, oldStar, star, starStage }); - // } - if (oldStar == HERO_GROW_MAX.STAR) { - return resResult(STATUS.ROLE_STAR_REACH_MAX); - } - // 根据dic_zyz_hero_star 计算需要花的碎片并检查碎片数量 - const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, quality, oldStar); - if (!curDicHeroStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let newStarStage = oldStarStage; - let max = isOneClick ? ABI_STAGE.END : oldStarStage + 1; - let check = new CheckMeterial(roleId); - for (let i = oldStarStage; i < max; i++) { - - let isEnough = await check.decrease([{ id: pieceId, count: curDicHeroStar.advanceUpFragmentNum }]); - if(!isEnough) break; // 消耗不足 - newStarStage++; - } - if (newStarStage == oldStarStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_STAR_UP); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let isUpStar = newStarStage == ABI_STAGE.END; - - let update = { - star: isUpStar ? oldStar + 1 : oldStar, - starStage: isUpStar ? ABI_STAGE.START : newStarStage, - } - if(CHECK_HERO_CONSUME) { - update['consumes'] = addConsumeToHero(hero.consumes, consumes) - } - - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.STAR, roleId, serverId, sid, hid, update, { hid, hero, isUpStar }); - if (isUpStar) { - await checkTaskInHeroStarUp(serverId, roleId, sid, curHero, oldStar); // 任务 - await SchoolModel.updateByHid(roleId, hid, { hid, star: update.star }); - } - return resResult(STATUS.SUCCESS, { isUpStar, curHero: pick(curHero, ['hid', 'star', 'starStage', 'colorStar', 'colorStarStage']) }); - } - - // 武将升品 - public async qualityUp(msg: { hid: number, quality: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { hid, quality } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - // 根据dic_hero 获得 碎片id - let { pieceId } = dicHero; - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - let { quality: oldQuality, star } = hero; - // if (quality != oldQuality) { - // return resResult(STATUS.WRONG_PARMS); - // } - if (oldQuality == HERO_GROW_MAX.QUALITY) { - return resResult(STATUS.ROLE_QUALITY_REACH_MAX); - } - if (star != HERO_GROW_MAX.STAR) { - return resResult(STATUS.ROLE_STAR_NOT_ENOUGH); - } - - // 根据dic_zyz_hero_quality_up 获得需要的材料 - const curDicHeroQualityUp = gameData.heroQualityUp.get(oldQuality); - if (!curDicHeroQualityUp) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let { fragmentNum } = curDicHeroQualityUp; - - let material = [{ id: pieceId, count: fragmentNum }]; - let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_QUALITY_UP); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let update = { - quality: hero.quality + 1, - } - if(CHECK_HERO_CONSUME) { - update['consumes'] = addConsumeToHero(hero.consumes, material) - } - - await SchoolModel.updateByHid(roleId, hid, { hid, quality: update.quality }); - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.QUALITY, roleId, serverId, sid, hid, update, { hero }); - await checkTaskInHeroQUalityUp(serverId, roleId, sid, curHero); - // pushHeroQualityUpMsg(roleId, roleName, serverId, curHero); - return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'quality']) }); - } - - // 武将觉醒 - public async wakeUp(msg: { hid: number, colorStar: number, colorStarStage: number, isOneClick: boolean }, session: BackendSession) { - - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let roleName: string = session.get('roleName'); - const serverId = session.get('serverId'); - - let { hid, colorStar, colorStarStage, isOneClick } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let { pieceId, jobid } = dicHero; - let dicJob = gameData.job.get(jobid); - if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - - let { colorStar: oldColorStar, colorStarStage: oldColorStarStage, star, quality } = hero; - // if (colorStar != oldColorStar || colorStarStage != oldColorStarStage) { - // return resResult(STATUS.WRONG_PARMS); - // } - if (star != HERO_GROW_MAX.STAR) { - return resResult(STATUS.ROLE_WAKE_STAR_NOT_ENOUGH); - } - if (quality < HERO_GROW_MAX.QUALITY) { - return resResult(STATUS.ROLE_QUALITY_NOT_ENOUGH); - } - // 根据dic_zyz_hero_wake 计算需要花的碎片并检查碎片数量 - const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, oldColorStar) - if (!curDicHeroStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let newColorStarStage = oldColorStarStage; - let isWakeUp = oldColorStar == 0; - let check = new CheckMeterial(roleId); - if(isWakeUp) { - let { fragmentNum, consume } = curDicHeroStar; - let isEnough = await check.decrease([{ id: pieceId, count: fragmentNum }, ...consume]); - if(!isEnough) { - return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - }; - } else { - let max = isOneClick ? ABI_STAGE.END : oldColorStarStage + 1; - for (let i = oldColorStarStage; i < max; i++) { - let { fragmentNum, consume } = curDicHeroStar; - let isEnough = await check.decrease([{ id: pieceId, count: fragmentNum }, ...consume]); - if(!isEnough) break; // 消耗不足 - newColorStarStage++; - } - if (newColorStarStage == oldColorStarStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - let consumes = check.getConsume(); - // console.log('&&&&&&&&7', JSON.stringify(consumes)) - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_WAKE_UP); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let isUpStar = isWakeUp || newColorStarStage == ABI_STAGE.END; - - let update = { - quality: isWakeUp? quality + 1: quality, - colorStar: isUpStar ? oldColorStar + 1 : oldColorStar, - colorStarStage: isUpStar ? ABI_STAGE.START : newColorStarStage, - consumes: addConsumeToHero(hero.consumes, consumes) - } - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.COLORSTAR, roleId, serverId, sid, hid, update, { hero, isUpStar }); - if (isUpStar) { - await SchoolModel.updateByHid(roleId, hid, { hid, quality: update.quality, colorStar: update.colorStar }); - await checkTaskInHeroWakeUp(serverId, roleId, sid, curHero, oldColorStar); // 任务 - } - if (isWakeUp) pushHeroWakeUp(roleId, roleName, serverId, curHero); // 第一次觉醒 - pushHeroStarMax(roleId, roleName, serverId, curHero); - return resResult(STATUS.SUCCESS, { isUpStar, curHero: pick(curHero, ['hid', 'quality', 'star', 'starStage', 'colorStar', 'colorStarStage']) }); - } - - //训练 - async heroJobTrain(msg: { hid: number, isOneClick: boolean, canReplace: boolean }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - - const serverId = session.get('serverId'); - let { hid, isOneClick, canReplace = false } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let dicJob = gameData.job.get(hero.job); - if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if (hero.jobStage >= dicJob.maxStage) - return resResult(STATUS.HERO_JOB_STAGE_REACH_MAX_STAGE); - if (hero.job >= getMaxGradeByjobClass(dicJob.job_class)) - return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE); - - let newJobStage = hero.jobStage; - let oldJobStage = hero.jobStage, oldJob = hero.job; - let max = isOneClick ? dicJob.maxStage: hero.jobStage + 1; - let trainCount = 0; - let check = new CheckMeterial(roleId); - check.setCanReplace(canReplace); - for(let i = hero.jobStage; i < max; i++) { - let singleConsume = dicJob.trainingConsume[i]; - if(!singleConsume) break; // 每天消耗不可训练 - - let isEnough = await check.decrease([singleConsume]); - if(!isEnough) break; // 消耗不足 - newJobStage ++; - trainCount++; - } - if (newJobStage == hero.jobStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - let consumes = check.getConsume(); - // console.log('#### consumes', consumes); - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_JOB_TRAIN); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - //重算战力并下发 - let update = { - job: hero.job, - jobStage: newJobStage, - consumes: addConsumeToHero(hero.consumes, consumes) - } - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TRAIN, roleId, serverId, sid, hid, update, { hero }); - await checkTaskInHeroTrain(serverId, roleId, sid, curHero, trainCount); // 任务 - return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'job', 'jobStage'])}); - } - - //进阶 - async heroJobStageUp(msg: { hid: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - const serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - let { hid } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) - return resResult(STATUS.HERO_NOT_FIND); - let curJob = hero.job; - let heroJob = gameData.job.get(curJob); - if (heroJob.unlockLevel > hero.lv) - return resResult(STATUS.NOT_REACH_UNLOCK_LEVEL); - if (curJob >= getMaxGradeByjobClass(heroJob.job_class)) - return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE); - let consumes = heroJob.upGradeConsume; - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_JOB_STAGEUP); - if (!result) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - let nextHeroJob = getJobByGradeAndClass(heroJob.job_class, heroJob.grade + 1); - if (!nextHeroJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - //重算战力并下发 - let update = { - job: nextHeroJob.jobid, - jobStage: 0, - consumes: addConsumeToHero(hero.consumes, consumes) - } - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.STAGEUP, roleId, serverId, sid, hid, update, { hid, hero }); - await checkTask(serverId, roleId, sid, TASK_TYPE.HERO_STAGE_UP, { hero: curHero, stageUpCnt: 1 }); // 任务 - const heroResult = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'job', 'jobStage', 'totalTalentPoint']) }}); - } - - //赠送(包括一键赠送) - async heroGiveFavor(msg: { hid: number, shipId: number, type: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { hid, shipId, type } = msg; - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); - - let dicFriendShip = getFriendShipByIdAndLv(hid, shipId, 1); - if(!dicFriendShip) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let heroes = await HeroModel.findByHidRange(dicFriendShip.hids, roleId); - if (heroes.length < dicFriendShip.hids.length) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - let hero = heroes.find(cur => cur.hid == hid); - if(!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - let { connections = []} = hero; - let curConnect = connections.find(cur => cur.shipId == shipId); - let { level: oldLv = 0, exp: oldExp = 0 } = curConnect||{}; - - let addLv = 0; - if (type == 1) { - addLv = 1; - } else if (type == 5) { - addLv = 5; - } else { - return resResult(STATUS.WRONG_PARMS); - } - - let maxLv = getConnectMaxLv(hid, shipId); // 好感度最大等级 - if (maxLv <= oldLv) - return resResult(STATUS.HERO_FAVOUR_LEVEL_REACH_MAXT); - - // 计算武将可以升的级数 - if (oldLv + addLv > maxLv) addLv = maxLv - oldLv; - - let nextObj = getFriendShipByIdAndLv(hid, shipId, oldLv + addLv); - if (!nextObj) return resResult(STATUS.HERO_FAVOUR_LEVEL_REACH_MAXT); - let nextExp = nextObj.shipExp; - let needExp = nextExp - oldExp; - let newExp = oldExp; - - // 计算得材料可转换的经验 - let originalConsumes = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.FAVOUR); - let material = new Array(); - for (let { id, count } of originalConsumes) { - let dicGoods = gameData.goods.get(id); - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let needCount = Math.ceil(needExp / dicGoods.value); - if(needCount <= 0) break; - if(needCount > count) needCount = count; - material.push({ id, count: needCount }); - newExp += dicGoods.value * needCount; - needExp -= dicGoods.value * count; - } - - if (newExp == oldExp) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - - let addItem: RewardInter[] = []; - let { newLv: newLevel, overExp } = getConnectLvByExp(hid, shipId, newExp); - let saveMaterial: RewardInter[] = []; - for(let { id, count } of material) { - if(count > 0) saveMaterial.push({ id, count}); - } - if(newLevel == maxLv && overExp > 0 && material.length > 0) { - let dicGoods = gameData.goods.get(saveMaterial[0].id); - if(!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - addItem.push({ id: DELICACY_GID, count: Math.floor(overExp/10) }); - saveMaterial.push({ id: DELICACY_GID, count: Math.floor((dicGoods.value - overExp)/10) }); - saveMaterial[0].count--; - saveMaterial = saveMaterial.filter(cur => cur.count > 0); - } - - let result = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_GIVE_FAVOR); - if (!result) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - - let updateConsume = addConsumeToHero(hero.consumes, saveMaterial); - let newConnections = addConnect(connections, { shipId, level: newLevel, exp: newExp }); - let update = { - connections: newConnections, - consumes: updateConsume - } - let goods = await addItems(roleId, roleName, sid, addItem, ITEM_CHANGE_REASON.HERO_GIVE_FAVOR); - - let isLv = oldLv != newLevel; - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.CONNECT, roleId, serverId, sid, hero.hid, update, { shipId }); - if(isLv) { - // await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.HERO_FAVOR, paramHid: curHero.hid, paramFavourLv: curHero.favourLv }]); - await checkTaskInHeroGiveFavor(serverId, roleId, sid, shipId, newConnections, connections); - } - return resResult(STATUS.SUCCESS, { curHero: { ...pick(curHero, ['hid', 'connections']), shipId }, goods }); - } - - //穿带时装 - async heroWearSkin(msg: { id: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { id } = msg; - if(isGoodsHidden(id)) return resResult(STATUS.FASHION_IS_HIDDEN); - let dicSkin = gameData.fashion.get(id); - // console.log('*****', id, dicSkin) - if (!dicSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); - if(isHeroHidden(dicSkin.actorId)) return resResult(STATUS.HERO_IS_HIDDEN); - - let hero = await HeroModel.findByHidAndRole(dicSkin.actorId, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let newHeroSkins: HeroSkin[] = []; - let result = false; - let lastSkinId: number; - for (let skin of hero.skins) { - if (skin.id == id) { - if (!!skin.enable) { - return resResult(STATUS.HERO_SKIN_IS_EQUIPED); - } - newHeroSkins.push({ ...skin, enable: true }); - result = true; - } else { - if (!!skin.enable) { - lastSkinId = skin.skinId; - } - newHeroSkins.push({ ...skin, enable: false }); - } - } - if (!result) { - return resResult(STATUS.HERO_SKIN_NOT_FIND); - } - - let dicHero = gameData.hero.get(dicSkin.heroId); - let dicMyJob = gameData.job.get(hero.job); - let dicNewJob = getJobByGradeAndClass(dicHero.jobClass, dicMyJob.grade); - - let oldEplace = hero.ePlace||[]; - let eplaceIds = new Map(); // 更新了的装备栏id - for(let { id } of oldEplace) { - let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id); - eplaceIds.set(id, { equipId: dicEquip.id }); - } - - let { newEplace } = updateEplaces(oldEplace, eplaceIds); - let update = { - skins: newHeroSkins, - skinId: dicSkin.heroId, - job: dicNewJob.jobid, - ePlace: newEplace - } - let artifact = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SKIN, roleId, serverId, sid, hero.hid, update, { hero, artifact }); - let resultHero = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: {...pick(resultHero, ['hid', 'skins', 'skinId', 'job', 'talent', 'usedTalentPoint']), ePlace: newEplace }}); - } - - public async previewRebirth(msg: { hid: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let { hid } = msg; - - let hero = await HeroModel.findByHidAndRole(hid, roleId, 'hid consumes star starStage quality'); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - let { consumes} = calStarUpConsume(hero); - - return resResult(STATUS.SUCCESS, { previewGoods: consumes.filter(consume => consume.count > 0) }); - } - - public async rebirth(msg: { hid: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { hid } = msg; - if(!isNumber(hid) && !hid) return resResult(STATUS.WRONG_PARMS); - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_REBIRTH); - - // 武将初始,但是皮肤这里不初始 - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - - // 消耗 - if(hero.lv >= REBORN.REBORON_FREE_LEVEL) { - let cost = [getGoldObject(REBORN.REBORON_HERO)]; - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.REBIRTH); - if(!costResult) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - } - - // 皮肤处理 - let { skins, skinId, ce, scrollActive, quality, star, starStage } = hero; - let dicHero = gameData.hero.get(skinId); - let dicJob = getJobByGradeAndClass(dicHero.jobClass, 0); - - let { consumes: consumesResult, newConsumes } = calStarUpConsume(hero); - - let newSkins = initSkinTalent(skins); - let newQuality = quality >= 3? ( dicHero.quality >= 3? dicHero.quality: 3 ): quality; - let dicHeroScroll = getScollByStar(dicHero.quality, star, newQuality, dicHero.initialColorStar); - let initInfo = HeroModel.getInitInfo(hid, { - artifact: hero.artifact, - job: dicJob.jobid, skins: newSkins, skinId, ce, - star, starStage, colorStar: dicHero.initialColorStar, colorStarStage: 0, quality: newQuality, - scrollActive: scrollActive, - scrollId: scrollActive? dicHeroScroll.id: 0, - scrollStar: scrollActive? dicHeroScroll.stars: 0, - scrollQuality: scrollActive? dicHeroScroll.qualityUp: 0, - scrollColorStar: scrollActive? dicHeroScroll.colorstars: 0, - consumes: newConsumes - }); - - // 天晶石 - let curJewels: jewelUpdate[] = []; - for(let { jewel, id } of hero.ePlace) { - if(jewel > 0) { - let jewelInfo = await JewelModel.putOnOrOff(jewel, 0, id); - curJewels.push({ - seqId: jewelInfo.seqId, - id: jewelInfo.id, - hid: jewelInfo.hid, - }); - } - } - - let school = await SchoolModel.findByHid(roleId, hid); - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.REBIRTH, roleId, serverId, sid, hid, initInfo, { schoolId: school?.schoolId }); - let goods = await addItems(roleId, roleName, sid, consumesResult, ITEM_CHANGE_REASON.REBIRTH); - saveRebirthLog(session, hero); - - const heroResult = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: heroResult, curJewels, goods }); - } - - // 解锁天赋 - public async unlockTalent(msg: { hid: number, id: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let { hid, id } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let dicHeroTalent = gameData.heroTalent.get(id); - if(!dicHeroTalent) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - - let skins = hero.skins||[]; - let curSkin = skins.find(cur => cur.enable); - if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); - - let talent = curSkin.talent.find(cur => cur.id == id); - if(talent) return resResult(STATUS.TALENT_HAS_UNLOCKED); - - let usedTalentPoint = curSkin.usedTalentPoint; - if(!checkUnlockTalentCondition(curSkin.skinId, id, curSkin.talent, usedTalentPoint)) { - return resResult(STATUS.TALENT_CONDITION_NOT_FIT); - } - - let totalTalentPoint = gameData.talentPointOfJob.get(hero.job); - let needTalentPoint = dicHeroTalent.level.find(cur => cur.lv == 1)?.cost||0; - if(totalTalentPoint - usedTalentPoint - needTalentPoint < 0) { - return resResult(STATUS.TALENT_POINT_NOT_ENOUGH); - } - - let { newSkins } = updateSkinTalent(skins, new Talent(id), usedTalentPoint + needTalentPoint); - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_UNLOCK, roleId, serverId, sid, hid, { skins: newSkins }, { talentId: id }); - const heroResult = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); - - } - - // 升级天赋 - public async upgradeTalent(msg: { hid: number, id: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let { hid, id } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let dicHeroTalent = gameData.heroTalent.get(id); - if(!dicHeroTalent) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - - let skins = hero.skins||[]; - let curSkin = skins.find(cur => cur.enable); - if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); - - let talent = curSkin.talent.find(cur => cur.id == id); - if(!talent) return resResult(STATUS.TALENT_NOT_UNLOCKED); - - let usedTalentPoint = curSkin.usedTalentPoint; - let totalTalentPoint = gameData.talentPointOfJob.get(hero.job); - let nextLv = dicHeroTalent.level.find(cur => cur.lv == talent.level + 1); - if(!nextLv) return resResult(STATUS.TALENT_LEVEL_MAX); - let needTalentPoint = nextLv.cost||0; - if(totalTalentPoint - usedTalentPoint - needTalentPoint < 0) { - return resResult(STATUS.TALENT_POINT_NOT_ENOUGH); - } - - let { newSkins } = updateSkinTalent(skins, new Talent(id, talent.level + 1), usedTalentPoint + needTalentPoint); - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_LV, roleId, serverId, sid, hid, { skins: newSkins }, { talentId: id }); - const heroResult = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); - } - - // 洗点 - public async resetTalent(msg: { hid: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let { hid } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - - let skins = hero.skins||[]; - let curSkin = skins.find(cur => cur.enable); - if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); - - let costItem = parseGoodStr(HERO.HERO_TALENTPOINT_RESET); - let consumeResult = await handleCost(roleId, sid, costItem, ITEM_CHANGE_REASON.RESET_TALENT); - if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - - let newSkins = initSkinTalent(skins); - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_RESET, roleId, serverId, sid, hid, { skins: newSkins }); - - const heroResult = new HeroParam(curHero); - return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); - } - - - // 设置副将 - async setSubHero(msg: { hid: number, subHid: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let { hid, subHid: subSkinId } = msg; - - let dicHero = gameData.hero.get(hid); - if(!dicHero || dicHero.urType != 1) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) return resResult(STATUS.HERO_NOT_FIND); - - let subHid = 0; - if(subSkinId > 0) { // 设置上 - if(hero.subHid == subSkinId) return resResult(STATUS.SUCCESS, { preHid: hero.subActorId, curHero: pick(hero, ['hid', 'subHid', 'subActorId']) }); - let dicHero = gameData.hero.get(subSkinId); - if(!dicHero || dicHero.urType == 1) return resResult(STATUS.HERO_CAN_NOT_BE_SET_SUB); - subHid = dicHero.actorId; - - let subHero = await HeroModel.findByHidAndRole(subHid, roleId); - if(!subHero) return resResult(STATUS.HERO_NOT_FIND); - - // await LadderMatchModel.removeBySub(roleId, subHid); - // await PvpSaveDataModel.removeBySub(roleId, subHid); - // await PvpDefenseModel.removeBySub(roleId, subHid); - // await GVGVestigeRankModel.removeBySub(roleId, subHid); - // await GVGTeamModel.removeBySub(roleId, subHid, subHero.ce); - - } else { // 卸下 - if(!hero.subHid) return resResult(STATUS.SUCCESS, { preHid: hero.subActorId, curHero: pick(hero, ['hid', 'subHid', 'subActorId']) }); - } - - // 设置副将 - const { preHid, curHero } = await HeroModel.setSubHero(roleId, hid, subSkinId, subHid); - - return resResult(STATUS.SUCCESS, { preHid, curHero: pick(curHero, ['hid', 'subHid', 'subActorId']) }); - } - - - /** - * 重生 武将等级、装备养成、职业进阶上养成度对换,升星、羁绊不对换,双方的职业天赋树均重置 - * @param msg - * @param session - */ - public async heroReborn(msg: { originHid: number, targetHid: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - const { originHid, targetHid } = msg; - - let { dbResonanceMap } = await getResonanceDataMap(roleId); - if(dbResonanceMap.has(originHid) || dbResonanceMap.has(targetHid)) return resResult(STATUS.RESONANCE__HID_NOT_REBIRTH); - - - let dbHeros = await HeroModel.findByHidsAndRole(roleId, [originHid, targetHid]); - if (dbHeros.length != 2) return resResult(STATUS.HERO_NOT_FIND); - const heroMap = dbHeros.reduce((map, obj) => { map.set(obj.hid, obj); return map; }, new Map()); - let originHero = heroMap.get(originHid); - let targetHero = heroMap.get(targetHid); - - //交换 lv exp jobStage - swapFields(originHero || {}, targetHero || {}, ['lv', 'exp', 'jobStage']); - - //交换job - let originJob = originHero.job, targetJob = targetHero.job - originHero.job = getNewJob(originHero, targetJob); - targetHero.job = getNewJob(targetHero, originJob); - - //天赋树置空 - if (originHero.skins || originHero.skins.length > 0) originHero.skins = initSkinTalent(originHero.skins); - if (targetHero.skins || targetHero.skins.length > 0) targetHero.skins = initSkinTalent(targetHero.skins); - - //装备养成交换 - let tempOriginEPlace = [], tempTargetEPlace = [] - if (originHero.ePlace || targetHero.ePlace.length > 0) tempOriginEPlace = getHeroNewEplace(originHero, targetHero?.ePlace || []); - if (targetHero.ePlace || originHero.ePlace.length > 0) tempTargetEPlace = getHeroNewEplace(targetHero, originHero?.ePlace || []); - - originHero.ePlace = tempOriginEPlace; - targetHero.ePlace = tempTargetEPlace; - // 天晶地玉 - let jewels: JewelType[] = []; - let curJewels: jewelUpdate[] = []; - for (let { jewel } of originHero.ePlace) { - if (jewel == 0) continue; - let result = await JewelModel.updateInfo(jewel, { hid: targetHid }); - if (!result) return resResult(STATUS.HERO_NOT_FIND); - jewels.push(result); - curJewels.push({ seqId:result.seqId, hid:result.hid}); - } - for (let { jewel } of targetHero.ePlace) { - if (jewel == 0) continue; - let result = await JewelModel.updateInfo(jewel, { hid: originHid }); - if (!result) return resResult(STATUS.HERO_NOT_FIND); - jewels.push(result); - curJewels.push({ seqId:result.seqId, hid:result.hid}); - } - - // 消耗 - let originalConsumes = originHero.consumes||[]; - let targetConsumes = targetHero.consumes||[]; - originHero.consumes = [...targetConsumes.filter(cur => REBORN_ITEM.includes(cur.id)), ...originalConsumes.filter(cur => !REBORN_ITEM.includes(cur.id))]; - targetHero.consumes = [...originalConsumes.filter(cur => REBORN_ITEM.includes(cur.id)), ...targetConsumes.filter(cur => !REBORN_ITEM.includes(cur.id))]; - - let cost = [getGoldObject(REBORN.EXCHANGE_COST)]; - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.REBORN_COST); - if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let heroesRet: HeroType[] = []; - for (let hero of [originHero, targetHero]) { - let result = await HeroModel.updateHeroInfo(roleId, hero.hid, { ...pick(hero, ['lv','exp', 'job', 'jobStage', 'ePlace', 'skins', 'consumes']) }); - if (!result) return resResult(STATUS.HERO_NOT_FIND); - heroesRet.push(result); - } - - let artifacts = await ArtifactModel.findbyHids(roleId, [originHid, targetHid]); - - // 战力重算 - let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.REBORN_CAL, roleId, serverId, sid, heroesRet, { jewels, heroes: heroesRet, artifacts }); - - let curHeroes = []; - for (let hero of (heroes || [])) { - const heroResult = new HeroParam(hero); - curHeroes.push({ ...pick(heroResult, ['seqId', 'hid', 'ce','exp', 'lv', 'job', 'jobStage', 'ePlace', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }); - } - - return resResult(STATUS.SUCCESS, { curHeroes, curJewels }) - } - - - // ! debug接口 一键全武将 - public async debugGetAllHeroes(msg: { magicWord: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - await HeroModel.deleteAccount(roleId); - await JewelModel.deleteAccount(roleId); - await SkinModel.deleteMany({ roleId }); - await SchoolModel.deleteAccount(roleId); - await RoleCeModel.deleteMany({ roleId }); - await RoleModel.updateRoleInfo(roleId, { jewelCount: 0 }); - let heroInfos = []; - - for(let [actorId] of gameData.recruit) { - let dicHero = gameData.hero.get(actorId); - if(!dicHero) continue; - let { jobid, grade } = gameData.jobClassMaxGrades.get(dicHero.jobClass); - heroInfos.push({ - hid: actorId, star: 6, colorStar: 6, quality: 4, lv: 100, exp: getExpByLv(100).sum, job: jobid, grade - }); - } - let resultHeroes = await createHeroes(roleId, roleName, sid, serverId, heroInfos); - - return resResult(STATUS.SUCCESS, resultHeroes); - } - - - // ! 测试接口,用来测试前清理并初始化某个武将;代码抄自:gm-server/app/service/users.ts deleteHero - public async testCleanUp(msg: { magicWord: string, hid: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - - const { magicWord, hid } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.HERO_NOT_FIND); - await addItems(roleId, roleName, sid, [{ - id: dicHero.pieceId, count: dicHero.pieceCount * HERO_GROW_MAX.STAR * ABI_STAGE.END - }], ITEM_CHANGE_REASON.DEBUG); - - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - await HeroModel.deleteHero(roleId, hid); - let role = await RoleModel.findByRoleId(roleId); - await PvpDefenseModel.deleteHero(roleId, hid); - await RoleModel.updateRoleInfo(roleId, { topLineup: role.topLineup, topLineupCe: role.topLineupCe, ce: role.ce - hero.ce }); - return resResult(STATUS.SUCCESS); - } - - public async addItem(msg: { id: number, count: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - - let { id, count } = msg; - - //let result = await handleCost(roleId, sid, [{id, count}] ); - let items = [{ id, count }]; - let role = await RoleModel.findByRoleId(roleId); - if (id == 999999) { - items = getDropItems(); - if (role.lv < 60) { - role.lv = 60; - let roleLvInfo = gameData.kingexp.get(role.lv - 1); - role.exp = roleLvInfo.sum; - await RoleModel.updateRoleInfo(roleId, role); - } - } - let result = await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.DEBUG); - if (!result) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - return resResult(STATUS.SUCCESS, { goods: result, lv: role.lv, exp: role.exp }); - - } - - public async debugSetHero(msg: { magicWord: string, hid: number, params: HeroUpdate }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - let { magicWord, hid, params } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let hero = await HeroModel.findByHidAndRole(hid, roleId); - if(!hero) { - let { resultHeroes } = await createHero(roleId, roleName, sid, serverId, { hid, count: 1, ...params }); - return resResult(STATUS.SUCCESS, { hero: resultHeroes[0] }); - } else { - hero = await HeroModel.updateHeroInfo(roleId, hid, params); - return resResult(STATUS.SUCCESS, { hero: new HeroParam(hero) }); - } - - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService, } from 'pinus'; +import { handleCost, addItems, unlockFigure, getCoinObject, getGoldObject } from '../../../services/role/rewardService'; +import { resResult, deepCopy, parseGoodStr, swapFields } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { HeroModel, Connect, HeroSkin, HeroUpdate, EPlace, Talent, HeroType } from '@db/Hero'; +import { CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ABI_STAGE, DEBUG_MAGIC_WORD, HERO_INITIAL_QUALITY, REDIS_KEY, TASK_TYPE, ITEM_CHANGE_REASON, CHECK_HERO_CONSUME } from '../../../consts'; +import { RoleModel } from '@db/Role'; +import { ItemModel } from '@db/Item'; +import { gameData, getHeroExpByLv, getHeroStarByQuality, getHeroWakeByQuality, getHeroLvByExp, getMaxGradeByjobClass, getJobByGradeAndClass, getConnectLvByExp, getEquipByJobClassAndEPlace, getScollByStar, getExpByLv, getConnectMaxLv, getFriendShipByIdAndLv } from '@pubUtils/data'; +import { ItemInter, RewardInter } from '@pubUtils/interface'; +import { getDropItems, FIGURE_UNLOCK_CONDITION, ITID, DELICACY_GID, REBORN_ITEM } from '@consts/constModules/itemConst' +import { pushHeroStarMax, pushHeroWakeUp } from '../../../services/chatService'; +import { PvpDefenseModel } from '@db/PvpDefense'; +import { checkTask, checkTaskInHeroGiveFavor, checkTaskInHeroQUalityUp, checkTaskInHeroStarUp, checkTaskInHeroTrain, checkTaskInHeroWakeUp } from '../../../services/task/taskService'; +import { isNumber, pick } from 'underscore'; +import { updateEplaces } from '../../../services/equipService'; +import { addConnect, addConsumeToHero, calStarUpConsume, checkUnlockTalentCondition, getHeroNewEplace, getNewJob, initSkinTalent, updateSkinTalent } from '../../../services/roleService'; +import { JewelModel, JewelType, jewelUpdate } from '@db/Jewel'; +import { HERO, REBORN } from '@pubUtils/dicParam'; +import { createHero, createHeroes } from '../../../services/role/createHero'; +import { CheckMeterial } from '../../../services/role/checkMaterial'; +import { HeroParam } from '@domain/roleField/hero'; +import { calculateCeWithHero, calculateCeWithHeroes, calculateCeWithRole } from '../../../services/playerCeService'; +import { SchoolModel } from '@db/School'; +import { SkinModel } from '@db/Skin'; +import { RoleCeModel } from '@db/RoleCe'; +import { saveRebirthLog } from '@pubUtils/logUtil'; +import { isGoodsHidden, isHeroHidden } from '../../../services/dataService'; +import { LadderMatchModel } from '@db/LadderMatch'; +import { PvpSaveDataModel } from '@db/PvpSaveData'; +import { ArtifactModel } from '@db/Artifact'; +import { GVGVestigeRankModel } from '@db/GVGVestigeRank'; +import { GVGTeamModel } from '@db/GVGTeam'; +import { getResonanceDataMap } from '../../../services/role/resonanceService'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new HeroHandler(app); +} + +export class HeroHandler { + constructor(private app: Application) { + } + + // 武将碎片合成 + public async compose(msg: { hid: number }, session: BackendSession) { + + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { hid } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 检查是否存在武将 + let hasHero = await HeroModel.findByHidAndRole(hid, roleId); + if (hasHero) return resResult(STATUS.ROLE_HERO_EXISTS); + // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 + let { pieceId, pieceCount } = dicHero; + // 碎片数量是否足够 + let costResult = await handleCost(roleId, sid, [{ id: pieceId, count: pieceCount }], ITEM_CHANGE_REASON.COMPOSE_HERO); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + // createHero + let { heroes, resultHeroes } = await createHero(roleId, roleName, sid, serverId, { hid, count: 1 }); + + return resResult(STATUS.SUCCESS, { curHero: {hid}, addHeros: heroes }); + } + + // 武将升级 + public async lvUp(msg: { hid: number, type: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + + const serverId = session.get('serverId'); + + let { hid, type } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let addLv = 0; + if (type == 1) { + addLv = 1; + } else if (type == 5) { + addLv = 5; + } else { + return resResult(STATUS.ROLE_HERO_LV_TYPE_ERROR); + } + // 计算武将可以升的级数 + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + let { lv: playerLv } = await RoleModel.findByRoleId(roleId); + let { lv: oldLv, exp: oldExp } = hero; + if (oldLv >= playerLv) return resResult(STATUS.ROLE_HERO_LV_OVER); + if (oldLv + addLv > playerLv) addLv = playerLv - oldLv; + + let nextExp = getHeroExpByLv(oldLv + addLv - 1); + // console.log('nextExp', nextExp, oldLv + addLv - 1, oldExp) + let needExp = nextExp - oldExp; + let newExp = oldExp; + + // 计算得材料可转换的经验 + let originalConsumes = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.EXP); + let material = new Array(); + for (let { id, count } of originalConsumes) { + let dicGoods = gameData.goods.get(id); + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if(needExp < 0) break; + let _count = Math.ceil(needExp / dicGoods.value); + if (_count < count) { + material.push({ id, count: _count }); + newExp += dicGoods.value * _count; + needExp -= dicGoods.value * _count; + break; + } else { + if(count > 0) { + material.push({ id, count }); + newExp += dicGoods.value * count; + needExp -= dicGoods.value * count; + } + } + } + + if (newExp == oldExp) { + return resResult(STATUS.ROLE_EXP_NOT_ENOUGH); + } + + let newLv = getHeroLvByExp(newExp); + + let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_LV_UP); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let update = { + lv: newLv, + exp: newExp, + consumes: addConsumeToHero(hero.consumes, material) + } + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.LVUP, roleId, serverId, sid, hid, update); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.HERO_LV, { oldLv, hero: curHero }); + return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'lv', 'exp']), cost: material }); + + } + + // 武将升星 + public async starUp(msg: { hid: number, star: number, starStage: number, isOneClick: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + const serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + let { hid, star, starStage, isOneClick } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let { pieceId, jobid } = dicHero; + let dicJob = gameData.job.get(jobid); + if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + + let { star: oldStar, starStage: oldStarStage, quality } = hero; + // if (oldStar != star || oldStarStage != starStage) { + // return resResult(STATUS.WRONG_PARMS, { oldStarStage, oldStar, star, starStage }); + // } + if (oldStar == HERO_GROW_MAX.STAR) { + return resResult(STATUS.ROLE_STAR_REACH_MAX); + } + // 根据dic_zyz_hero_star 计算需要花的碎片并检查碎片数量 + const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, quality, oldStar); + if (!curDicHeroStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let newStarStage = oldStarStage; + let max = isOneClick ? ABI_STAGE.END : oldStarStage + 1; + let check = new CheckMeterial(roleId); + for (let i = oldStarStage; i < max; i++) { + + let isEnough = await check.decrease([{ id: pieceId, count: curDicHeroStar.advanceUpFragmentNum }]); + if(!isEnough) break; // 消耗不足 + newStarStage++; + } + if (newStarStage == oldStarStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_STAR_UP); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let isUpStar = newStarStage == ABI_STAGE.END; + + let update = { + star: isUpStar ? oldStar + 1 : oldStar, + starStage: isUpStar ? ABI_STAGE.START : newStarStage, + } + if(CHECK_HERO_CONSUME) { + update['consumes'] = addConsumeToHero(hero.consumes, consumes) + } + + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.STAR, roleId, serverId, sid, hid, update, { hid, hero, isUpStar }); + if (isUpStar) { + await checkTaskInHeroStarUp(serverId, roleId, sid, curHero, oldStar); // 任务 + await SchoolModel.updateByHid(roleId, hid, { hid, star: update.star }); + } + return resResult(STATUS.SUCCESS, { isUpStar, curHero: pick(curHero, ['hid', 'star', 'starStage', 'colorStar', 'colorStarStage']) }); + } + + // 武将升品 + public async qualityUp(msg: { hid: number, quality: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { hid, quality } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + // 根据dic_hero 获得 碎片id + let { pieceId } = dicHero; + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + let { quality: oldQuality, star } = hero; + // if (quality != oldQuality) { + // return resResult(STATUS.WRONG_PARMS); + // } + if (oldQuality == HERO_GROW_MAX.QUALITY) { + return resResult(STATUS.ROLE_QUALITY_REACH_MAX); + } + if (star != HERO_GROW_MAX.STAR) { + return resResult(STATUS.ROLE_STAR_NOT_ENOUGH); + } + + // 根据dic_zyz_hero_quality_up 获得需要的材料 + const curDicHeroQualityUp = gameData.heroQualityUp.get(oldQuality); + if (!curDicHeroQualityUp) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let { fragmentNum } = curDicHeroQualityUp; + + let material = [{ id: pieceId, count: fragmentNum }]; + let costResult = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_QUALITY_UP); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let update = { + quality: hero.quality + 1, + } + if(CHECK_HERO_CONSUME) { + update['consumes'] = addConsumeToHero(hero.consumes, material) + } + + await SchoolModel.updateByHid(roleId, hid, { hid, quality: update.quality }); + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.QUALITY, roleId, serverId, sid, hid, update, { hero }); + await checkTaskInHeroQUalityUp(serverId, roleId, sid, curHero); + // pushHeroQualityUpMsg(roleId, roleName, serverId, curHero); + return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'quality']) }); + } + + // 武将觉醒 + public async wakeUp(msg: { hid: number, colorStar: number, colorStarStage: number, isOneClick: boolean }, session: BackendSession) { + + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let roleName: string = session.get('roleName'); + const serverId = session.get('serverId'); + + let { hid, colorStar, colorStarStage, isOneClick } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + // 根据dic_hero 获得 1. 碎片id 2. 碎片数量 3. 初始武将星级 4. 初始品质 + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let { pieceId, jobid } = dicHero; + let dicJob = gameData.job.get(jobid); + if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + + let { colorStar: oldColorStar, colorStarStage: oldColorStarStage, star, quality } = hero; + // if (colorStar != oldColorStar || colorStarStage != oldColorStarStage) { + // return resResult(STATUS.WRONG_PARMS); + // } + if (star != HERO_GROW_MAX.STAR) { + return resResult(STATUS.ROLE_WAKE_STAR_NOT_ENOUGH); + } + if (quality < HERO_GROW_MAX.QUALITY) { + return resResult(STATUS.ROLE_QUALITY_NOT_ENOUGH); + } + // 根据dic_zyz_hero_wake 计算需要花的碎片并检查碎片数量 + const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, oldColorStar) + if (!curDicHeroStar) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let newColorStarStage = oldColorStarStage; + let isWakeUp = oldColorStar == 0; + let check = new CheckMeterial(roleId); + if(isWakeUp) { + let { fragmentNum, consume } = curDicHeroStar; + let isEnough = await check.decrease([{ id: pieceId, count: fragmentNum }, ...consume]); + if(!isEnough) { + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + }; + } else { + let max = isOneClick ? ABI_STAGE.END : oldColorStarStage + 1; + for (let i = oldColorStarStage; i < max; i++) { + let { fragmentNum, consume } = curDicHeroStar; + let isEnough = await check.decrease([{ id: pieceId, count: fragmentNum }, ...consume]); + if(!isEnough) break; // 消耗不足 + newColorStarStage++; + } + if (newColorStarStage == oldColorStarStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + let consumes = check.getConsume(); + // console.log('&&&&&&&&7', JSON.stringify(consumes)) + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_WAKE_UP); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let isUpStar = isWakeUp || newColorStarStage == ABI_STAGE.END; + + let update = { + quality: isWakeUp? quality + 1: quality, + colorStar: isUpStar ? oldColorStar + 1 : oldColorStar, + colorStarStage: isUpStar ? ABI_STAGE.START : newColorStarStage, + consumes: addConsumeToHero(hero.consumes, consumes) + } + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.COLORSTAR, roleId, serverId, sid, hid, update, { hero, isUpStar }); + if (isUpStar) { + await SchoolModel.updateByHid(roleId, hid, { hid, quality: update.quality, colorStar: update.colorStar }); + await checkTaskInHeroWakeUp(serverId, roleId, sid, curHero, oldColorStar); // 任务 + } + if (isWakeUp) pushHeroWakeUp(roleId, roleName, serverId, curHero); // 第一次觉醒 + pushHeroStarMax(roleId, roleName, serverId, curHero); + return resResult(STATUS.SUCCESS, { isUpStar, curHero: pick(curHero, ['hid', 'quality', 'star', 'starStage', 'colorStar', 'colorStarStage']) }); + } + + //训练 + async heroJobTrain(msg: { hid: number, isOneClick: boolean, canReplace: boolean }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + + const serverId = session.get('serverId'); + let { hid, isOneClick, canReplace = false } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let dicJob = gameData.job.get(hero.job); + if (!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + if (hero.jobStage >= dicJob.maxStage) + return resResult(STATUS.HERO_JOB_STAGE_REACH_MAX_STAGE); + if (hero.job >= getMaxGradeByjobClass(dicJob.job_class)) + return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE); + + let newJobStage = hero.jobStage; + let oldJobStage = hero.jobStage, oldJob = hero.job; + let max = isOneClick ? dicJob.maxStage: hero.jobStage + 1; + let trainCount = 0; + let check = new CheckMeterial(roleId); + check.setCanReplace(canReplace); + for(let i = hero.jobStage; i < max; i++) { + let singleConsume = dicJob.trainingConsume[i]; + if(!singleConsume) break; // 每天消耗不可训练 + + let isEnough = await check.decrease([singleConsume]); + if(!isEnough) break; // 消耗不足 + newJobStage ++; + trainCount++; + } + if (newJobStage == hero.jobStage) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + let consumes = check.getConsume(); + // console.log('#### consumes', consumes); + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_JOB_TRAIN); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + //重算战力并下发 + let update = { + job: hero.job, + jobStage: newJobStage, + consumes: addConsumeToHero(hero.consumes, consumes) + } + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TRAIN, roleId, serverId, sid, hid, update, { hero }); + await checkTaskInHeroTrain(serverId, roleId, sid, curHero, trainCount); // 任务 + return resResult(STATUS.SUCCESS, { curHero: pick(curHero, ['hid', 'job', 'jobStage'])}); + } + + //进阶 + async heroJobStageUp(msg: { hid: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + const serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + let { hid } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) + return resResult(STATUS.HERO_NOT_FIND); + let curJob = hero.job; + let heroJob = gameData.job.get(curJob); + if (heroJob.unlockLevel > hero.lv) + return resResult(STATUS.NOT_REACH_UNLOCK_LEVEL); + if (curJob >= getMaxGradeByjobClass(heroJob.job_class)) + return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE); + let consumes = heroJob.upGradeConsume; + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.HERO_JOB_STAGEUP); + if (!result) { + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + } + let nextHeroJob = getJobByGradeAndClass(heroJob.job_class, heroJob.grade + 1); + if (!nextHeroJob) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + //重算战力并下发 + let update = { + job: nextHeroJob.jobid, + jobStage: 0, + consumes: addConsumeToHero(hero.consumes, consumes) + } + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.STAGEUP, roleId, serverId, sid, hid, update, { hid, hero }); + await checkTask(serverId, roleId, sid, TASK_TYPE.HERO_STAGE_UP, { hero: curHero, stageUpCnt: 1 }); // 任务 + const heroResult = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'job', 'jobStage', 'totalTalentPoint']) }}); + } + + //赠送(包括一键赠送) + async heroGiveFavor(msg: { hid: number, shipId: number, type: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { hid, shipId, type } = msg; + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_CAN); + + let dicFriendShip = getFriendShipByIdAndLv(hid, shipId, 1); + if(!dicFriendShip) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let heroes = await HeroModel.findByHidRange(dicFriendShip.hids, roleId); + if (heroes.length < dicFriendShip.hids.length) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + let hero = heroes.find(cur => cur.hid == hid); + if(!hero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + let { connections = []} = hero; + let curConnect = connections.find(cur => cur.shipId == shipId); + let { level: oldLv = 0, exp: oldExp = 0 } = curConnect||{}; + + let addLv = 0; + if (type == 1) { + addLv = 1; + } else if (type == 5) { + addLv = 5; + } else { + return resResult(STATUS.WRONG_PARMS); + } + + let maxLv = getConnectMaxLv(hid, shipId); // 好感度最大等级 + if (maxLv <= oldLv) + return resResult(STATUS.HERO_FAVOUR_LEVEL_REACH_MAXT); + + // 计算武将可以升的级数 + if (oldLv + addLv > maxLv) addLv = maxLv - oldLv; + + let nextObj = getFriendShipByIdAndLv(hid, shipId, oldLv + addLv); + if (!nextObj) return resResult(STATUS.HERO_FAVOUR_LEVEL_REACH_MAXT); + let nextExp = nextObj.shipExp; + let needExp = nextExp - oldExp; + let newExp = oldExp; + + // 计算得材料可转换的经验 + let originalConsumes = await ItemModel.findByRoleAndType(roleId, CONSUME_TYPE.FAVOUR); + let material = new Array(); + for (let { id, count } of originalConsumes) { + let dicGoods = gameData.goods.get(id); + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let needCount = Math.ceil(needExp / dicGoods.value); + if(needCount <= 0) break; + if(needCount > count) needCount = count; + material.push({ id, count: needCount }); + newExp += dicGoods.value * needCount; + needExp -= dicGoods.value * count; + } + + if (newExp == oldExp) { + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + } + + let addItem: RewardInter[] = []; + let { newLv: newLevel, overExp } = getConnectLvByExp(hid, shipId, newExp); + let saveMaterial: RewardInter[] = []; + for(let { id, count } of material) { + if(count > 0) saveMaterial.push({ id, count}); + } + if(newLevel == maxLv && overExp > 0 && material.length > 0) { + let dicGoods = gameData.goods.get(saveMaterial[0].id); + if(!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + addItem.push({ id: DELICACY_GID, count: Math.floor(overExp/10) }); + saveMaterial.push({ id: DELICACY_GID, count: Math.floor((dicGoods.value - overExp)/10) }); + saveMaterial[0].count--; + saveMaterial = saveMaterial.filter(cur => cur.count > 0); + } + + let result = await handleCost(roleId, sid, material, ITEM_CHANGE_REASON.HERO_GIVE_FAVOR); + if (!result) { + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + } + + let updateConsume = addConsumeToHero(hero.consumes, saveMaterial); + let newConnections = addConnect(connections, { shipId, level: newLevel, exp: newExp }); + let update = { + connections: newConnections, + consumes: updateConsume + } + let goods = await addItems(roleId, roleName, sid, addItem, ITEM_CHANGE_REASON.HERO_GIVE_FAVOR); + + let isLv = oldLv != newLevel; + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.CONNECT, roleId, serverId, sid, hero.hid, update, { shipId }); + if(isLv) { + // await unlockFigure(sid, roleId, [{ type: FIGURE_UNLOCK_CONDITION.HERO_FAVOR, paramHid: curHero.hid, paramFavourLv: curHero.favourLv }]); + await checkTaskInHeroGiveFavor(serverId, roleId, sid, shipId, newConnections, connections); + } + return resResult(STATUS.SUCCESS, { curHero: { ...pick(curHero, ['hid', 'connections']), shipId }, goods }); + } + + //穿带时装 + async heroWearSkin(msg: { id: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { id } = msg; + if(isGoodsHidden(id)) return resResult(STATUS.FASHION_IS_HIDDEN); + let dicSkin = gameData.fashion.get(id); + // console.log('*****', id, dicSkin) + if (!dicSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); + if(isHeroHidden(dicSkin.actorId)) return resResult(STATUS.HERO_IS_HIDDEN); + + let hero = await HeroModel.findByHidAndRole(dicSkin.actorId, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let newHeroSkins: HeroSkin[] = []; + let result = false; + let lastSkinId: number; + for (let skin of hero.skins) { + if (skin.id == id) { + if (!!skin.enable) { + return resResult(STATUS.HERO_SKIN_IS_EQUIPED); + } + newHeroSkins.push({ ...skin, enable: true }); + result = true; + } else { + if (!!skin.enable) { + lastSkinId = skin.skinId; + } + newHeroSkins.push({ ...skin, enable: false }); + } + } + if (!result) { + return resResult(STATUS.HERO_SKIN_NOT_FIND); + } + + let dicHero = gameData.hero.get(dicSkin.heroId); + let dicMyJob = gameData.job.get(hero.job); + let dicNewJob = getJobByGradeAndClass(dicHero.jobClass, dicMyJob.grade); + + let oldEplace = hero.ePlace||[]; + let eplaceIds = new Map(); // 更新了的装备栏id + for(let { id } of oldEplace) { + let dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id); + eplaceIds.set(id, { equipId: dicEquip.id }); + } + + let { newEplace } = updateEplaces(oldEplace, eplaceIds); + let update = { + skins: newHeroSkins, + skinId: dicSkin.heroId, + job: dicNewJob.jobid, + ePlace: newEplace + } + let artifact = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SKIN, roleId, serverId, sid, hero.hid, update, { hero, artifact }); + let resultHero = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: {...pick(resultHero, ['hid', 'skins', 'skinId', 'job', 'talent', 'usedTalentPoint']), ePlace: newEplace }}); + } + + public async previewRebirth(msg: { hid: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let { hid } = msg; + + let hero = await HeroModel.findByHidAndRole(hid, roleId, 'hid consumes star starStage quality'); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + let { consumes} = calStarUpConsume(hero); + + return resResult(STATUS.SUCCESS, { previewGoods: consumes.filter(consume => consume.count > 0) }); + } + + public async rebirth(msg: { hid: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { hid } = msg; + if(!isNumber(hid) && !hid) return resResult(STATUS.WRONG_PARMS); + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(hid)) return resResult(STATUS.RESONANCE__HID_NOT_REBIRTH); + + // 武将初始,但是皮肤这里不初始 + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + + // 消耗 + if(hero.lv >= REBORN.REBORON_FREE_LEVEL) { + let cost = [getGoldObject(REBORN.REBORON_HERO)]; + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.REBIRTH); + if(!costResult) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + } + + // 皮肤处理 + let { skins, skinId, ce, scrollActive, quality, star, starStage } = hero; + let dicHero = gameData.hero.get(skinId); + let dicJob = getJobByGradeAndClass(dicHero.jobClass, 0); + + let { consumes: consumesResult, newConsumes } = calStarUpConsume(hero); + + let newSkins = initSkinTalent(skins); + let newQuality = quality >= 3? ( dicHero.quality >= 3? dicHero.quality: 3 ): quality; + let dicHeroScroll = getScollByStar(dicHero.quality, star, newQuality, dicHero.initialColorStar); + let initInfo = HeroModel.getInitInfo(hid, { + artifact: hero.artifact, + job: dicJob.jobid, skins: newSkins, skinId, ce, + star, starStage, colorStar: dicHero.initialColorStar, colorStarStage: 0, quality: newQuality, + scrollActive: scrollActive, + scrollId: scrollActive? dicHeroScroll.id: 0, + scrollStar: scrollActive? dicHeroScroll.stars: 0, + scrollQuality: scrollActive? dicHeroScroll.qualityUp: 0, + scrollColorStar: scrollActive? dicHeroScroll.colorstars: 0, + consumes: newConsumes + }); + + // 天晶石 + let curJewels: jewelUpdate[] = []; + for(let { jewel, id } of hero.ePlace) { + if(jewel > 0) { + let jewelInfo = await JewelModel.putOnOrOff(jewel, 0, id); + curJewels.push({ + seqId: jewelInfo.seqId, + id: jewelInfo.id, + hid: jewelInfo.hid, + }); + } + } + + let school = await SchoolModel.findByHid(roleId, hid); + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.REBIRTH, roleId, serverId, sid, hid, initInfo, { schoolId: school?.schoolId }); + let goods = await addItems(roleId, roleName, sid, consumesResult, ITEM_CHANGE_REASON.REBIRTH); + saveRebirthLog(session, hero); + + const heroResult = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: heroResult, curJewels, goods }); + } + + // 解锁天赋 + public async unlockTalent(msg: { hid: number, id: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let { hid, id } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let dicHeroTalent = gameData.heroTalent.get(id); + if(!dicHeroTalent) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + + let skins = hero.skins||[]; + let curSkin = skins.find(cur => cur.enable); + if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); + + let talent = curSkin.talent.find(cur => cur.id == id); + if(talent) return resResult(STATUS.TALENT_HAS_UNLOCKED); + + let usedTalentPoint = curSkin.usedTalentPoint; + if(!checkUnlockTalentCondition(curSkin.skinId, id, curSkin.talent, usedTalentPoint)) { + return resResult(STATUS.TALENT_CONDITION_NOT_FIT); + } + + let totalTalentPoint = gameData.talentPointOfJob.get(hero.job); + let needTalentPoint = dicHeroTalent.level.find(cur => cur.lv == 1)?.cost||0; + if(totalTalentPoint - usedTalentPoint - needTalentPoint < 0) { + return resResult(STATUS.TALENT_POINT_NOT_ENOUGH); + } + + let { newSkins } = updateSkinTalent(skins, new Talent(id), usedTalentPoint + needTalentPoint); + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_UNLOCK, roleId, serverId, sid, hid, { skins: newSkins }, { talentId: id }); + const heroResult = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); + + } + + // 升级天赋 + public async upgradeTalent(msg: { hid: number, id: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let { hid, id } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let dicHeroTalent = gameData.heroTalent.get(id); + if(!dicHeroTalent) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + + let skins = hero.skins||[]; + let curSkin = skins.find(cur => cur.enable); + if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); + + let talent = curSkin.talent.find(cur => cur.id == id); + if(!talent) return resResult(STATUS.TALENT_NOT_UNLOCKED); + + let usedTalentPoint = curSkin.usedTalentPoint; + let totalTalentPoint = gameData.talentPointOfJob.get(hero.job); + let nextLv = dicHeroTalent.level.find(cur => cur.lv == talent.level + 1); + if(!nextLv) return resResult(STATUS.TALENT_LEVEL_MAX); + let needTalentPoint = nextLv.cost||0; + if(totalTalentPoint - usedTalentPoint - needTalentPoint < 0) { + return resResult(STATUS.TALENT_POINT_NOT_ENOUGH); + } + + let { newSkins } = updateSkinTalent(skins, new Talent(id, talent.level + 1), usedTalentPoint + needTalentPoint); + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_LV, roleId, serverId, sid, hid, { skins: newSkins }, { talentId: id }); + const heroResult = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); + } + + // 洗点 + public async resetTalent(msg: { hid: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let { hid } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + + let skins = hero.skins||[]; + let curSkin = skins.find(cur => cur.enable); + if(!curSkin) return resResult(STATUS.HERO_SKIN_NOT_FIND); + + let costItem = parseGoodStr(HERO.HERO_TALENTPOINT_RESET); + let consumeResult = await handleCost(roleId, sid, costItem, ITEM_CHANGE_REASON.RESET_TALENT); + if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + + let newSkins = initSkinTalent(skins); + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.TALENT_RESET, roleId, serverId, sid, hid, { skins: newSkins }); + + const heroResult = new HeroParam(curHero); + return resResult(STATUS.SUCCESS, { curHero: {...pick(heroResult, ['hid', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }}); + } + + + // 设置副将 + async setSubHero(msg: { hid: number, subHid: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let { hid, subHid: subSkinId } = msg; + + let dicHero = gameData.hero.get(hid); + if(!dicHero || dicHero.urType != 1) return resResult(STATUS.HERO_CAN_NOT_SET_SUB); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) return resResult(STATUS.HERO_NOT_FIND); + + let subHid = 0; + if(subSkinId > 0) { // 设置上 + if(hero.subHid == subSkinId) return resResult(STATUS.SUCCESS, { preHid: hero.subActorId, curHero: pick(hero, ['hid', 'subHid', 'subActorId']) }); + let dicHero = gameData.hero.get(subSkinId); + if(!dicHero || dicHero.urType == 1) return resResult(STATUS.HERO_CAN_NOT_BE_SET_SUB); + subHid = dicHero.actorId; + + let subHero = await HeroModel.findByHidAndRole(subHid, roleId); + if(!subHero) return resResult(STATUS.HERO_NOT_FIND); + + // await LadderMatchModel.removeBySub(roleId, subHid); + // await PvpSaveDataModel.removeBySub(roleId, subHid); + // await PvpDefenseModel.removeBySub(roleId, subHid); + // await GVGVestigeRankModel.removeBySub(roleId, subHid); + // await GVGTeamModel.removeBySub(roleId, subHid, subHero.ce); + + } else { // 卸下 + if(!hero.subHid) return resResult(STATUS.SUCCESS, { preHid: hero.subActorId, curHero: pick(hero, ['hid', 'subHid', 'subActorId']) }); + } + + // 设置副将 + const { preHid, curHero } = await HeroModel.setSubHero(roleId, hid, subSkinId, subHid); + + return resResult(STATUS.SUCCESS, { preHid, curHero: pick(curHero, ['hid', 'subHid', 'subActorId']) }); + } + + + /** + * 重生 武将等级、装备养成、职业进阶上养成度对换,升星、羁绊不对换,双方的职业天赋树均重置 + * @param msg + * @param session + */ + public async heroReborn(msg: { originHid: number, targetHid: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + const { originHid, targetHid } = msg; + + let { dbResonanceMap } = await getResonanceDataMap(roleId); + if(dbResonanceMap.has(originHid) || dbResonanceMap.has(targetHid)) return resResult(STATUS.RESONANCE__HID_NOT_REBIRTH); + + + let dbHeros = await HeroModel.findByHidsAndRole(roleId, [originHid, targetHid]); + if (dbHeros.length != 2) return resResult(STATUS.HERO_NOT_FIND); + const heroMap = dbHeros.reduce((map, obj) => { map.set(obj.hid, obj); return map; }, new Map()); + let originHero = heroMap.get(originHid); + let targetHero = heroMap.get(targetHid); + + //交换 lv exp jobStage + swapFields(originHero || {}, targetHero || {}, ['lv', 'exp', 'jobStage']); + + //交换job + let originJob = originHero.job, targetJob = targetHero.job + originHero.job = getNewJob(originHero, targetJob); + targetHero.job = getNewJob(targetHero, originJob); + + //天赋树置空 + if (originHero.skins || originHero.skins.length > 0) originHero.skins = initSkinTalent(originHero.skins); + if (targetHero.skins || targetHero.skins.length > 0) targetHero.skins = initSkinTalent(targetHero.skins); + + //装备养成交换 + let tempOriginEPlace = [], tempTargetEPlace = [] + if (originHero.ePlace || targetHero.ePlace.length > 0) tempOriginEPlace = getHeroNewEplace(originHero, targetHero?.ePlace || []); + if (targetHero.ePlace || originHero.ePlace.length > 0) tempTargetEPlace = getHeroNewEplace(targetHero, originHero?.ePlace || []); + + originHero.ePlace = tempOriginEPlace; + targetHero.ePlace = tempTargetEPlace; + // 天晶地玉 + let jewels: JewelType[] = []; + let curJewels: jewelUpdate[] = []; + for (let { jewel } of originHero.ePlace) { + if (jewel == 0) continue; + let result = await JewelModel.updateInfo(jewel, { hid: targetHid }); + if (!result) return resResult(STATUS.HERO_NOT_FIND); + jewels.push(result); + curJewels.push({ seqId:result.seqId, hid:result.hid}); + } + for (let { jewel } of targetHero.ePlace) { + if (jewel == 0) continue; + let result = await JewelModel.updateInfo(jewel, { hid: originHid }); + if (!result) return resResult(STATUS.HERO_NOT_FIND); + jewels.push(result); + curJewels.push({ seqId:result.seqId, hid:result.hid}); + } + + // 消耗 + let originalConsumes = originHero.consumes||[]; + let targetConsumes = targetHero.consumes||[]; + originHero.consumes = [...targetConsumes.filter(cur => REBORN_ITEM.includes(cur.id)), ...originalConsumes.filter(cur => !REBORN_ITEM.includes(cur.id))]; + targetHero.consumes = [...originalConsumes.filter(cur => REBORN_ITEM.includes(cur.id)), ...targetConsumes.filter(cur => !REBORN_ITEM.includes(cur.id))]; + + let cost = [getGoldObject(REBORN.EXCHANGE_COST)]; + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.REBORN_COST); + if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let heroesRet: HeroType[] = []; + for (let hero of [originHero, targetHero]) { + let result = await HeroModel.updateHeroInfo(roleId, hero.hid, { ...pick(hero, ['lv','exp', 'job', 'jobStage', 'ePlace', 'skins', 'consumes']) }); + if (!result) return resResult(STATUS.HERO_NOT_FIND); + heroesRet.push(result); + } + + let artifacts = await ArtifactModel.findbyHids(roleId, [originHid, targetHid]); + + // 战力重算 + let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.REBORN_CAL, roleId, serverId, sid, heroesRet, { jewels, heroes: heroesRet, artifacts }); + + let curHeroes = []; + for (let hero of (heroes || [])) { + const heroResult = new HeroParam(hero); + curHeroes.push({ ...pick(heroResult, ['seqId', 'hid', 'ce','exp', 'lv', 'job', 'jobStage', 'ePlace', 'talent', 'usedTalentPoint', 'totalTalentPoint']) }); + } + + return resResult(STATUS.SUCCESS, { curHeroes, curJewels }) + } + + + // ! debug接口 一键全武将 + public async debugGetAllHeroes(msg: { magicWord: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + await HeroModel.deleteAccount(roleId); + await JewelModel.deleteAccount(roleId); + await SkinModel.deleteMany({ roleId }); + await SchoolModel.deleteAccount(roleId); + await RoleCeModel.deleteMany({ roleId }); + await RoleModel.updateRoleInfo(roleId, { jewelCount: 0 }); + let heroInfos = []; + + for(let [actorId] of gameData.recruit) { + let dicHero = gameData.hero.get(actorId); + if(!dicHero) continue; + let { jobid, grade } = gameData.jobClassMaxGrades.get(dicHero.jobClass); + heroInfos.push({ + hid: actorId, star: 6, colorStar: 6, quality: 4, lv: 100, exp: getExpByLv(100).sum, job: jobid, grade + }); + } + let resultHeroes = await createHeroes(roleId, roleName, sid, serverId, heroInfos); + + return resResult(STATUS.SUCCESS, resultHeroes); + } + + + // ! 测试接口,用来测试前清理并初始化某个武将;代码抄自:gm-server/app/service/users.ts deleteHero + public async testCleanUp(msg: { magicWord: string, hid: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + + const { magicWord, hid } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.HERO_NOT_FIND); + await addItems(roleId, roleName, sid, [{ + id: dicHero.pieceId, count: dicHero.pieceCount * HERO_GROW_MAX.STAR * ABI_STAGE.END + }], ITEM_CHANGE_REASON.DEBUG); + + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + await HeroModel.deleteHero(roleId, hid); + let role = await RoleModel.findByRoleId(roleId); + await PvpDefenseModel.deleteHero(roleId, hid); + await RoleModel.updateRoleInfo(roleId, { topLineup: role.topLineup, topLineupCe: role.topLineupCe, ce: role.ce - hero.ce }); + return resResult(STATUS.SUCCESS); + } + + public async addItem(msg: { id: number, count: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + + let { id, count } = msg; + + //let result = await handleCost(roleId, sid, [{id, count}] ); + let items = [{ id, count }]; + let role = await RoleModel.findByRoleId(roleId); + if (id == 999999) { + items = getDropItems(); + if (role.lv < 60) { + role.lv = 60; + let roleLvInfo = gameData.kingexp.get(role.lv - 1); + role.exp = roleLvInfo.sum; + await RoleModel.updateRoleInfo(roleId, role); + } + } + let result = await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.DEBUG); + if (!result) { + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + } + return resResult(STATUS.SUCCESS, { goods: result, lv: role.lv, exp: role.exp }); + + } + + public async debugSetHero(msg: { magicWord: string, hid: number, params: HeroUpdate }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let { magicWord, hid, params } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let hero = await HeroModel.findByHidAndRole(hid, roleId); + if(!hero) { + let { resultHeroes } = await createHero(roleId, roleName, sid, serverId, { hid, count: 1, ...params }); + return resResult(STATUS.SUCCESS, { hero: resultHeroes[0] }); + } else { + hero = await HeroModel.updateHeroInfo(roleId, hid, params); + return resResult(STATUS.SUCCESS, { hero: new HeroParam(hero) }); + } + + } +} + diff --git a/game-server/app/servers/role/handler/itemHandler.ts b/game-server/app/servers/role/handler/itemHandler.ts index f2c5d9e60..fa05e9c37 100644 --- a/game-server/app/servers/role/handler/itemHandler.ts +++ b/game-server/app/servers/role/handler/itemHandler.ts @@ -1,308 +1,309 @@ -import { Application, BackendSession, HandlerService, } from "pinus"; -import { STATUS, CONSUME_TYPE, DEBUG_MAGIC_WORD, GIFT_GENERATE_TYPE, ITEM_CHANGE_REASON, GIFT_TYPE } from "../../../consts"; -import { RewardInter } from "../../../pubUtils/interface"; - -import { getRandSingleEelm, resResult } from "../../../pubUtils/util"; -import { addItems, handleCost } from "../../../services/role/rewardService"; -import { RoleModel } from "../../../db/Role"; -import { gameData } from "../../../pubUtils/data"; -import { ITID } from "../../../consts/constModules/itemConst"; -import { useGiftPackage } from "../../../services/activity/giftPackageService"; -import { getAp, setAp, setApBuyTimes } from "../../../services/actionPointService"; -import { ActionPointModel } from "../../../db/ActionPoint"; -import { GiftCodeDetailModel } from "../../../db/GiftCodeDetail"; -import { GiftCodeType, GiftCodeModel } from "../../../db/GiftCode"; -import { nowSeconds } from "../../../pubUtils/timeUtil"; -import { AP } from "../../../pubUtils/dicParam"; -import { GiftPackageFloorModel } from "../../../db/GiftPackageFloor"; -import { UserGiftCodeDetailModel } from "../../../db/UserGiftCodeDetail"; -import { combineItems } from "../../../services/role/util"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ItemHandler(app); -} - -export class ItemHandler { - - constructor(private app: Application) { - } - - - // 道具的使用 - public async useItem(msg: { id: number, selected: Array, count: number }, session: BackendSession) { - let { id, selected, count } = msg; - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const roleName = session.get('roleName'); - const guildCode = session.get('guildCode'); - - let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }], ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); - if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); - - let dicGoods = gameData.goods.get(id); - if (!dicGoods) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicItid.type != CONSUME_TYPE.GIFT_PACKAGE) { - return resResult(STATUS.NOT_CONSUME_GOODS); - } - let giftID = dicGoods.gift; - if (!giftID) { - return resResult(STATUS.NOT_GIFTPACKAGE); - } - let result = await useGiftPackage(roleId, roleName, sid, serverId, guildCode, giftID, selected, count); - return result; - - } - - // 获取礼包保底情况 - public async getGiftPackageFloor(msg: { id: number }, session: BackendSession) { - let { id } = msg; - const roleId = session.get('roleId'); - let dicGoods = gameData.goods.get(id); - if (!dicGoods) { - return resResult(STATUS.ACTIVITY_DATA_ERROR); - } - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicItid.type != CONSUME_TYPE.GIFT_PACKAGE) { - return resResult(STATUS.NOT_CONSUME_GOODS); - } - let giftID = dicGoods.gift; - if (!giftID) { - return resResult(STATUS.NOT_GIFTPACKAGE); - } - let giftPackageData = gameData.giftPackage.get(giftID); - if (!giftPackageData) { - return resResult(STATUS.NOT_GIFTPACKAGE); - } - let result = await GiftPackageFloorModel.findByGiftPackageId(roleId, giftPackageData.id, 'floors giftPackageId'); - return resResult(STATUS.SUCCESS, result); - } - - // 使用体力道具 - public async useApItem(msg: { id: number, count: number }, session: BackendSession) { - let { id, count } = msg; - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const ip = session.get('ip'); - const serverId = session.get('serverId'); - - let dicGoods = gameData.goods.get(id); - if (!dicGoods) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicItid.type != CONSUME_TYPE.AP) { - return resResult(STATUS.ROLE_METERIAL_ERROR); - } - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let { ap, isOver } = await getAp(roleId, ip, role.lv); - if (isOver) return resResult(STATUS.AP_IS_FULL); - - if(ap + dicGoods.value * count > AP.AP_SAVE_MAX) { - return resResult(STATUS.AP_IS_FULL); - } - - let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }], ITEM_CHANGE_REASON.USE_MEAT); - if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let apJson = await setAp(serverId, roleId, ip, role.lv, dicGoods.value * count, sid, ITEM_CHANGE_REASON.USE_MEAT); - - return resResult(STATUS.SUCCESS, { - apJson - }); - } - - // 购买体力道具 - public async buyApItem(msg: { id: number, count: number }, session: BackendSession) { - let { id, count } = msg; - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const ip: string = session.get('ip'); - - if (count <= 0) return resResult(STATUS.WRONG_PARMS); - - let dicGoods = gameData.goods.get(id); - if (!dicGoods) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicItid.type != CONSUME_TYPE.AP) { - return resResult(STATUS.ROLE_METERIAL_ERROR); - } - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let { buyTimes = 0 } = await getAp(roleId, ip, role.lv); - if (buyTimes + count > gameData.apMaxBuyTimes.max) return resResult(STATUS.AP_BUY_TIMES_LACK); - - let cost: RewardInter[] = []; - for (let i = 0; i < count; i++) { - let curCost = gameData.apBuy.get(++buyTimes); - if (curCost) cost = cost.concat(curCost); - } - - let consumeResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.BUY_MEAT); - if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.BUY_MEAT); - let apJson = await setApBuyTimes(roleId, ip, role.lv, sid, count); - - return resResult(STATUS.SUCCESS, { - goods, apJson - }); - } - - // 兑换礼包码 - public async useGiftCode(msg: { code: string }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const serverId: number = session.get('serverId'); - const sid: string = session.get('sid'); - const channel: string = session.get('channel'); - const { code } = msg; - - let giftCodeDetail = await GiftCodeDetailModel.findByCode(code); - if(!giftCodeDetail) { - return resResult(STATUS.GIFT_CODE_NOT_FOUND); - } - let giftCode = await GiftCodeModel.findByGiftId(giftCodeDetail.giftId); - if(!giftCode) { - return resResult(STATUS.GIFT_CODE_NOT_FOUND); - } - if(giftCode.type != GIFT_TYPE.GAME && giftCode.type != GIFT_TYPE.DEFAULT) return resResult(STATUS.GIFT_TYPE_ERR); - if(giftCode.generateType == GIFT_GENERATE_TYPE.ONE_TO_ONE) { // 一人一条,单条不能被多人使用 - if(giftCodeDetail.usedNum > 0) return resResult(STATUS.GIFT_CODE_USED_NUM_MAX); - } - if(!giftCode.isEnable) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED); - if (giftCode.beginTime > nowSeconds()) return resResult(STATUS.GIFT_CODE_NOT_START); - if (giftCode.endTime < nowSeconds()) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED); - - if(giftCode.channel.indexOf('all') == -1 && giftCode.channel.indexOf(channel) == -1) { - return resResult(STATUS.GIFT_CODE_CHANNEL_ERR); - } - - let checkHasUse = await GiftCodeDetailModel.checkHasUsed(roleId, giftCodeDetail.giftId) - if(checkHasUse) { - return resResult(STATUS.YOU_HAVE_USED_THIS_CODE); - } - let checkHasUse2 = await UserGiftCodeDetailModel.checkHasUsed(roleId, giftCodeDetail.giftId) - if(checkHasUse2) { - return resResult(STATUS.YOU_HAVE_USED_THIS_CODE); - } - - await UserGiftCodeDetailModel.record(roleId, roleName, serverId, giftCodeDetail.giftId, code); - await GiftCodeDetailModel.increaseUsedNum(code); - await GiftCodeModel.increaseUsedNum(giftCode.id); - - let goods = await addItems(roleId, roleName, sid, giftCode.goods, ITEM_CHANGE_REASON.USE_GIFT_CODE); - return resResult(STATUS.SUCCESS, { goods }); - } - - public async getAp(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let ip = session.get('ip'); - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let apJson = await getAp(roleId, ip, role.lv); - return resResult(STATUS.SUCCESS, { apJson }); - } - - public async getApByLv(msg: { lv: number }, session: BackendSession) { - const { lv } = msg; - let roleId = session.get('roleId'); - let ip = session.get('ip'); - - let { lvRecords = [] } = await ActionPointModel.getAp(roleId); - let lvRecord = lvRecords.find(cur => cur.lv == lv); - let ap = 0, apBefore = 0; - if(!lvRecord) { - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let apJson = await getAp(roleId, ip, role.lv); - ap = apJson.ap; - apBefore = apJson.ap; - } else { - ({ ap, apBefore } = lvRecord); - } - return resResult(STATUS.SUCCESS, { ap, apBefore }); - } - - public async exchangeSpirit(msg: { origin: { id: number, count: number }[] }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { origin = [] } = msg; - - let originQuality = 0, allCount = 0; - for (let { id, count } of origin) { - let dicGoods = gameData.goods.get(id); - let dicItid = ITID.get(dicGoods?.itid); - if (!dicItid || dicItid.type != CONSUME_TYPE.SPIRIT_STONE) - return resResult(STATUS.ACCESS_BUSY); - if (originQuality == 0) originQuality = dicGoods.quality; - if (dicGoods.quality != originQuality) return resResult(STATUS.SPIRIT_QUALITY_NOT_SAME); - allCount += count; - } - let dicSpiritCompose = gameData.spiritCompose.get(originQuality); - if (!dicSpiritCompose) return resResult(STATUS.SPIRIT_QUALITY_NOT_FOUND); - - let { goalQuality, materialNum } = dicSpiritCompose; - let num = Math.floor(allCount/materialNum); - if (allCount > num * materialNum) return resResult(STATUS.SPIRIT_QUALITY_NOT_INTERGER); - - let pool = gameData.spiritByQuality.get(goalQuality); - if (!pool || pool.length <= 0) return resResult(STATUS.TARGET_SPIRIT_QUALITY_NOT_FOUND); - - let costResult = await handleCost(roleId, sid, origin, ITEM_CHANGE_REASON.EXCHANGE_SPIRIT); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let rewards: RewardInter[] = []; - for (let i = 0; i < num; i++) { - let gid = getRandSingleEelm(pool); - rewards.push({ id: gid, count: 1 }); - } - - let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.EXCHANGE_SPIRIT); - - return resResult(STATUS.SUCCESS, { goods }); - } - - - public async debugIncAp(msg: { magicWord: string, ap: number }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - const roleId = session.get('roleId'); - const sid = session.get('sid'); - const ip = session.get('ip'); - const serverId = session.get('serverId'); - - let role = await RoleModel.findByRoleId(roleId, 'lv'); - let apJson = await setAp(serverId, roleId, ip, role.lv, msg.ap, sid, ITEM_CHANGE_REASON.DEBUG); - if (!apJson) return resResult(STATUS.BATTLE_ACTION_POINT_LACK) - return resResult(STATUS.SUCCESS, { apJson }); - } - - public async debugResetBuyTimes(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let roleId = session.get('roleId'); - let ip = session.get('ip'); - let role = await RoleModel.findByRoleId(roleId, 'lv'); - await ActionPointModel.resetBuyTimes(roleId); - let apJson = await getAp(roleId, ip, role.lv); - return resResult(STATUS.SUCCESS, { apJson }); - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from "pinus"; +import { STATUS, CONSUME_TYPE, DEBUG_MAGIC_WORD, GIFT_GENERATE_TYPE, ITEM_CHANGE_REASON, GIFT_TYPE } from "../../../consts"; +import { RewardInter } from "@pubUtils/interface"; + +import { getRandSingleEelm, resResult } from "@pubUtils/util"; +import { addItems, handleCost } from "../../../services/role/rewardService"; +import { RoleModel } from "@db/Role"; +import { gameData } from "@pubUtils/data"; +import { ITID } from "@consts/constModules/itemConst"; +import { useGiftPackage } from "../../../services/activity/giftPackageService"; +import { getAp, setAp, setApBuyTimes } from "../../../services/actionPointService"; +import { ActionPointModel } from "@db/ActionPoint"; +import { GiftCodeDetailModel } from "@db/GiftCodeDetail"; +import { GiftCodeType, GiftCodeModel } from "@db/GiftCode"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { AP } from "@pubUtils/dicParam"; +import { GiftPackageFloorModel } from "@db/GiftPackageFloor"; +import { UserGiftCodeDetailModel } from "@db/UserGiftCodeDetail"; +import { combineItems } from "../../../services/role/util"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ItemHandler(app); +} + +export class ItemHandler { + + constructor(private app: Application) { + } + + + // 道具的使用 + public async useItem(msg: { id: number, selected: Array, count: number }, session: BackendSession) { + let { id, selected, count } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const roleName = session.get('roleName'); + const guildCode = session.get('guildCode'); + + let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }], ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + + let dicGoods = gameData.goods.get(id); + if (!dicGoods) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicItid.type != CONSUME_TYPE.GIFT_PACKAGE) { + return resResult(STATUS.NOT_CONSUME_GOODS); + } + let giftID = dicGoods.gift; + if (!giftID) { + return resResult(STATUS.NOT_GIFTPACKAGE); + } + let result = await useGiftPackage(roleId, roleName, sid, serverId, guildCode, giftID, selected, count); + return result; + + } + + // 获取礼包保底情况 + public async getGiftPackageFloor(msg: { id: number }, session: BackendSession) { + let { id } = msg; + const roleId = session.get('roleId'); + let dicGoods = gameData.goods.get(id); + if (!dicGoods) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicItid.type != CONSUME_TYPE.GIFT_PACKAGE) { + return resResult(STATUS.NOT_CONSUME_GOODS); + } + let giftID = dicGoods.gift; + if (!giftID) { + return resResult(STATUS.NOT_GIFTPACKAGE); + } + let giftPackageData = gameData.giftPackage.get(giftID); + if (!giftPackageData) { + return resResult(STATUS.NOT_GIFTPACKAGE); + } + let result = await GiftPackageFloorModel.findByGiftPackageId(roleId, giftPackageData.id, 'floors giftPackageId'); + return resResult(STATUS.SUCCESS, result); + } + + // 使用体力道具 + public async useApItem(msg: { id: number, count: number }, session: BackendSession) { + let { id, count } = msg; + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const ip = session.get('ip'); + const serverId = session.get('serverId'); + + let dicGoods = gameData.goods.get(id); + if (!dicGoods) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicItid.type != CONSUME_TYPE.AP) { + return resResult(STATUS.ROLE_METERIAL_ERROR); + } + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let { ap, isOver } = await getAp(roleId, ip, role.lv); + if (isOver) return resResult(STATUS.AP_IS_FULL); + + if(ap + dicGoods.value * count > AP.AP_SAVE_MAX) { + return resResult(STATUS.AP_IS_FULL); + } + + let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }], ITEM_CHANGE_REASON.USE_MEAT); + if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let apJson = await setAp(serverId, roleId, ip, role.lv, dicGoods.value * count, sid, ITEM_CHANGE_REASON.USE_MEAT); + + return resResult(STATUS.SUCCESS, { + apJson + }); + } + + // 购买体力道具 + public async buyApItem(msg: { id: number, count: number }, session: BackendSession) { + let { id, count } = msg; + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const ip: string = session.get('ip'); + + if (count <= 0) return resResult(STATUS.WRONG_PARMS); + + let dicGoods = gameData.goods.get(id); + if (!dicGoods) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicItid.type != CONSUME_TYPE.AP) { + return resResult(STATUS.ROLE_METERIAL_ERROR); + } + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let { buyTimes = 0 } = await getAp(roleId, ip, role.lv); + if (buyTimes + count > gameData.apMaxBuyTimes.max) return resResult(STATUS.AP_BUY_TIMES_LACK); + + let cost: RewardInter[] = []; + for (let i = 0; i < count; i++) { + let curCost = gameData.apBuy.get(++buyTimes); + if (curCost) cost = cost.concat(curCost); + } + + let consumeResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.BUY_MEAT); + if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let goods = await addItems(roleId, roleName, sid, [{ id, count }], ITEM_CHANGE_REASON.BUY_MEAT); + let apJson = await setApBuyTimes(roleId, ip, role.lv, sid, count); + + return resResult(STATUS.SUCCESS, { + goods, apJson + }); + } + + // 兑换礼包码 + public async useGiftCode(msg: { code: string }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const serverId: number = session.get('serverId'); + const sid: string = session.get('sid'); + const channel: string = session.get('channel'); + const { code } = msg; + + let giftCodeDetail = await GiftCodeDetailModel.findByCode(code); + if(!giftCodeDetail) { + return resResult(STATUS.GIFT_CODE_NOT_FOUND); + } + let giftCode = await GiftCodeModel.findByGiftId(giftCodeDetail.giftId); + if(!giftCode) { + return resResult(STATUS.GIFT_CODE_NOT_FOUND); + } + if(giftCode.type != GIFT_TYPE.GAME && giftCode.type != GIFT_TYPE.DEFAULT) return resResult(STATUS.GIFT_TYPE_ERR); + if(giftCode.generateType == GIFT_GENERATE_TYPE.ONE_TO_ONE) { // 一人一条,单条不能被多人使用 + if(giftCodeDetail.usedNum > 0) return resResult(STATUS.GIFT_CODE_USED_NUM_MAX); + } + if(!giftCode.isEnable) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED); + if (giftCode.beginTime > nowSeconds()) return resResult(STATUS.GIFT_CODE_NOT_START); + if (giftCode.endTime < nowSeconds()) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED); + + if(giftCode.channel.indexOf('all') == -1 && giftCode.channel.indexOf(channel) == -1) { + return resResult(STATUS.GIFT_CODE_CHANNEL_ERR); + } + + let checkHasUse = await GiftCodeDetailModel.checkHasUsed(roleId, giftCodeDetail.giftId) + if(checkHasUse) { + return resResult(STATUS.YOU_HAVE_USED_THIS_CODE); + } + let checkHasUse2 = await UserGiftCodeDetailModel.checkHasUsed(roleId, giftCodeDetail.giftId) + if(checkHasUse2) { + return resResult(STATUS.YOU_HAVE_USED_THIS_CODE); + } + + await UserGiftCodeDetailModel.record(roleId, roleName, serverId, giftCodeDetail.giftId, code); + await GiftCodeDetailModel.increaseUsedNum(code); + await GiftCodeModel.increaseUsedNum(giftCode.id); + + let goods = await addItems(roleId, roleName, sid, giftCode.goods, ITEM_CHANGE_REASON.USE_GIFT_CODE); + return resResult(STATUS.SUCCESS, { goods }); + } + + public async getAp(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let ip = session.get('ip'); + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let apJson = await getAp(roleId, ip, role.lv); + return resResult(STATUS.SUCCESS, { apJson }); + } + + public async getApByLv(msg: { lv: number }, session: BackendSession) { + const { lv } = msg; + let roleId = session.get('roleId'); + let ip = session.get('ip'); + + let { lvRecords = [] } = await ActionPointModel.getAp(roleId); + let lvRecord = lvRecords.find(cur => cur.lv == lv); + let ap = 0, apBefore = 0; + if(!lvRecord) { + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let apJson = await getAp(roleId, ip, role.lv); + ap = apJson.ap; + apBefore = apJson.ap; + } else { + ({ ap, apBefore } = lvRecord); + } + return resResult(STATUS.SUCCESS, { ap, apBefore }); + } + + public async exchangeSpirit(msg: { origin: { id: number, count: number }[] }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { origin = [] } = msg; + + let originQuality = 0, allCount = 0; + for (let { id, count } of origin) { + let dicGoods = gameData.goods.get(id); + let dicItid = ITID.get(dicGoods?.itid); + if (!dicItid || dicItid.type != CONSUME_TYPE.SPIRIT_STONE) + return resResult(STATUS.ACCESS_BUSY); + if (originQuality == 0) originQuality = dicGoods.quality; + if (dicGoods.quality != originQuality) return resResult(STATUS.SPIRIT_QUALITY_NOT_SAME); + allCount += count; + } + let dicSpiritCompose = gameData.spiritCompose.get(originQuality); + if (!dicSpiritCompose) return resResult(STATUS.SPIRIT_QUALITY_NOT_FOUND); + + let { goalQuality, materialNum } = dicSpiritCompose; + let num = Math.floor(allCount/materialNum); + if (allCount > num * materialNum) return resResult(STATUS.SPIRIT_QUALITY_NOT_INTERGER); + + let pool = gameData.spiritByQuality.get(goalQuality); + if (!pool || pool.length <= 0) return resResult(STATUS.TARGET_SPIRIT_QUALITY_NOT_FOUND); + + let costResult = await handleCost(roleId, sid, origin, ITEM_CHANGE_REASON.EXCHANGE_SPIRIT); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let rewards: RewardInter[] = []; + for (let i = 0; i < num; i++) { + let gid = getRandSingleEelm(pool); + rewards.push({ id: gid, count: 1 }); + } + + let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.EXCHANGE_SPIRIT); + + return resResult(STATUS.SUCCESS, { goods }); + } + + + public async debugIncAp(msg: { magicWord: string, ap: number }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + const roleId = session.get('roleId'); + const sid = session.get('sid'); + const ip = session.get('ip'); + const serverId = session.get('serverId'); + + let role = await RoleModel.findByRoleId(roleId, 'lv'); + let apJson = await setAp(serverId, roleId, ip, role.lv, msg.ap, sid, ITEM_CHANGE_REASON.DEBUG); + if (!apJson) return resResult(STATUS.BATTLE_ACTION_POINT_LACK) + return resResult(STATUS.SUCCESS, { apJson }); + } + + public async debugResetBuyTimes(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let roleId = session.get('roleId'); + let ip = session.get('ip'); + let role = await RoleModel.findByRoleId(roleId, 'lv'); + await ActionPointModel.resetBuyTimes(roleId); + let apJson = await getAp(roleId, ip, role.lv); + return resResult(STATUS.SUCCESS, { apJson }); + } +} + diff --git a/game-server/app/servers/role/handler/mailHandler.ts b/game-server/app/servers/role/handler/mailHandler.ts index c8f048ab2..1c20211da 100644 --- a/game-server/app/servers/role/handler/mailHandler.ts +++ b/game-server/app/servers/role/handler/mailHandler.ts @@ -1,188 +1,189 @@ -import {Application, BackendSession, ChannelService} from 'pinus'; -import { MailModel, MailType } from '../../../db/Mail'; -import { GroupMailModel, GroupMailType } from '../../../db/GroupMail'; -import { resResult } from '../../../pubUtils/util'; -import { STATUS } from '../../../consts/statusCode'; -import { MAIL_STATUS, GM_MAIL_TYPE } from '../../../consts/constModules/mailConst'; -import { addItems } from '../../../services/role/rewardService'; -import { checkMailGoods, getMails } from '../../../services/mailService'; -import { ServerMailModel, ServerMailType } from '../../../db/ServerMail'; -import { MailParam } from '../../../domain/roleField/mail'; -import { ItemInter, RewardInter } from '../../../pubUtils/interface'; -import { RoleModel } from '../../../db/Role'; -import { gameData } from '../../../pubUtils/data'; -import { ITEM_CHANGE_REASON, ITID, RECEIVE_MAIL_TYPE } from '../../../consts'; -import { BAG } from '../../../pubUtils/dicParam'; -import { saveMailLog } from '../../../pubUtils/logUtil'; - -export default function(app: Application) { - return new MailHandler(app); -} - -export class MailHandler { - constructor(private app: Application) { - - } - - public async getMails(msg:{}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - - const list = await getMails(roleId, serverId); - return resResult(STATUS.SUCCESS, { list }); - } - - public async refrshMails(msg:{}) { - - } - - public async readMail(msg: { id: string, mailType: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let { id, mailType } = msg; - let mails = []; - if (mailType == GM_MAIL_TYPE.SINGLE) { - let mail = await MailModel.getMailById(id); - if(mail && mail.status == MAIL_STATUS.CREATE) { - mail = await MailModel.updateStatusWithCondition(id, MAIL_STATUS.READ); - mails.push({ id, status: MAIL_STATUS.READ, mailType }); - } - - } else if (mailType == GM_MAIL_TYPE.GROUP) { - let mail = await GroupMailModel.getMailById(id); - if(mail) { - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(myStatus && myStatus.status == MAIL_STATUS.CREATE) { - mail = await GroupMailModel.updateStatusWithCondition(id, roleId, MAIL_STATUS.READ); - mails.push({ id, status: MAIL_STATUS.READ, mailType }); - } - } - } else if (mailType == GM_MAIL_TYPE.SERVER) { - let mail = await ServerMailModel.getMailById(id); - if(mail) { - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(!myStatus || myStatus.status == MAIL_STATUS.CREATE) { - mail = await ServerMailModel.updateStatusWithCondition(id, roleId, MAIL_STATUS.READ); - mails.push({ id, status: MAIL_STATUS.READ, mailType }); - } - } - } - // if (!mail) - // return resResult(STATUS.WRONG_PARMS); - return resResult(STATUS.SUCCESS, { mails }); - } - - public async delMails(msg: { id: string, mailType: number, type: number }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let serverId: number = session.get('serverId'); - let { id, type, mailType } = msg; - if (type == 1) {//单个删除 - let mail: MailType|GroupMailType|ServerMailType; - if (mailType == GM_MAIL_TYPE.SINGLE) { - mail = await MailModel.delMailById(id); - } else if (mailType == GM_MAIL_TYPE.GROUP) { - mail = await GroupMailModel.delMailById(id, roleId); - } else if (mailType == GM_MAIL_TYPE.SERVER) { - mail = await ServerMailModel.delMailById(id, roleId); - } - if (!mail) return resResult(STATUS.WRONG_PARMS); - - return resResult(STATUS.SUCCESS, { mails: [{ id: mail._id, mailType, status: MAIL_STATUS.DELETE}] }); - } else {//一键删除 - let singlemails = await MailModel.delMailsByRoleId(roleId); - let groupMails = await GroupMailModel.delMailsByRoleId(roleId); - let servermails = await ServerMailModel.delMailsByRoleId(roleId, serverId); - let mails: { id: string, mailType: GM_MAIL_TYPE, status: MAIL_STATUS }[] = []; - for(let mail of singlemails) { - mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.SINGLE, status: MAIL_STATUS.DELETE }); - } - for(let mail of groupMails) { - mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.GROUP, status: MAIL_STATUS.DELETE }); - } - for(let mail of servermails) { - mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.SERVER, status: MAIL_STATUS.DELETE }); - } - return resResult(STATUS.SUCCESS, { mails }); - } - } - - public async getMailRewards(msg: { id: string, mailType: number, type: RECEIVE_MAIL_TYPE }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let roleName: string = session.get('roleName'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - let { id, type, mailType } = msg; - let { jewelCount } = await RoleModel.findByRoleId(roleId, 'jewelCount'); - - let originMails: {mailType: GM_MAIL_TYPE, mail: MailType|GroupMailType|ServerMailType}[] = [] - - if (type == RECEIVE_MAIL_TYPE.SINGLE) {//单个领取 - let mail: MailType|GroupMailType|ServerMailType; - if (mailType == GM_MAIL_TYPE.SINGLE) { - mail = await MailModel.getMailById(id); - if (!mail) return resResult(STATUS.WRONG_PARMS); - if(mail.status != MAIL_STATUS.READ && mail.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); - } else if (mailType == GM_MAIL_TYPE.GROUP) { - mail = await GroupMailModel.getMailById(id); - if (!mail) return resResult(STATUS.WRONG_PARMS); - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(!myStatus) return resResult(STATUS.WRONG_PARMS); - if(myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); - } else if (mailType == GM_MAIL_TYPE.SERVER) { - mail = await ServerMailModel.getMailById(id); - if (!mail) return resResult(STATUS.WRONG_PARMS); - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(myStatus && myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); - } - originMails.push({ mailType, mail }); - } else {//一键领取 - let singlemails = await MailModel.findRewardsMails(roleId); - for(let mail of singlemails) { - if(mail.status != MAIL_STATUS.READ && mail.status != MAIL_STATUS.CREATE) continue; - originMails.push({ mailType: GM_MAIL_TYPE.SINGLE, mail }); - } - let groupMails = await GroupMailModel.findRewardsMails(roleId); - for(let mail of groupMails) { - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(!myStatus) continue; - if(myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) continue; - originMails.push({ mailType: GM_MAIL_TYPE.GROUP, mail }) - } - let servermails = await ServerMailModel.findRewardsMails(serverId, roleId); - for(let mail of servermails) { - let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); - if(myStatus && myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) continue; - originMails.push({ mailType: GM_MAIL_TYPE.SERVER, mail }) - } - } - - let mailGoods: ItemInter[] = [], mails: MailParam[] = []; - for(let { mail, mailType } of originMails) { - let { isEquipOver, jewelCount: newEquipCount } = checkMailGoods(mail, jewelCount); - if(isEquipOver) { - if(type == RECEIVE_MAIL_TYPE.SINGLE) { - return resResult(STATUS.EQUIP_IS_OVER); - } else { - continue; // 如果有装备数量超过,那么一键领取这条邮件就不领了 - } - } - jewelCount = newEquipCount; - - if(mailType == GM_MAIL_TYPE.SINGLE) { - mail = await MailModel.updateStatusWithCondition(mail._id, MAIL_STATUS.RECEIVED); - } else if (mailType == GM_MAIL_TYPE.GROUP) { - mail = await GroupMailModel.updateStatusWithCondition(mail._id, roleId, MAIL_STATUS.RECEIVED); - } else if (mailType == GM_MAIL_TYPE.SERVER) { - mail = await ServerMailModel.updateStatusWithCondition(mail._id, roleId, MAIL_STATUS.RECEIVED, mail); - } - if(!mail) return resResult(STATUS.MAIL_HAS_RECEIVE); - - let mailObj = new MailParam(mailType, mail, roleId); - mailGoods.push(...mailObj.goods); - mails.push(mailObj); - } - - let resGoods = await addItems(roleId, roleName, sid, mailGoods, ITEM_CHANGE_REASON.MAIL); - saveMailLog(session, mails); - return resResult(STATUS.SUCCESS, { mails, goods: resGoods }); - } -} \ No newline at end of file +import {Application, BackendSession, ChannelService} from 'pinus'; +import { MailModel, MailType } from '@db/Mail'; +import { GroupMailModel, GroupMailType } from '@db/GroupMail'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { MAIL_STATUS, GM_MAIL_TYPE } from '@consts/constModules/mailConst'; +import { addItems } from '../../../services/role/rewardService'; +import { checkMailGoods, getMails } from '../../../services/mailService'; +import { ServerMailModel, ServerMailType } from '@db/ServerMail'; +import { MailParam } from '@domain/roleField/mail'; +import { ItemInter, RewardInter } from '@pubUtils/interface'; +import { RoleModel } from '@db/Role'; +import { gameData } from '@pubUtils/data'; +import { ITEM_CHANGE_REASON, ITID, RECEIVE_MAIL_TYPE } from '../../../consts'; +import { BAG } from '@pubUtils/dicParam'; +import { saveMailLog } from '@pubUtils/logUtil'; + +export default function(app: Application) { + return new MailHandler(app); +} + +export class MailHandler { + constructor(private app: Application) { + + } + + public async getMails(msg:{}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + + const list = await getMails(roleId, serverId); + return resResult(STATUS.SUCCESS, { list }); + } + + public async refrshMails(msg:{}) { + + } + + public async readMail(msg: { id: string, mailType: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let { id, mailType } = msg; + let mails = []; + if (mailType == GM_MAIL_TYPE.SINGLE) { + let mail = await MailModel.getMailById(id); + if(mail && mail.status == MAIL_STATUS.CREATE) { + mail = await MailModel.updateStatusWithCondition(id, MAIL_STATUS.READ); + mails.push({ id, status: MAIL_STATUS.READ, mailType }); + } + + } else if (mailType == GM_MAIL_TYPE.GROUP) { + let mail = await GroupMailModel.getMailById(id); + if(mail) { + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(myStatus && myStatus.status == MAIL_STATUS.CREATE) { + mail = await GroupMailModel.updateStatusWithCondition(id, roleId, MAIL_STATUS.READ); + mails.push({ id, status: MAIL_STATUS.READ, mailType }); + } + } + } else if (mailType == GM_MAIL_TYPE.SERVER) { + let mail = await ServerMailModel.getMailById(id); + if(mail) { + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(!myStatus || myStatus.status == MAIL_STATUS.CREATE) { + mail = await ServerMailModel.updateStatusWithCondition(id, roleId, MAIL_STATUS.READ); + mails.push({ id, status: MAIL_STATUS.READ, mailType }); + } + } + } + // if (!mail) + // return resResult(STATUS.WRONG_PARMS); + return resResult(STATUS.SUCCESS, { mails }); + } + + public async delMails(msg: { id: string, mailType: number, type: number }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let serverId: number = session.get('serverId'); + let { id, type, mailType } = msg; + if (type == 1) {//单个删除 + let mail: MailType|GroupMailType|ServerMailType; + if (mailType == GM_MAIL_TYPE.SINGLE) { + mail = await MailModel.delMailById(id); + } else if (mailType == GM_MAIL_TYPE.GROUP) { + mail = await GroupMailModel.delMailById(id, roleId); + } else if (mailType == GM_MAIL_TYPE.SERVER) { + mail = await ServerMailModel.delMailById(id, roleId); + } + if (!mail) return resResult(STATUS.WRONG_PARMS); + + return resResult(STATUS.SUCCESS, { mails: [{ id: mail._id, mailType, status: MAIL_STATUS.DELETE}] }); + } else {//一键删除 + let singlemails = await MailModel.delMailsByRoleId(roleId); + let groupMails = await GroupMailModel.delMailsByRoleId(roleId); + let servermails = await ServerMailModel.delMailsByRoleId(roleId, serverId); + let mails: { id: string, mailType: GM_MAIL_TYPE, status: MAIL_STATUS }[] = []; + for(let mail of singlemails) { + mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.SINGLE, status: MAIL_STATUS.DELETE }); + } + for(let mail of groupMails) { + mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.GROUP, status: MAIL_STATUS.DELETE }); + } + for(let mail of servermails) { + mails.push({ id: mail._id, mailType: GM_MAIL_TYPE.SERVER, status: MAIL_STATUS.DELETE }); + } + return resResult(STATUS.SUCCESS, { mails }); + } + } + + public async getMailRewards(msg: { id: string, mailType: number, type: RECEIVE_MAIL_TYPE }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + let { id, type, mailType } = msg; + let { jewelCount } = await RoleModel.findByRoleId(roleId, 'jewelCount'); + + let originMails: {mailType: GM_MAIL_TYPE, mail: MailType|GroupMailType|ServerMailType}[] = [] + + if (type == RECEIVE_MAIL_TYPE.SINGLE) {//单个领取 + let mail: MailType|GroupMailType|ServerMailType; + if (mailType == GM_MAIL_TYPE.SINGLE) { + mail = await MailModel.getMailById(id); + if (!mail) return resResult(STATUS.WRONG_PARMS); + if(mail.status != MAIL_STATUS.READ && mail.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); + } else if (mailType == GM_MAIL_TYPE.GROUP) { + mail = await GroupMailModel.getMailById(id); + if (!mail) return resResult(STATUS.WRONG_PARMS); + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(!myStatus) return resResult(STATUS.WRONG_PARMS); + if(myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); + } else if (mailType == GM_MAIL_TYPE.SERVER) { + mail = await ServerMailModel.getMailById(id); + if (!mail) return resResult(STATUS.WRONG_PARMS); + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(myStatus && myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) return resResult(STATUS.WRONG_PARMS); + } + originMails.push({ mailType, mail }); + } else {//一键领取 + let singlemails = await MailModel.findRewardsMails(roleId); + for(let mail of singlemails) { + if(mail.status != MAIL_STATUS.READ && mail.status != MAIL_STATUS.CREATE) continue; + originMails.push({ mailType: GM_MAIL_TYPE.SINGLE, mail }); + } + let groupMails = await GroupMailModel.findRewardsMails(roleId); + for(let mail of groupMails) { + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(!myStatus) continue; + if(myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) continue; + originMails.push({ mailType: GM_MAIL_TYPE.GROUP, mail }) + } + let servermails = await ServerMailModel.findRewardsMails(serverId, roleId); + for(let mail of servermails) { + let myStatus = mail.roleStatus.find(cur => cur.roleId == roleId); + if(myStatus && myStatus.status != MAIL_STATUS.READ && myStatus.status != MAIL_STATUS.CREATE) continue; + originMails.push({ mailType: GM_MAIL_TYPE.SERVER, mail }) + } + } + + let mailGoods: ItemInter[] = [], mails: MailParam[] = []; + for(let { mail, mailType } of originMails) { + let { isEquipOver, jewelCount: newEquipCount } = checkMailGoods(mail, jewelCount); + if(isEquipOver) { + if(type == RECEIVE_MAIL_TYPE.SINGLE) { + return resResult(STATUS.EQUIP_IS_OVER); + } else { + continue; // 如果有装备数量超过,那么一键领取这条邮件就不领了 + } + } + jewelCount = newEquipCount; + + if(mailType == GM_MAIL_TYPE.SINGLE) { + mail = await MailModel.updateStatusWithCondition(mail._id, MAIL_STATUS.RECEIVED); + } else if (mailType == GM_MAIL_TYPE.GROUP) { + mail = await GroupMailModel.updateStatusWithCondition(mail._id, roleId, MAIL_STATUS.RECEIVED); + } else if (mailType == GM_MAIL_TYPE.SERVER) { + mail = await ServerMailModel.updateStatusWithCondition(mail._id, roleId, MAIL_STATUS.RECEIVED, mail); + } + if(!mail) return resResult(STATUS.MAIL_HAS_RECEIVE); + + let mailObj = new MailParam(mailType, mail, roleId); + mailGoods.push(...mailObj.goods); + mails.push(mailObj); + } + + let resGoods = await addItems(roleId, roleName, sid, mailGoods, ITEM_CHANGE_REASON.MAIL); + saveMailLog(session, mails); + return resResult(STATUS.SUCCESS, { mails, goods: resGoods }); + } +} + diff --git a/game-server/app/servers/role/handler/rankHandler.ts b/game-server/app/servers/role/handler/rankHandler.ts index 198caa323..8d85e500c 100644 --- a/game-server/app/servers/role/handler/rankHandler.ts +++ b/game-server/app/servers/role/handler/rankHandler.ts @@ -1,154 +1,155 @@ -import { Application, BackendSession, HandlerService, pinus, } from "pinus"; -import { resResult } from "../../../pubUtils/util"; -import { STATUS, getRedisKeyByRankType, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SELECT, RANK_FIRST_REWARD_STATUS, ITEM_CHANGE_REASON, REDIS_KEY } from "../../../consts"; -import {RoleModel} from "../../../db/Role"; -import { UserGuildModel } from "../../../db/UserGuild"; -import { GuildModel } from "../../../db/Guild"; -import { Rank, getGeneralRank, getRankFirstReward, getRankInHandler } from "../../../services/rankService"; -import { gameData } from "../../../pubUtils/data"; -import { addItems } from "../../../services/role/rewardService"; -import { RewardInter } from "../../../pubUtils/interface"; -import { RankFirstType } from "../../../db/RankFirst"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RoleHandler(app); -} - -export class RoleHandler { - constructor(private app: Application) { - } - - async getGeneralRank(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - - let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); - if (!role) return resResult(STATUS.WRONG_PARMS); - - let ranks = await getGeneralRank(role, serverId); - - return resResult(STATUS.SUCCESS, { ranks }); - } - - - async getRankReward(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let serverId = session.get('serverId'); - - let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); - if (!role) return resResult(STATUS.WRONG_PARMS); - - let ranks = await getRankFirstReward(role, serverId); - - return resResult(STATUS.SUCCESS, { ranks }); - } - - async getRank(msg: { type: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - - let { type } = msg; - let redisKey = getRedisKeyByRankType(type); - if (!redisKey) return resResult(STATUS.WRONG_PARMS); - let result = await getRankInHandler(redisKey, type, { serverId }, session); - return resResult(STATUS.SUCCESS, { type, ...result }); - } - - // 查看活跃排行榜 - async getGuildRank(msg: { type: number }, session: BackendSession) { - - let roleId = session.get('roleId'); - let serverId = session.get('serverId') - - let { type } = msg; - - let redisKey = getRedisKeyByRankType(type); - if (!redisKey) return resResult(STATUS.WRONG_PARMS); - - let r = new Rank(redisKey, { serverId }); - const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode'); - let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild?.guildCode || '' }); - if (!myRank) { - let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, GUILD_SELECT.RANK); - if (type == RANK_TYPE.GUILD_LV) { - myRank = await r.generMyRankWithGuild(guild.code, guild.lv, guild.lvUpdateTime, guild); - } else if (type == RANK_TYPE.GUILD_ACTIVE) { - myRank = await r.generMyRankWithGuild(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); - } - } - - return resResult(STATUS.SUCCESS, { type, ranks, myRank }); - } - - // 查看单个武将排行榜 - async getHeroRank(msg: { type: number, hid: number }, session: BackendSession) { - - let serverId = session.get('serverId') - - let { type, hid } = msg; - let redisKey = getRedisKeyByRankType(type); - if (!redisKey) return resResult(STATUS.WRONG_PARMS); - - let r = new Rank(redisKey, { serverId, hid }); - let ranks = await r.getRankByRange(200, 0); - - return resResult(STATUS.SUCCESS, { - type, hid, ranks - }); - } - - async receiveReward(msg: { type: number, id: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - let { type, id } = msg; - - let ids: number[] = []; - if (id == 0) { - gameData.generalRankReward.forEach((dic, id) => { - if (dic.rankId == type) { - ids.push(id); - } - }); - } else { - ids.push(id); - } - let rewards: RewardInter[] = []; - let canReceiveId: number[] = []; - let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); - - for (let id of ids) { - let dicReward = gameData.generalRankReward.get(id); - if (!dicReward || dicReward.rankId != type) continue; - - let rankFirst: RankFirstType = pinus.app.get('rankFirstRewards').get(serverId)?.get(id); - // console.log('*******', pinus.app.get('rankFirstRewards'), rankFirst); - if (!rankFirst) continue; - if (role.rankReceived.includes(id)) continue; - - let reward = dicReward.reward; - rewards = rewards.concat(reward); - canReceiveId.push(id); - } - - role = await RoleModel.receiveRankReward(roleId, canReceiveId); - if (canReceiveId.length <= 0) return resResult(STATUS.REWARD_CONDITION_NOT_REACH); - - let rewardStatus = canReceiveId.map(id => { - return { id, type, status: RANK_FIRST_REWARD_STATUS.RECEIVED } - }) - - let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RANK_REWARD); - - return resResult(STATUS.SUCCESS, { - rewards: rewardStatus, - goods - }) - } -} \ No newline at end of file +import { Application, BackendSession, HandlerService, pinus, } from "pinus"; +import { resResult } from "@pubUtils/util"; +import { STATUS, getRedisKeyByRankType, ROLE_SELECT, RANK_TYPE, HERO_SELECT, GUILD_SELECT, RANK_FIRST_REWARD_STATUS, ITEM_CHANGE_REASON, REDIS_KEY } from "../../../consts"; +import {RoleModel} from "@db/Role"; +import { UserGuildModel } from "@db/UserGuild"; +import { GuildModel } from "@db/Guild"; +import { Rank, getGeneralRank, getRankFirstReward, getRankInHandler } from "../../../services/rankService"; +import { gameData } from "@pubUtils/data"; +import { addItems } from "../../../services/role/rewardService"; +import { RewardInter } from "@pubUtils/interface"; +import { RankFirstType } from "@db/RankFirst"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RoleHandler(app); +} + +export class RoleHandler { + constructor(private app: Application) { + } + + async getGeneralRank(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + + let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); + if (!role) return resResult(STATUS.WRONG_PARMS); + + let ranks = await getGeneralRank(role, serverId); + + return resResult(STATUS.SUCCESS, { ranks }); + } + + + async getRankReward(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let serverId = session.get('serverId'); + + let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); + if (!role) return resResult(STATUS.WRONG_PARMS); + + let ranks = await getRankFirstReward(role, serverId); + + return resResult(STATUS.SUCCESS, { ranks }); + } + + async getRank(msg: { type: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + + let { type } = msg; + let redisKey = getRedisKeyByRankType(type); + if (!redisKey) return resResult(STATUS.WRONG_PARMS); + let result = await getRankInHandler(redisKey, type, { serverId }, session); + return resResult(STATUS.SUCCESS, { type, ...result }); + } + + // 查看活跃排行榜 + async getGuildRank(msg: { type: number }, session: BackendSession) { + + let roleId = session.get('roleId'); + let serverId = session.get('serverId') + + let { type } = msg; + + let redisKey = getRedisKeyByRankType(type); + if (!redisKey) return resResult(STATUS.WRONG_PARMS); + + let r = new Rank(redisKey, { serverId }); + const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode'); + let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild?.guildCode || '' }); + if (!myRank) { + let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, GUILD_SELECT.RANK); + if (type == RANK_TYPE.GUILD_LV) { + myRank = await r.generMyRankWithGuild(guild.code, guild.lv, guild.lvUpdateTime, guild); + } else if (type == RANK_TYPE.GUILD_ACTIVE) { + myRank = await r.generMyRankWithGuild(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); + } + } + + return resResult(STATUS.SUCCESS, { type, ranks, myRank }); + } + + // 查看单个武将排行榜 + async getHeroRank(msg: { type: number, hid: number }, session: BackendSession) { + + let serverId = session.get('serverId') + + let { type, hid } = msg; + let redisKey = getRedisKeyByRankType(type); + if (!redisKey) return resResult(STATUS.WRONG_PARMS); + + let r = new Rank(redisKey, { serverId, hid }); + let ranks = await r.getRankByRange(200, 0); + + return resResult(STATUS.SUCCESS, { + type, hid, ranks + }); + } + + async receiveReward(msg: { type: number, id: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + let { type, id } = msg; + + let ids: number[] = []; + if (id == 0) { + gameData.generalRankReward.forEach((dic, id) => { + if (dic.rankId == type) { + ids.push(id); + } + }); + } else { + ids.push(id); + } + let rewards: RewardInter[] = []; + let canReceiveId: number[] = []; + let role = await RoleModel.findByRoleId(roleId, 'rankReceived'); + + for (let id of ids) { + let dicReward = gameData.generalRankReward.get(id); + if (!dicReward || dicReward.rankId != type) continue; + + let rankFirst: RankFirstType = pinus.app.get('rankFirstRewards').get(serverId)?.get(id); + // console.log('*******', pinus.app.get('rankFirstRewards'), rankFirst); + if (!rankFirst) continue; + if (role.rankReceived.includes(id)) continue; + + let reward = dicReward.reward; + rewards = rewards.concat(reward); + canReceiveId.push(id); + } + + role = await RoleModel.receiveRankReward(roleId, canReceiveId); + if (canReceiveId.length <= 0) return resResult(STATUS.REWARD_CONDITION_NOT_REACH); + + let rewardStatus = canReceiveId.map(id => { + return { id, type, status: RANK_FIRST_REWARD_STATUS.RECEIVED } + }) + + let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.RANK_REWARD); + + return resResult(STATUS.SUCCESS, { + rewards: rewardStatus, + goods + }) + } +} + diff --git a/game-server/app/servers/role/handler/resonanceHandler.ts b/game-server/app/servers/role/handler/resonanceHandler.ts index 61648fe09..323f38f68 100644 --- a/game-server/app/servers/role/handler/resonanceHandler.ts +++ b/game-server/app/servers/role/handler/resonanceHandler.ts @@ -1,193 +1,194 @@ -import { Application, BackendSession, HandlerService, } from 'pinus'; -import { getInitEplace, getJewelDataMap, getResonanceDataMap, refreshResonanceData } from '../../../services/role/resonanceService'; -import { resResult } from '../../../pubUtils/util' -import { HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, LINEUP_NUM, RESONANCE, STATUS } from '../../../consts'; -import { ResonanceModel } from '../../../db/Resonance'; -import { gameData } from '../../../pubUtils/data'; -import { RoleModel } from '../../../db/Role'; -import { handleCost } from '../../../services/role/rewardService'; -import { HeroModel } from '../../../db/Hero'; -import { ArtifactModel, ArtifactModelType } from '../../../db/Artifact'; -import { calculateCeWithHero } from '../../../services/playerCeService'; -import { HeroParam } from '../../../domain/roleField/hero'; -import { pick } from 'underscore'; -import { ResonanceHistoryModel } from '../../../db/ResonanceHistory'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new HeroHandler(app); -} - -export class HeroHandler { - constructor(private app: Application) { - } - - /** - * 获取最新数据(会刷新) - * @param msg - * @param session - * @returns - */ - async getData(msg: {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - const resonances = await refreshResonanceData(roleId, serverId, sid); - - return resResult(STATUS.SUCCESS, resonances) - } - - /** - * 解锁阵位 - * @param msg - * @param session - * @returns - */ - async unlockPosition(msg: { position: number }, session: BackendSession) { - const { position } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - - let dbResonance = await ResonanceModel.findByPosition(roleId, position); - if (dbResonance) return resResult(STATUS.RESONANCE_POSITION_LOCK); - - const dicResonance = gameData.resonance.get(position); - if (!dicResonance) return resResult(STATUS.RESONANCE_POSITION_NOT_FOUND); - - const role = await RoleModel.findByRoleId(roleId); - if (!role || !role.lv || role.lv < (dicResonance?.openLimit || 0)) return resResult(STATUS.RESONANCE_POSITION_LV_NOT_ENOUGH); - - let costResult = await handleCost(roleId, sid, dicResonance.openConsume, ITEM_CHANGE_REASON.RESONANCE_LOCK_POSITION); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let result = await ResonanceModel.updateByPosition(roleId, position, {}); - - if (!result || !result.position) return resResult(STATUS.RESONANCE_POSITION_LOCK_FAIL); - - return resResult(STATUS.SUCCESS, { position: result.position }); - } - - /** - * 武将上阵 - * @param msg - * @param session - * @returns - */ - async heroPutPosition(msg: { position: number, hid: number }, session: BackendSession) { - const { position, hid } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - // if (!await getStartLimt(roleId)) return resResult(STATUS.RESONANCE_NO_START); - let { dbResonanceMap } = await getResonanceDataMap(roleId); - let dbRole = await RoleModel.findByRoleId(roleId); - if (dbResonanceMap.size + LINEUP_NUM >= (dbRole?.heroNum || 0)) return resResult(STATUS.RESONANCE_PUT_NOT_POSITION) - - let dbResonance = await ResonanceModel.findByPosition(roleId, position); - if (!dbResonance) return resResult(STATUS.RESONANCE_POSITION_UNLOCK); - if (dbResonance.hid) return resResult(STATUS.RESONANCE_POSITION_EXIST_HID); - - let dbHeroes = await HeroModel.findByHidAndRole(hid, roleId); - if (!dbHeroes) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - - let { lv = 1, exp = 0, job = 0, jobStage = 0, skinId, skins = [], connections = [], ePlace = [], seqId, ce } = dbHeroes; - - //检测养成维度 - if (lv > 1) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_LV); - // if (jobStage) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_JOBSTAGE); - if (skins.find(cur => (cur?.usedTalentPoint || 0) > 0)) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_TALENT); - if (connections.length > 0) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_CONNECT); - // if (ePlace.length > 0) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); - if (ePlace.length > 0) { - for (let obj of ePlace) { - let newEplace = await getInitEplace(obj.id, skinId); - if (obj.lv != newEplace.lv || obj.quality != newEplace.quality || obj.qualityStage != newEplace.qualityStage || - obj.star != newEplace.star || obj.starStage != newEplace.starStage || obj.jewel != newEplace.jewel) { - return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); - } - for (let st of obj.stones) { - if (st.stone != (newEplace.stones.find(cur => cur.id == st.id)?.stone || 0)) { - return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); - } - } - } - } - - let result = await ResonanceModel.updateByPosition(roleId, position, { hid, seqId, lv, exp, job, jobStage, skinId, skins, connections, ePlace, ce }); - if (!result) return resResult(STATUS.RESONANCE_PUT_POSITION_FAIL); - - const resonances = await refreshResonanceData(roleId, serverId, sid); - - return resResult(STATUS.SUCCESS, resonances) - } - - /** - * 武将下阵 - * @param msg - * @param session - * @returns - */ - async heroOffPosition(msg: { position: number, hid: number }, session: BackendSession) { - const { position, hid } = msg; - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - let dbResonance = await ResonanceModel.findByPositionAndHid(roleId, position, hid); - if (!dbResonance) return resResult(STATUS.RESONANCE_NOT_PUT_POSITION); - - let dbHero = await HeroModel.findByHidAndRole(hid, roleId); - if (!dbHero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); - - let { lv = 1, exp = 0, job = 0, jobStage = 0, skinId, skins = [], connections = [], ePlace = [], seqId } = dbResonance; - for (let obj of dbHero.skins) { - let newSkin = skins.find(cur => cur.id == obj.id); - if (newSkin) { - obj.skinId = newSkin.skinId; - obj.enable = newSkin.enable; - obj.talent = newSkin.talent; - obj.usedTalentPoint = newSkin.usedTalentPoint; - } - } - for (let obj of dbHero.ePlace) { - let tempEPlace = ePlace.find(cur => cur.id == obj.id); - if (!tempEPlace && (!RESONANCE.JEWEL || !RESONANCE.STONE) && (obj.jewel || obj.stones.find(cur => cur.stone != 0))) { - ePlace.push({ ...await getInitEplace(obj.id, skinId) }); - tempEPlace = ePlace.find(cur => cur.id == obj.id); - } - if (!RESONANCE.JEWEL && obj.jewel) { - tempEPlace.jewel = obj.jewel; - } - if (!RESONANCE.STONE && obj.stones.find(cur => cur.stone != 0)) { - tempEPlace.stones = obj.stones; - } - } - let heroResult = await HeroModel.updateHeroInfo(roleId, hid, { lv, exp, job, jobStage, skinId, skins: dbHero.skins, connections, ePlace }); - if (!heroResult) return resResult(STATUS.RESONANCE_OFF_POSITION_FAIL); - - // 重新计算战力 - let dbJewelMap = await getJewelDataMap([heroResult]); - let artifact = await ArtifactModel.findbySeqId(roleId, seqId); - let artifacts: ArtifactModelType[] = []; - if (artifact) { - artifacts = [artifact] - } - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, hid, heroResult, { jewels: [...dbJewelMap.values()], heroes: [heroResult], artifacts }); - - - await ResonanceModel.deletePosition(roleId, position); - let result = await ResonanceModel.updateByPosition(roleId, position, {}); - if (!result || result.hid) return resResult(STATUS.RESONANCE_OFF_POSITION_FAIL); - await ResonanceHistoryModel.updateByPosition(roleId, position, { ...dbResonance }); - - const resonances = await refreshResonanceData(roleId, serverId, sid); - - return resResult(STATUS.SUCCESS, { - curHero: { isResonance: false, ...pick(new HeroParam(curHero), ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'skinId', 'skins', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) }, - ...resonances, - }) - } - -} \ No newline at end of file +import { Application, BackendSession, HandlerService, } from 'pinus'; +import { getInitEplace, getJewelDataMap, getResonanceDataMap, refreshResonanceData } from '../../../services/role/resonanceService'; +import { resResult } from '@pubUtils/util' +import { HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, LINEUP_NUM, RESONANCE, STATUS } from '../../../consts'; +import { ResonanceModel } from '@db/Resonance'; +import { gameData } from '@pubUtils/data'; +import { RoleModel } from '@db/Role'; +import { handleCost } from '../../../services/role/rewardService'; +import { HeroModel } from '@db/Hero'; +import { ArtifactModel, ArtifactModelType } from '@db/Artifact'; +import { calculateCeWithHero } from '../../../services/playerCeService'; +import { HeroParam } from '@domain/roleField/hero'; +import { pick } from 'underscore'; +import { ResonanceHistoryModel } from '@db/ResonanceHistory'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new HeroHandler(app); +} + +export class HeroHandler { + constructor(private app: Application) { + } + + /** + * 获取最新数据(会刷新) + * @param msg + * @param session + * @returns + */ + async getData(msg: {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + const resonances = await refreshResonanceData(roleId, serverId, sid); + + return resResult(STATUS.SUCCESS, resonances) + } + + /** + * 解锁阵位 + * @param msg + * @param session + * @returns + */ + async unlockPosition(msg: { position: number }, session: BackendSession) { + const { position } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + + let dbResonance = await ResonanceModel.findByPosition(roleId, position); + if (dbResonance) return resResult(STATUS.RESONANCE_POSITION_LOCK); + + const dicResonance = gameData.resonance.get(position); + if (!dicResonance) return resResult(STATUS.RESONANCE_POSITION_NOT_FOUND); + + const role = await RoleModel.findByRoleId(roleId); + if (!role || !role.lv || role.lv < (dicResonance?.openLimit || 0)) return resResult(STATUS.RESONANCE_POSITION_LV_NOT_ENOUGH); + + let costResult = await handleCost(roleId, sid, dicResonance.openConsume, ITEM_CHANGE_REASON.RESONANCE_LOCK_POSITION); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let result = await ResonanceModel.updateByPosition(roleId, position, {}); + + if (!result || !result.position) return resResult(STATUS.RESONANCE_POSITION_LOCK_FAIL); + + return resResult(STATUS.SUCCESS, { position: result.position }); + } + + /** + * 武将上阵 + * @param msg + * @param session + * @returns + */ + async heroPutPosition(msg: { position: number, hid: number }, session: BackendSession) { + const { position, hid } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + // if (!await getStartLimt(roleId)) return resResult(STATUS.RESONANCE_NO_START); + let { dbResonanceMap } = await getResonanceDataMap(roleId); + let dbRole = await RoleModel.findByRoleId(roleId); + if (dbResonanceMap.size + LINEUP_NUM >= (dbRole?.heroNum || 0)) return resResult(STATUS.RESONANCE_PUT_NOT_POSITION) + + let dbResonance = await ResonanceModel.findByPosition(roleId, position); + if (!dbResonance) return resResult(STATUS.RESONANCE_POSITION_UNLOCK); + if (dbResonance.hid) return resResult(STATUS.RESONANCE_POSITION_EXIST_HID); + + let dbHeroes = await HeroModel.findByHidAndRole(hid, roleId); + if (!dbHeroes) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + + let { lv = 1, exp = 0, job = 0, jobStage = 0, skinId, skins = [], connections = [], ePlace = [], seqId, ce } = dbHeroes; + + //检测养成维度 + if (lv > 1) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_LV); + // if (jobStage) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_JOBSTAGE); + if (skins.find(cur => (cur?.usedTalentPoint || 0) > 0)) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_TALENT); + if (connections.length > 0) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_CONNECT); + // if (ePlace.length > 0) return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); + if (ePlace.length > 0) { + for (let obj of ePlace) { + let newEplace = await getInitEplace(obj.id, skinId); + if (obj.lv != newEplace.lv || obj.quality != newEplace.quality || obj.qualityStage != newEplace.qualityStage || + obj.star != newEplace.star || obj.starStage != newEplace.starStage || obj.jewel != newEplace.jewel) { + return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); + } + for (let st of obj.stones) { + if (st.stone != (newEplace.stones.find(cur => cur.id == st.id)?.stone || 0)) { + return resResult(STATUS.RESONANCE_PUT_POSITION_EXIST_EQUIP); + } + } + } + } + + let result = await ResonanceModel.updateByPosition(roleId, position, { hid, seqId, lv, exp, job, jobStage, skinId, skins, connections, ePlace, ce }); + if (!result) return resResult(STATUS.RESONANCE_PUT_POSITION_FAIL); + + const resonances = await refreshResonanceData(roleId, serverId, sid); + + return resResult(STATUS.SUCCESS, resonances) + } + + /** + * 武将下阵 + * @param msg + * @param session + * @returns + */ + async heroOffPosition(msg: { position: number, hid: number }, session: BackendSession) { + const { position, hid } = msg; + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + let dbResonance = await ResonanceModel.findByPositionAndHid(roleId, position, hid); + if (!dbResonance) return resResult(STATUS.RESONANCE_NOT_PUT_POSITION); + + let dbHero = await HeroModel.findByHidAndRole(hid, roleId); + if (!dbHero) return resResult(STATUS.ROLE_HERO_NOT_EXISTS); + + let { lv = 1, exp = 0, job = 0, jobStage = 0, skinId, skins = [], connections = [], ePlace = [], seqId } = dbResonance; + for (let obj of dbHero.skins) { + let newSkin = skins.find(cur => cur.id == obj.id); + if (newSkin) { + obj.skinId = newSkin.skinId; + obj.enable = newSkin.enable; + obj.talent = newSkin.talent; + obj.usedTalentPoint = newSkin.usedTalentPoint; + } + } + for (let obj of dbHero.ePlace) { + let tempEPlace = ePlace.find(cur => cur.id == obj.id); + if (!tempEPlace && (!RESONANCE.JEWEL || !RESONANCE.STONE) && (obj.jewel || obj.stones.find(cur => cur.stone != 0))) { + ePlace.push({ ...await getInitEplace(obj.id, skinId) }); + tempEPlace = ePlace.find(cur => cur.id == obj.id); + } + if (!RESONANCE.JEWEL && obj.jewel) { + tempEPlace.jewel = obj.jewel; + } + if (!RESONANCE.STONE && obj.stones.find(cur => cur.stone != 0)) { + tempEPlace.stones = obj.stones; + } + } + let heroResult = await HeroModel.updateHeroInfo(roleId, hid, { lv, exp, job, jobStage, skinId, skins: dbHero.skins, connections, ePlace }); + if (!heroResult) return resResult(STATUS.RESONANCE_OFF_POSITION_FAIL); + + // 重新计算战力 + let dbJewelMap = await getJewelDataMap([heroResult]); + let artifact = await ArtifactModel.findbySeqId(roleId, seqId); + let artifacts: ArtifactModelType[] = []; + if (artifact) { + artifacts = [artifact] + } + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, hid, heroResult, { jewels: [...dbJewelMap.values()], heroes: [heroResult], artifacts }); + + + await ResonanceModel.deletePosition(roleId, position); + let result = await ResonanceModel.updateByPosition(roleId, position, {}); + if (!result || result.hid) return resResult(STATUS.RESONANCE_OFF_POSITION_FAIL); + await ResonanceHistoryModel.updateByPosition(roleId, position, { ...dbResonance }); + + const resonances = await refreshResonanceData(roleId, serverId, sid); + + return resResult(STATUS.SUCCESS, { + curHero: { isResonance: false, ...pick(new HeroParam(curHero), ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'skinId', 'skins', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) }, + ...resonances, + }) + } + +} + diff --git a/game-server/app/servers/role/handler/roleHandler.ts b/game-server/app/servers/role/handler/roleHandler.ts index 5eb8c3617..cc048c509 100644 --- a/game-server/app/servers/role/handler/roleHandler.ts +++ b/game-server/app/servers/role/handler/roleHandler.ts @@ -1,647 +1,648 @@ -import { STATUS } from '../../../consts/statusCode'; -import { RoleModel, RoleUpdate } from './../../../db/Role'; -import { HeroModel, HeroType, HeroUpdate } from '../../../db/Hero'; -import { resResult, decodeIdCntArrayStr, parseGoodStr, genCode } from '../../../pubUtils/util'; -import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; -import { handleCost, addItems, getGoldObject, getCoinObject } from '../../../services/role/rewardService'; -import { getTitle, getTeraph, gameData, getScollByStar, getFriendLvByExp, getHeroExpByLv, getExpByLv } from '../../../pubUtils/data'; -import { SCHOOL, SCROLL, EXTERIOR, SCRIPT } from '../../../pubUtils/dicParam'; -import { getAtrrNameById } from '../../../consts/constModules/abilityConst' -import { findIndex, pick } from 'underscore'; -import { SclResultInter, SclPosInter } from '../../../pubUtils/interface'; -import { SchoolModel } from '../../../db/School'; -import { getTeraphStrengthenResult, getSchoolList } from '../../../services/roleService' -import { HERO_SYSTEM_TYPE, LINEUP_NUM, ROLE_SELECT, REDIS_KEY, TASK_TYPE, DEFAULT_HEROES, DEFAULT_HERO_LV, DEFAULT_ITEMS, DEFAULT_EQUIPS, DEFAULT_GOLD, DEFAULT_COIN, DEBUG_MAGIC_WORD, COUNTER, DEFAULT_LV, ITEM_CHANGE_REASON, PUSH_ROUTE, POP_UP_SHOP_CONDITION_TYPE, LEAGUE_AUTH } from '../../../consts'; -import { checkBattleHeroesByHid, roleLevelup } from '../../../services/normalBattleService'; -import { Rank } from '../../../services/rankService'; -import { updateUserInfo } from '../../../services/redisService'; -import { checkTask, checkTaskInActiveScroll } from '../../../services/task/taskService'; -import { RScriptRecordModel } from '../../../db/RScriptRecord'; -import * as dicParam from '../../../pubUtils/dicParam'; -import Counter from '../../../db/Counter'; -import { UserModel } from '../../../db/User'; -import { checkFilterWords, reportTAEvent, treatRoleName } from '../../../services/sdkService'; -import { createHeroes } from '../../../services/role/createHero'; -import { calculateCeWithHero, calculateCeWithRole } from '../../../services/playerCeService'; -import { sendMessageToUserWithSuc } from '../../../services/pushService'; -import { GuildLeader, LeagueLeader } from '../../../domain/rank'; -import { checkPopUpCondition } from '../../../services/activity/popUpShopService'; -import { isGoodsHidden, isHeroHidden } from '../../../services/dataService'; -import { updateGVGBattleRoleInfo, getMyAuth } from '../../../services/gvg/gvgTeamService'; -import { GVGLeagueModel } from '../../../db/GVGLeague'; -import { deletRole } from '../../../pubUtils/roleUtil'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RoleHandler(app); -} - -export class RoleHandler { - constructor(private app: Application) { - } - - async initRole(msg: { roleName: string }, session: BackendSession) { - // console.log('******** initRole start', Date.now()); - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let sid: string = session.get('sid'); - - - let { roleName } = msg; - let role = await RoleModel.findByRoleId(roleId, 'roleName hasInit title teraphs lv', true); - if (role.hasInit) return resResult(STATUS.ROLE_HAS_INIT); - - let checkName = await RoleModel.checkName(roleName, serverId); - if (checkName) return resResult(STATUS.NAME_HAS_USED); - - let { resultHeroes: heroes } = await createHeroes(roleId, roleName, sid, serverId, DEFAULT_HEROES.map(hid => ({hid, count: 1})), { roleName, hasInit: true, title: role.title, teraphs: role.teraphs, lv: role.lv }); - // role = await RoleModel.updateRoleInfo(roleId, { roleName, hasInit: true }); // 在算战力的时候一起更新 - session.set('roleName', roleName); - session.push('roleName', () => { }); - - let items = [].concat(DEFAULT_ITEMS, DEFAULT_EQUIPS, [getGoldObject(DEFAULT_GOLD)], [getCoinObject(DEFAULT_COIN)]); - await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.DEFAULT_ITEMS); - - let battleId = SCRIPT.SCRIPT_BATTLE_ID; - let warInfo = gameData.war.get(battleId); - await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, 2, SCRIPT.SCRIPT_NAME); - - // console.log('******** initRole end', Date.now()); - return resResult(STATUS.SUCCESS, { - roleId, roleName, heroes - }) - } - - async getRoleInfo(msg: { targetRoleId: string }, session: BackendSession) { - let { targetRoleId } = msg; - let { roleId, roleName, head = EXTERIOR.EXTERIOR_FACE, frame = EXTERIOR.EXTERIOR_FACECASE, spine = EXTERIOR.EXTERIOR_APPEARANCE, ce = 0, topLineup, topLineupCe = 0 } = await RoleModel.findByRoleId(targetRoleId); - return resResult(STATUS.SUCCESS, { roleId, roleName, head, frame, spine, ce, topLineup, topLineupCe }); - } - - //爵位 - async roleTitleLevelUp(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid: string = session.get('sid'); - const serverId = session.get('serverId'); - - - let role = await RoleModel.findByRoleId(roleId); - - let { title } = role; - let titleInfo = getTitle(title + 1); - if (!titleInfo) - return resResult(STATUS.DIC_DATA_NOT_FOUND) - if (titleInfo.lvLimited > role.lv) - return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH) - let consumes = titleInfo.material; - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TITLE_LEVEL_UP); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let update = { title: title + 1 } - let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TITLE, roleId, serverId, sid, update); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TITLE, { oldTitle: title, title: update.title }); // 弹出礼包 - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TITLE, { oldLv: title, newLv: update.title }); - return resResult(STATUS.SUCCESS, { roleId, title: curRole.title }); - } - - //神像强化 - async roleTeraphStrengthen(msg: { id: number, count: number }, session: BackendSession) { - let { id, count } = msg; - let roleId = session.get('roleId'); - let sid: string = session.get('sid'); - let serverId: number = session.get('serverId'); - - - let role = await RoleModel.findByRoleId(roleId, 'roleId teraphs gold coin'); - let teraphs = role.teraphs; - let index = findIndex(teraphs, { id }); - if (index < 0) - return resResult(STATUS.WRONG_PARMS); - let teraph = teraphs[index]; - let dicTeraph = getTeraph(id, teraph.grade); - if (!dicTeraph) - return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let { times, consumes, criAttr } = await getTeraphStrengthenResult(role, count, dicTeraph, teraph); - if (times == 0) - return resResult(STATUS.ROLE_TERAPH_NOT_STRENGTHEN); - - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TERAPH_STRENGTHEN); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TERAPH, roleId, serverId, sid, { teraphs }, { teraphId: id }); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TERAPH_STRENGTHEN, { count }); - - return resResult(STATUS.SUCCESS, { roleId, teraphs: curRole.teraphs, criAttr }); - } - - //神像进阶 - async roleTeraphQualityUp(msg: { id: number }, session: BackendSession) { - let { id } = msg; - let roleId = session.get('roleId'); - let sid: string = session.get('sid'); - const serverId = session.get('serverId'); - - - let role = await RoleModel.findByRoleId(roleId); - let teraphs = role.teraphs; - let index = findIndex(teraphs, { id }); - if (index < 0) - return resResult(STATUS.WRONG_PARMS); - let teraph = teraphs[index]; - let teraphInfo = getTeraph(id, teraph.grade); - if (!teraphInfo) - return resResult(STATUS.DIC_DATA_NOT_FOUND) - - for (let [attrId, val] of teraph.attr) { - if (val < teraphInfo.mainAttrMax.get(attrId)) - return resResult(STATUS.ROLE_TERAPH_NOT_QUILITY); - - teraph.attr.set(attrId, 0); - } - teraph.grade++; - - - let nextTeraphInfo = getTeraph(id, teraph.grade) - if (!nextTeraphInfo) - return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let consumes = teraphInfo.upGradeMaterial; - let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TERAPH_QUALITY_UP); - if (!result) - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TERAPH_UP, roleId, serverId, sid, { teraphs }, { teraphId: id }); - - // 神像进阶,进阶一次就触发一次礼包弹框 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TERAPH_STAGE_UP); - - return resResult(STATUS.SUCCESS, { roleId, teraphs: curRole.teraphs }); - } - - // 获得百家学宫 - async getSchoolList(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let school = await getSchoolList(roleId); - - return resResult(STATUS.SUCCESS, { school }); - - } - - // 摆放/替换/卸下武将 - async changeSchoolHero(msg: { schoolId: number, positionId: number, hid: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - const serverId = session.get('serverId'); - - let { schoolId, positionId, hid } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - if (!gameData.school.has(schoolId)) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id(str) => isOpen - if (!dicPosition.has(positionId.toString())) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - let isOpen = !!dicPosition.get(positionId.toString()); // 该位置是否解锁 - let curHero: HeroType = null; - if (hid > 0) { - let findHero = await SchoolModel.findByHid(roleId, hid); - if (!!findHero) { - return resResult(STATUS.ROLE_SCHOOL_HERO_USED); - } - - curHero = await HeroModel.findByHidAndRole(hid, roleId); - if (!curHero) return resResult(STATUS.HERO_NOT_FIND); - } - - let curSchool = await SchoolModel.findBySclAndPos(roleId, schoolId, positionId); - let preHid = 0; // 原先在该位置上的武将 - if (curSchool) { - isOpen = curSchool.isOpen; - preHid = curSchool.hid; - } - - - if (!isOpen) { - return resResult(STATUS.ROLE_SCHOOL_POSITION_LOCKED); - } - - await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { hid, isOpen, star: curHero?.star??0, quality: curHero?.quality??0, colorStar: curHero?.colorStar??0 }); - await calculateCeWithRole(HERO_SYSTEM_TYPE.SCHOOL, roleId, serverId, sid, {}, { schoolId, hero: curHero, schoolHid: hid, preSchoolHid: preHid }); - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_SCHOOL_PUT_HERO, { hid, preHid }); - - return resResult(STATUS.SUCCESS, { - schoolId, positionId, hid, preHid, isOpen - }); - - } - - // 解锁位置 - async unlockSchoolPosition(msg: { schoolId: number, positionId: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - - let { schoolId, positionId } = msg; - if (!gameData.school.has(schoolId)) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id(str) => isOpen - if (!dicPosition.has(positionId.toString())) { - return resResult(STATUS.DIC_DATA_NOT_FOUND); - } - let isOpen = !!dicPosition.get(positionId.toString()); // 该位置是否解锁 - if (isOpen) { - return resResult(STATUS.ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED); - } - let curSchool = await SchoolModel.findBySclAndPos(roleId, schoolId, positionId); - if (curSchool && curSchool.isOpen) { - return resResult(STATUS.ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED); - } - - const cost = parseGoodStr(SCHOOL.SCHOOL_UNLOCK_COIN); - const costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.UNLOCK_SCHOOL_POSITION); - if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - curSchool = await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { isOpen: true }) - - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_SCHOOL_UNLOCK); - - return resResult(STATUS.SUCCESS, { - schoolId, positionId, hid: curSchool.hid, isOpen: curSchool.isOpen - }); - } - - // 激活/升级名将谱 - async activeHeroScroll(msg: { hid: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - let serverId: number = session.get('serverId'); - - let { hid } = msg; - - if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); - - let dicHero = gameData.hero.get(hid); - if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let hero = await HeroModel.findByHidAndRole(hid, roleId, 'hid lv star colorStar quality scrollId scrollActive scrollStar scrollColorStar scrollQuality connections attr ce'); - if (!hero) return resResult(STATUS.HERO_NOT_FIND); - - let { star, colorStar, quality, scrollId, scrollActive, scrollStar, scrollColorStar, scrollQuality } = hero; - - let update = { - scrollActive, scrollId, scrollStar, scrollColorStar, scrollQuality - }; - if (!scrollActive) { // 初次激活 - update.scrollActive = true; - update.scrollStar = dicHero.initialStar; - update.scrollQuality = dicHero.quality; - update.scrollColorStar = dicHero.initialColorStar; - } else { - if (star > scrollStar) { // 可以升星 - update.scrollStar++; - } else if (quality > scrollQuality && (quality != 4 || scrollQuality != 3)) { // 可以升品 - update.scrollQuality++; - } else if (colorStar > scrollColorStar) { // 可以升彩星 - update.scrollColorStar++; - update.scrollQuality = 4; - } else { - return resResult(STATUS.ROLE_SCROLL_REACH_MAX); - } - - } - - let dicHeroScroll = getScollByStar(dicHero.quality, update.scrollStar, update.scrollQuality, update.scrollColorStar); - update.scrollId = dicHeroScroll ? dicHeroScroll.id : 0; - - let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SCROLL, roleId, serverId, sid, hid, update); - - // 任务 - await checkTaskInActiveScroll(serverId, roleId, sid, scrollActive, hero); - - return resResult(STATUS.SUCCESS, { - curHero: pick(curHero, ['hid', 'scrollActive', 'scrollId', 'scrollStar', 'scrollColorStar', 'scrollQuality']) - }); - } - - // 保存展示阵容 - async saveShowLineup(msg: { showLineup: number[] }, session: BackendSession) { - let { showLineup } = msg; - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - - if(isHeroHidden(...showLineup)) return resResult(STATUS.HERO_IS_HIDDEN); - - let checkHeroes = await checkBattleHeroesByHid(roleId, showLineup); - if (showLineup.length > 0 && !checkHeroes) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); - - if (showLineup.length > LINEUP_NUM) { - return resResult(STATUS.LINEUP_MAX); - } - - let role = await RoleModel.updateRoleInfo(roleId, { showLineup }); - let r = new Rank(REDIS_KEY.SHOW_LINEUP, {}); - await r.generParamAndSet(REDIS_KEY.SHOW_LINEUP, { roleId }, { role }); - - return resResult(STATUS.SUCCESS, { showLineup: role.showLineup }); - } - - // 更换头像 - async setHead(msg: { id: number }, session: BackendSession) { - let { id } = msg; - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - - if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); - - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - if (!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let { heads } = role; - let curHead = heads.find(cur => cur.id == id); - if (!curHead) return resResult(STATUS.HEAD_NOT_FOUND); - if (curHead.enable) return resResult(STATUS.HEAD_IS_WEARING); - if (!curHead.status) return resResult(STATUS.HEAD_IS_LOCKED); - - let oldHead = heads.find(cur => cur.enable); // 穿戴中的头像 - if (oldHead) { - oldHead.enable = false; - } - curHead.enable = true; - - role = await RoleModel.updateRoleInfo(roleId, { heads }); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'head', value: id }]); - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - } - - return resResult(STATUS.SUCCESS, { heads: role.heads, head: role.head }); - } - - // 更换相框 - async setFrame(msg: { id: number }, session: BackendSession) { - let { id } = msg; - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - - if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); - - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - if (!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let { frames } = role; - let curFrame = frames.find(cur => cur.id == id); - if (!curFrame) return resResult(STATUS.FRAME_NOT_FOUND); - if (curFrame.enable) return resResult(STATUS.FRAME_IS_WEARING); - if (!curFrame.status) return resResult(STATUS.FRAME_IS_LOCKED); - - let oldHead = frames.find(cur => cur.enable); // 穿戴中的头像 - if (oldHead) { - oldHead.enable = false; - } - curFrame.enable = true; - - role = await RoleModel.updateRoleInfo(roleId, { frames }); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'frame', value: id }]); - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - } - - return resResult(STATUS.SUCCESS, { frames: role.frames, frame: role.frame }); - } - - // 更换形象 - async setSpine(msg: { id: number }, session: BackendSession) { - let { id } = msg; - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - - if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); - - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - if (!role) return resResult(STATUS.ROLE_NOT_FOUND); - - let { spines } = role; - let curSpine = spines.find(cur => cur.id == id); - if (!curSpine) return resResult(STATUS.SPINE_NOT_FOUND); - if (curSpine.enable) return resResult(STATUS.SPINE_IS_WEARING); - if (!curSpine.status) return resResult(STATUS.SPINE_IS_LOCKED); - - let oldHead = spines.find(cur => cur.enable); // 穿戴中的头像 - if (oldHead) { - oldHead.enable = false; - } - curSpine.enable = true; - - role = await RoleModel.updateRoleInfo(roleId, { spines }); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'spine', value: id }]); - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - } - - return resResult(STATUS.SUCCESS, { spines: role.spines, spine: role.spine }); - } - - // 改名 - async rename(msg: { roleName: string }, session: BackendSession) { - let { roleName } = msg; - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let guildCode = session.get('guildCode'); - let sid = session.get('sid'); - if(!roleName) return resResult(STATUS.WRONG_PARMS); - - let checkName = await RoleModel.checkName(roleName, serverId); - if (checkName) return resResult(STATUS.NAME_HAS_USED); - - let role = await RoleModel.findByRoleId(roleId, 'renameCnt'); - let costGold = role.renameCnt >= dicParam.NAMEPLATE.NAMEPLATE_FREECOST? dicParam.NAMEPLATE.NAMEPLATE_FEECOST: 0; - if(costGold > 0) { - let result = await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.RENAME); - if(!result) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); - } - - role = await RoleModel.incRoleInfo(roleId, { renameCnt: 1 }, { roleName }); - session.set('roleName', role.roleName); - session.push('roleName', () => { }); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'roleName', value: roleName }]); - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(myLeague && getMyAuth(myLeague, roleId) == LEAGUE_AUTH.LEADER) { - await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'leader', value: new LeagueLeader(role) }]); - } - - } - await updateGVGBattleRoleInfo(serverId, roleId, { roleName }); - - return resResult(STATUS.SUCCESS, { roleName: role.roleName, renameCnt: role.renameCnt }); - } - - async saveGuide(msg: { ids: number[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let { ids } = msg; - if(ids == undefined || ids.length <= 0) { - return resResult(STATUS.WRONG_PARMS); - } - let role = await RoleModel.saveGuide(roleId, ids); - return resResult(STATUS.SUCCESS, { - guide: role.guide - }); - } - - async setPushMsgTrigger(msg: { isClosePush: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - const { isClosePush } = msg; - - let role = await RoleModel.setPushMsgOpen(roleId, isClosePush); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - return resResult(STATUS.SUCCESS, { - isClosePush: role.isClosePush - }) - } - - async setHasComment(msg: { hasComment: boolean }, session: BackendSession) { - const roleId = session.get('roleId'); - const { hasComment } = msg; - - let role = await RoleModel.setHasComment(roleId, hasComment); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - return resResult(STATUS.SUCCESS, { - hasComment: role.hasComment - }) - } - - // 防沉迷调试用,推送窗口 - async debugPlayerTime(msg: { type: number }, session: BackendSession) { - let { type } = msg; - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - if (type == 1) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest: true, - guestTime: 60 * 60, // 游客已体验时间 - hasAuthenticated: false, // 是否进行过实名认证 - isAdult: false, // 是否已成年 - todayPlayTime: 60 * 60, // 今天已游戏时长 - type: 1 - }, sid); - } else if (type == 2) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest: false, - guestTime: 0, // 游客已体验时间 - hasAuthenticated: true, // 是否进行过实名认证 - isAdult: false, // 是否已成年 - todayPlayTime: 60 * 60, // 今天已游戏时长 - type: 2 - }, sid); - } else if (type == 3) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest: false, - guestTime: 0, // 游客已体验时间 - hasAuthenticated: true, // 是否进行过实名认证 - isAdult: false, // 是否已成年 - todayPlayTime: 3 * 60 * 60, // 今天已游戏时长 - type: 3 - }, sid); - } else if (type == 4) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest: false, - guestTime: 0, // 游客已体验时间 - hasAuthenticated: true, // 是否进行过实名认证 - isAdult: false, // 是否已成年 - todayPlayTime: 1.5 * 60 * 60, // 今天已游戏时长 - type: 4 - }, sid); - } - - return resResult(STATUS.SUCCESS); - } - - // debug接口,清空某个角色 - async debugClearRole(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let roleId = session.get('roleId'); - let role = await RoleModel.findByRoleId(roleId); - if(!role) return resResult(STATUS.ROLE_NOT_FOUND); - if(role.hasInit) { - await deletRole(roleId); - } - - return resResult(STATUS.SUCCESS, { roleId: role?.roleId }); - } - - async debugRoleLvUp(msg: { magicWord: string, lv: number }, session: BackendSession) { - const { magicWord, lv } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - let roleId = session.get('roleId'); - let roleLvInfo = gameData.kingexp.get(lv - 1); - let role = await RoleModel.updateRoleInfo(roleId, { lv, exp: roleLvInfo.sum }); - - return resResult(STATUS.SUCCESS, { lv: role.lv }); - } - - public async debugSetRole(msg: { magicWord: string, params: RoleUpdate }, session: BackendSession) { - let roleId: string = session.get('roleId'); - - let { magicWord, params } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let role = await RoleModel.updateRoleInfo(roleId, params); - - return resResult(STATUS.SUCCESS, { role }); - - } - - public async test(msg: { magicWord: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - let serverId: string = session.get('serverId'); - - let { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - let role = await RoleModel.findByRoleId(roleId); - let user = await UserModel.findUserByUid(role.userInfo.uid); - - reportTAEvent(roleId, 'test', { serverId }, user.ip); - - return resResult(STATUS.SUCCESS); - - } - - async debugTreatRoleName(msg: { magicWord: string }, session: BackendSession) { - let roleId: string = session.get('roleId'); - - let { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - - await treatRoleName(roleId, true); - return resResult(STATUS.SUCCESS); - } -} +import { STATUS } from '@consts/statusCode'; +import { RoleModel, RoleUpdate } from './../../../db/Role'; +import { HeroModel, HeroType, HeroUpdate } from '@db/Hero'; +import { resResult, decodeIdCntArrayStr, parseGoodStr, genCode } from '@pubUtils/util'; +import { Application, BackendSession, pinus, HandlerService, } from 'pinus'; +import { handleCost, addItems, getGoldObject, getCoinObject } from '../../../services/role/rewardService'; +import { getTitle, getTeraph, gameData, getScollByStar, getFriendLvByExp, getHeroExpByLv, getExpByLv } from '@pubUtils/data'; +import { SCHOOL, SCROLL, EXTERIOR, SCRIPT } from '@pubUtils/dicParam'; +import { getAtrrNameById } from '@consts/constModules/abilityConst' +import { findIndex, pick } from 'underscore'; +import { SclResultInter, SclPosInter } from '@pubUtils/interface'; +import { SchoolModel } from '@db/School'; +import { getTeraphStrengthenResult, getSchoolList } from '../../../services/roleService' +import { HERO_SYSTEM_TYPE, LINEUP_NUM, ROLE_SELECT, REDIS_KEY, TASK_TYPE, DEFAULT_HEROES, DEFAULT_HERO_LV, DEFAULT_ITEMS, DEFAULT_EQUIPS, DEFAULT_GOLD, DEFAULT_COIN, DEBUG_MAGIC_WORD, COUNTER, DEFAULT_LV, ITEM_CHANGE_REASON, PUSH_ROUTE, POP_UP_SHOP_CONDITION_TYPE, LEAGUE_AUTH } from '../../../consts'; +import { checkBattleHeroesByHid, roleLevelup } from '../../../services/normalBattleService'; +import { Rank } from '../../../services/rankService'; +import { updateUserInfo } from '../../../services/redisService'; +import { checkTask, checkTaskInActiveScroll } from '../../../services/task/taskService'; +import { RScriptRecordModel } from '@db/RScriptRecord'; +import * as dicParam from '@pubUtils/dicParam'; +import Counter from '@db/Counter'; +import { UserModel } from '@db/User'; +import { checkFilterWords, reportTAEvent, treatRoleName } from '../../../services/sdkService'; +import { createHeroes } from '../../../services/role/createHero'; +import { calculateCeWithHero, calculateCeWithRole } from '../../../services/playerCeService'; +import { sendMessageToUserWithSuc } from '../../../services/pushService'; +import { GuildLeader, LeagueLeader } from '@domain/rank'; +import { checkPopUpCondition } from '../../../services/activity/popUpShopService'; +import { isGoodsHidden, isHeroHidden } from '../../../services/dataService'; +import { updateGVGBattleRoleInfo, getMyAuth } from '../../../services/gvg/gvgTeamService'; +import { GVGLeagueModel } from '@db/GVGLeague'; +import { deletRole } from '@pubUtils/roleUtil'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RoleHandler(app); +} + +export class RoleHandler { + constructor(private app: Application) { + } + + async initRole(msg: { roleName: string }, session: BackendSession) { + // console.log('******** initRole start', Date.now()); + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let sid: string = session.get('sid'); + + + let { roleName } = msg; + let role = await RoleModel.findByRoleId(roleId, 'roleName hasInit title teraphs lv', true); + if (role.hasInit) return resResult(STATUS.ROLE_HAS_INIT); + + let checkName = await RoleModel.checkName(roleName, serverId); + if (checkName) return resResult(STATUS.NAME_HAS_USED); + + let { resultHeroes: heroes } = await createHeroes(roleId, roleName, sid, serverId, DEFAULT_HEROES.map(hid => ({hid, count: 1})), { roleName, hasInit: true, title: role.title, teraphs: role.teraphs, lv: role.lv }); + // role = await RoleModel.updateRoleInfo(roleId, { roleName, hasInit: true }); // 在算战力的时候一起更新 + session.set('roleName', roleName); + session.push('roleName', () => { }); + + let items = [].concat(DEFAULT_ITEMS, DEFAULT_EQUIPS, [getGoldObject(DEFAULT_GOLD)], [getCoinObject(DEFAULT_COIN)]); + await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.DEFAULT_ITEMS); + + let battleId = SCRIPT.SCRIPT_BATTLE_ID; + let warInfo = gameData.war.get(battleId); + await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, 2, SCRIPT.SCRIPT_NAME); + + // console.log('******** initRole end', Date.now()); + return resResult(STATUS.SUCCESS, { + roleId, roleName, heroes + }) + } + + async getRoleInfo(msg: { targetRoleId: string }, session: BackendSession) { + let { targetRoleId } = msg; + let { roleId, roleName, head = EXTERIOR.EXTERIOR_FACE, frame = EXTERIOR.EXTERIOR_FACECASE, spine = EXTERIOR.EXTERIOR_APPEARANCE, ce = 0, topLineup, topLineupCe = 0 } = await RoleModel.findByRoleId(targetRoleId); + return resResult(STATUS.SUCCESS, { roleId, roleName, head, frame, spine, ce, topLineup, topLineupCe }); + } + + //爵位 + async roleTitleLevelUp(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid: string = session.get('sid'); + const serverId = session.get('serverId'); + + + let role = await RoleModel.findByRoleId(roleId); + + let { title } = role; + let titleInfo = getTitle(title + 1); + if (!titleInfo) + return resResult(STATUS.DIC_DATA_NOT_FOUND) + if (titleInfo.lvLimited > role.lv) + return resResult(STATUS.COM_BATTLE_LV_NOT_ENOUGH) + let consumes = titleInfo.material; + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TITLE_LEVEL_UP); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let update = { title: title + 1 } + let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TITLE, roleId, serverId, sid, update); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TITLE, { oldTitle: title, title: update.title }); // 弹出礼包 + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TITLE, { oldLv: title, newLv: update.title }); + return resResult(STATUS.SUCCESS, { roleId, title: curRole.title }); + } + + //神像强化 + async roleTeraphStrengthen(msg: { id: number, count: number }, session: BackendSession) { + let { id, count } = msg; + let roleId = session.get('roleId'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + + let role = await RoleModel.findByRoleId(roleId, 'roleId teraphs gold coin'); + let teraphs = role.teraphs; + let index = findIndex(teraphs, { id }); + if (index < 0) + return resResult(STATUS.WRONG_PARMS); + let teraph = teraphs[index]; + let dicTeraph = getTeraph(id, teraph.grade); + if (!dicTeraph) + return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let { times, consumes, criAttr } = await getTeraphStrengthenResult(role, count, dicTeraph, teraph); + if (times == 0) + return resResult(STATUS.ROLE_TERAPH_NOT_STRENGTHEN); + + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TERAPH_STRENGTHEN); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TERAPH, roleId, serverId, sid, { teraphs }, { teraphId: id }); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TERAPH_STRENGTHEN, { count }); + + return resResult(STATUS.SUCCESS, { roleId, teraphs: curRole.teraphs, criAttr }); + } + + //神像进阶 + async roleTeraphQualityUp(msg: { id: number }, session: BackendSession) { + let { id } = msg; + let roleId = session.get('roleId'); + let sid: string = session.get('sid'); + const serverId = session.get('serverId'); + + + let role = await RoleModel.findByRoleId(roleId); + let teraphs = role.teraphs; + let index = findIndex(teraphs, { id }); + if (index < 0) + return resResult(STATUS.WRONG_PARMS); + let teraph = teraphs[index]; + let teraphInfo = getTeraph(id, teraph.grade); + if (!teraphInfo) + return resResult(STATUS.DIC_DATA_NOT_FOUND) + + for (let [attrId, val] of teraph.attr) { + if (val < teraphInfo.mainAttrMax.get(attrId)) + return resResult(STATUS.ROLE_TERAPH_NOT_QUILITY); + + teraph.attr.set(attrId, 0); + } + teraph.grade++; + + + let nextTeraphInfo = getTeraph(id, teraph.grade) + if (!nextTeraphInfo) + return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let consumes = teraphInfo.upGradeMaterial; + let result = await handleCost(roleId, sid, consumes, ITEM_CHANGE_REASON.TERAPH_QUALITY_UP); + if (!result) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + let { curRole } = await calculateCeWithRole(HERO_SYSTEM_TYPE.TERAPH_UP, roleId, serverId, sid, { teraphs }, { teraphId: id }); + + // 神像进阶,进阶一次就触发一次礼包弹框 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_TERAPH_STAGE_UP); + + return resResult(STATUS.SUCCESS, { roleId, teraphs: curRole.teraphs }); + } + + // 获得百家学宫 + async getSchoolList(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let school = await getSchoolList(roleId); + + return resResult(STATUS.SUCCESS, { school }); + + } + + // 摆放/替换/卸下武将 + async changeSchoolHero(msg: { schoolId: number, positionId: number, hid: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + const serverId = session.get('serverId'); + + let { schoolId, positionId, hid } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + if (!gameData.school.has(schoolId)) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id(str) => isOpen + if (!dicPosition.has(positionId.toString())) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + let isOpen = !!dicPosition.get(positionId.toString()); // 该位置是否解锁 + let curHero: HeroType = null; + if (hid > 0) { + let findHero = await SchoolModel.findByHid(roleId, hid); + if (!!findHero) { + return resResult(STATUS.ROLE_SCHOOL_HERO_USED); + } + + curHero = await HeroModel.findByHidAndRole(hid, roleId); + if (!curHero) return resResult(STATUS.HERO_NOT_FIND); + } + + let curSchool = await SchoolModel.findBySclAndPos(roleId, schoolId, positionId); + let preHid = 0; // 原先在该位置上的武将 + if (curSchool) { + isOpen = curSchool.isOpen; + preHid = curSchool.hid; + } + + + if (!isOpen) { + return resResult(STATUS.ROLE_SCHOOL_POSITION_LOCKED); + } + + await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { hid, isOpen, star: curHero?.star??0, quality: curHero?.quality??0, colorStar: curHero?.colorStar??0 }); + await calculateCeWithRole(HERO_SYSTEM_TYPE.SCHOOL, roleId, serverId, sid, {}, { schoolId, hero: curHero, schoolHid: hid, preSchoolHid: preHid }); + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_SCHOOL_PUT_HERO, { hid, preHid }); + + return resResult(STATUS.SUCCESS, { + schoolId, positionId, hid, preHid, isOpen + }); + + } + + // 解锁位置 + async unlockSchoolPosition(msg: { schoolId: number, positionId: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + + let { schoolId, positionId } = msg; + if (!gameData.school.has(schoolId)) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id(str) => isOpen + if (!dicPosition.has(positionId.toString())) { + return resResult(STATUS.DIC_DATA_NOT_FOUND); + } + let isOpen = !!dicPosition.get(positionId.toString()); // 该位置是否解锁 + if (isOpen) { + return resResult(STATUS.ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED); + } + let curSchool = await SchoolModel.findBySclAndPos(roleId, schoolId, positionId); + if (curSchool && curSchool.isOpen) { + return resResult(STATUS.ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED); + } + + const cost = parseGoodStr(SCHOOL.SCHOOL_UNLOCK_COIN); + const costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.UNLOCK_SCHOOL_POSITION); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + curSchool = await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { isOpen: true }) + + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.ROLE_SCHOOL_UNLOCK); + + return resResult(STATUS.SUCCESS, { + schoolId, positionId, hid: curSchool.hid, isOpen: curSchool.isOpen + }); + } + + // 激活/升级名将谱 + async activeHeroScroll(msg: { hid: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + let serverId: number = session.get('serverId'); + + let { hid } = msg; + + if(isHeroHidden(hid)) return resResult(STATUS.HERO_IS_HIDDEN); + + let dicHero = gameData.hero.get(hid); + if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let hero = await HeroModel.findByHidAndRole(hid, roleId, 'hid lv star colorStar quality scrollId scrollActive scrollStar scrollColorStar scrollQuality connections attr ce'); + if (!hero) return resResult(STATUS.HERO_NOT_FIND); + + let { star, colorStar, quality, scrollId, scrollActive, scrollStar, scrollColorStar, scrollQuality } = hero; + + let update = { + scrollActive, scrollId, scrollStar, scrollColorStar, scrollQuality + }; + if (!scrollActive) { // 初次激活 + update.scrollActive = true; + update.scrollStar = dicHero.initialStar; + update.scrollQuality = dicHero.quality; + update.scrollColorStar = dicHero.initialColorStar; + } else { + if (star > scrollStar) { // 可以升星 + update.scrollStar++; + } else if (quality > scrollQuality && (quality != 4 || scrollQuality != 3)) { // 可以升品 + update.scrollQuality++; + } else if (colorStar > scrollColorStar) { // 可以升彩星 + update.scrollColorStar++; + update.scrollQuality = 4; + } else { + return resResult(STATUS.ROLE_SCROLL_REACH_MAX); + } + + } + + let dicHeroScroll = getScollByStar(dicHero.quality, update.scrollStar, update.scrollQuality, update.scrollColorStar); + update.scrollId = dicHeroScroll ? dicHeroScroll.id : 0; + + let { curHero } = await calculateCeWithHero(HERO_SYSTEM_TYPE.SCROLL, roleId, serverId, sid, hid, update); + + // 任务 + await checkTaskInActiveScroll(serverId, roleId, sid, scrollActive, hero); + + return resResult(STATUS.SUCCESS, { + curHero: pick(curHero, ['hid', 'scrollActive', 'scrollId', 'scrollStar', 'scrollColorStar', 'scrollQuality']) + }); + } + + // 保存展示阵容 + async saveShowLineup(msg: { showLineup: number[] }, session: BackendSession) { + let { showLineup } = msg; + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + + if(isHeroHidden(...showLineup)) return resResult(STATUS.HERO_IS_HIDDEN); + + let checkHeroes = await checkBattleHeroesByHid(roleId, showLineup); + if (showLineup.length > 0 && !checkHeroes) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); + + if (showLineup.length > LINEUP_NUM) { + return resResult(STATUS.LINEUP_MAX); + } + + let role = await RoleModel.updateRoleInfo(roleId, { showLineup }); + let r = new Rank(REDIS_KEY.SHOW_LINEUP, {}); + await r.generParamAndSet(REDIS_KEY.SHOW_LINEUP, { roleId }, { role }); + + return resResult(STATUS.SUCCESS, { showLineup: role.showLineup }); + } + + // 更换头像 + async setHead(msg: { id: number }, session: BackendSession) { + let { id } = msg; + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + + if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); + + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + if (!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let { heads } = role; + let curHead = heads.find(cur => cur.id == id); + if (!curHead) return resResult(STATUS.HEAD_NOT_FOUND); + if (curHead.enable) return resResult(STATUS.HEAD_IS_WEARING); + if (!curHead.status) return resResult(STATUS.HEAD_IS_LOCKED); + + let oldHead = heads.find(cur => cur.enable); // 穿戴中的头像 + if (oldHead) { + oldHead.enable = false; + } + curHead.enable = true; + + role = await RoleModel.updateRoleInfo(roleId, { heads }); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'head', value: id }]); + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + } + + return resResult(STATUS.SUCCESS, { heads: role.heads, head: role.head }); + } + + // 更换相框 + async setFrame(msg: { id: number }, session: BackendSession) { + let { id } = msg; + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + + if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); + + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + if (!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let { frames } = role; + let curFrame = frames.find(cur => cur.id == id); + if (!curFrame) return resResult(STATUS.FRAME_NOT_FOUND); + if (curFrame.enable) return resResult(STATUS.FRAME_IS_WEARING); + if (!curFrame.status) return resResult(STATUS.FRAME_IS_LOCKED); + + let oldHead = frames.find(cur => cur.enable); // 穿戴中的头像 + if (oldHead) { + oldHead.enable = false; + } + curFrame.enable = true; + + role = await RoleModel.updateRoleInfo(roleId, { frames }); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'frame', value: id }]); + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + } + + return resResult(STATUS.SUCCESS, { frames: role.frames, frame: role.frame }); + } + + // 更换形象 + async setSpine(msg: { id: number }, session: BackendSession) { + let { id } = msg; + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + + if(isGoodsHidden(id)) return resResult(STATUS.ITEM_IS_HIDDEN); + + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + if (!role) return resResult(STATUS.ROLE_NOT_FOUND); + + let { spines } = role; + let curSpine = spines.find(cur => cur.id == id); + if (!curSpine) return resResult(STATUS.SPINE_NOT_FOUND); + if (curSpine.enable) return resResult(STATUS.SPINE_IS_WEARING); + if (!curSpine.status) return resResult(STATUS.SPINE_IS_LOCKED); + + let oldHead = spines.find(cur => cur.enable); // 穿戴中的头像 + if (oldHead) { + oldHead.enable = false; + } + curSpine.enable = true; + + role = await RoleModel.updateRoleInfo(roleId, { spines }); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'spine', value: id }]); + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + } + + return resResult(STATUS.SUCCESS, { spines: role.spines, spine: role.spine }); + } + + // 改名 + async rename(msg: { roleName: string }, session: BackendSession) { + let { roleName } = msg; + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let guildCode = session.get('guildCode'); + let sid = session.get('sid'); + if(!roleName) return resResult(STATUS.WRONG_PARMS); + + let checkName = await RoleModel.checkName(roleName, serverId); + if (checkName) return resResult(STATUS.NAME_HAS_USED); + + let role = await RoleModel.findByRoleId(roleId, 'renameCnt'); + let costGold = role.renameCnt >= dicParam.NAMEPLATE.NAMEPLATE_FREECOST? dicParam.NAMEPLATE.NAMEPLATE_FEECOST: 0; + if(costGold > 0) { + let result = await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.RENAME); + if(!result) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH); + } + + role = await RoleModel.incRoleInfo(roleId, { renameCnt: 1 }, { roleName }); + session.set('roleName', role.roleName); + session.push('roleName', () => { }); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'roleName', value: roleName }]); + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(myLeague && getMyAuth(myLeague, roleId) == LEAGUE_AUTH.LEADER) { + await updateUserInfo(REDIS_KEY.LEAGUE_INFO, myLeague.leagueCode, [{ field: 'leader', value: new LeagueLeader(role) }]); + } + + } + await updateGVGBattleRoleInfo(serverId, roleId, { roleName }); + + return resResult(STATUS.SUCCESS, { roleName: role.roleName, renameCnt: role.renameCnt }); + } + + async saveGuide(msg: { ids: number[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let { ids } = msg; + if(ids == undefined || ids.length <= 0) { + return resResult(STATUS.WRONG_PARMS); + } + let role = await RoleModel.saveGuide(roleId, ids); + return resResult(STATUS.SUCCESS, { + guide: role.guide + }); + } + + async setPushMsgTrigger(msg: { isClosePush: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + const { isClosePush } = msg; + + let role = await RoleModel.setPushMsgOpen(roleId, isClosePush); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + return resResult(STATUS.SUCCESS, { + isClosePush: role.isClosePush + }) + } + + async setHasComment(msg: { hasComment: boolean }, session: BackendSession) { + const roleId = session.get('roleId'); + const { hasComment } = msg; + + let role = await RoleModel.setHasComment(roleId, hasComment); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + return resResult(STATUS.SUCCESS, { + hasComment: role.hasComment + }) + } + + // 防沉迷调试用,推送窗口 + async debugPlayerTime(msg: { type: number }, session: BackendSession) { + let { type } = msg; + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + if (type == 1) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest: true, + guestTime: 60 * 60, // 游客已体验时间 + hasAuthenticated: false, // 是否进行过实名认证 + isAdult: false, // 是否已成年 + todayPlayTime: 60 * 60, // 今天已游戏时长 + type: 1 + }, sid); + } else if (type == 2) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest: false, + guestTime: 0, // 游客已体验时间 + hasAuthenticated: true, // 是否进行过实名认证 + isAdult: false, // 是否已成年 + todayPlayTime: 60 * 60, // 今天已游戏时长 + type: 2 + }, sid); + } else if (type == 3) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest: false, + guestTime: 0, // 游客已体验时间 + hasAuthenticated: true, // 是否进行过实名认证 + isAdult: false, // 是否已成年 + todayPlayTime: 3 * 60 * 60, // 今天已游戏时长 + type: 3 + }, sid); + } else if (type == 4) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest: false, + guestTime: 0, // 游客已体验时间 + hasAuthenticated: true, // 是否进行过实名认证 + isAdult: false, // 是否已成年 + todayPlayTime: 1.5 * 60 * 60, // 今天已游戏时长 + type: 4 + }, sid); + } + + return resResult(STATUS.SUCCESS); + } + + // debug接口,清空某个角色 + async debugClearRole(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let roleId = session.get('roleId'); + let role = await RoleModel.findByRoleId(roleId); + if(!role) return resResult(STATUS.ROLE_NOT_FOUND); + if(role.hasInit) { + await deletRole(roleId); + } + + return resResult(STATUS.SUCCESS, { roleId: role?.roleId }); + } + + async debugRoleLvUp(msg: { magicWord: string, lv: number }, session: BackendSession) { + const { magicWord, lv } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + let roleId = session.get('roleId'); + let roleLvInfo = gameData.kingexp.get(lv - 1); + let role = await RoleModel.updateRoleInfo(roleId, { lv, exp: roleLvInfo.sum }); + + return resResult(STATUS.SUCCESS, { lv: role.lv }); + } + + public async debugSetRole(msg: { magicWord: string, params: RoleUpdate }, session: BackendSession) { + let roleId: string = session.get('roleId'); + + let { magicWord, params } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let role = await RoleModel.updateRoleInfo(roleId, params); + + return resResult(STATUS.SUCCESS, { role }); + + } + + public async test(msg: { magicWord: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + let serverId: string = session.get('serverId'); + + let { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + let role = await RoleModel.findByRoleId(roleId); + let user = await UserModel.findUserByUid(role.userInfo.uid); + + reportTAEvent(roleId, 'test', { serverId }, user.ip); + + return resResult(STATUS.SUCCESS); + + } + + async debugTreatRoleName(msg: { magicWord: string }, session: BackendSession) { + let roleId: string = session.get('roleId'); + + let { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + + await treatRoleName(roleId, true); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/role/handler/shopHandler.ts b/game-server/app/servers/role/handler/shopHandler.ts index 5369d7ea0..edb281228 100644 --- a/game-server/app/servers/role/handler/shopHandler.ts +++ b/game-server/app/servers/role/handler/shopHandler.ts @@ -1,254 +1,255 @@ -import { Application, BackendSession, pinus } from "pinus"; -import { gameData, hasShopType } from "../../../pubUtils/data"; -import { arrToMap, parseGoodStr, resResult } from "../../../pubUtils/util"; -import { STATUS, GUILD_STRUCTURE, ITID, CONSUME_TYPE, HERO_QUALITY_TYPE, HERO_GROW_MAX, ITEM_CHANGE_REASON } from "../../../consts"; -import { UserShopModel } from "../../../db/UserShop"; -import { handleCost, addItems } from "../../../services/role/rewardService"; -import { SHOP } from "../../../pubUtils/dicParam"; -import { HeroModel, HeroType } from "../../../db/Hero"; -import { checkShopInPurchase, getShopDicById, getShopListByType, getShopPrice } from "../../../services/shopService"; -import { RewardInter, recycleSoulFastPara } from "../../../pubUtils/interface"; -import { UserShopTypeModel } from "../../../db/UserShopType"; -import { nowSeconds } from "../../../pubUtils/timeUtil"; -import { isGoodsHidden, isHeroHidden } from "../../../services/dataService"; -import { RoleModel } from './../../../db/Role'; -import { calUpSixColorsResidueFragment } from "../../../services/role/checkMaterial"; -import { ItemModel } from "../../../db/Item"; - -export default function (app: Application) { - return new ShopHandler(app); -} - -export class ShopHandler { - constructor(private app: Application) { - } - - // 获得商品列表 - async getShopList(msg: { shop: number, type: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let { shop, type } = msg; - - if (!hasShopType(shop, type)) { - return resResult(STATUS.WRONG_PARMS); - } - - const result = await getShopListByType(shop, type, roleId, serverId); - return resResult(STATUS.SUCCESS, result); - } - - // 读取红点 - async readShop(msg: { shop: number, type: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let { shop, type } = msg; - - if (!hasShopType(shop, type)) { - return resResult(STATUS.WRONG_PARMS); - } - - await UserShopTypeModel.read(roleId, shop, type); - return resResult(STATUS.SUCCESS); - } - - // 购买商品 - async purchase(msg: { activityId: number, shopItemId: number, count: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let serverId = session.get('serverId'); - let seasonNum = pinus.app.get('pvpSeasonNum'); - - let { activityId = 0, shopItemId, count } = msg; - - let dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); - if (!dicShopItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicShopItem['productID'] && dicShopItem['productID'] != '&') return resResult(STATUS.CAN_NOT_PURCHASE); - if (dicShopItem['beginTime'] && dicShopItem['beginTime'] > nowSeconds()) return resResult(STATUS.SHOP_CLOSED); - if (dicShopItem['endTime'] && dicShopItem['endTime'] < nowSeconds()) return resResult(STATUS.SHOP_CLOSED); - - let userShop = await UserShopModel.findByRoleAndItem(roleId, dicShopItem, seasonNum); - - let checkResult = await checkShopInPurchase(session, activityId, count, userShop?.count || 0, dicShopItem); - if (checkResult.code != STATUS.SUCCESS.code) { - return resResult(checkResult); - } - - // 总计可买次数(从配置表读取) - const totalCanBuyTimes = dicShopItem.purchaseLimit; - if (!totalCanBuyTimes || totalCanBuyTimes <= 0) { - return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - } - - // 消耗 - let cost = getShopPrice(dicShopItem.money, count, userShop?.count || 0, dicShopItem.price); - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE); - if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - // 次数 - userShop = await UserShopModel.purchase(roleId, roleName, activityId, dicShopItem, count, seasonNum); - if (!userShop || (userShop && userShop.count > totalCanBuyTimes)) { - // rollback 消耗 - let role = await RoleModel.findByRoleId(roleId); - addItems(roleId, role.roleName, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE); - - // rollback 购买次数 - await UserShopModel.updateCount(roleId, dicShopItem, -count, seasonNum) - return resResult(STATUS.BUY_COUNT_OVER); - } - - // 获得 - let reward = [{ - id: dicShopItem.goodId, - count: count * (dicShopItem.num || 1) - }]; - let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE); - - return resResult(STATUS.SUCCESS, { - shopItemId, count, - goods - }); - - } - - // 将魂回收 - async recycleSoul(msg: { goodsId: number, count: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let { goodsId, count } = msg; - - if (isGoodsHidden(goodsId)) return resResult(STATUS.ITEM_IS_HIDDEN); - let dicGoods = gameData.goods.get(goodsId); - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); - if (dicItid.type != CONSUME_TYPE.SOUL) { - return resResult(STATUS.ITEM_NOT_SOUL); - } - - let hero = await HeroModel.findByHidAndRole(dicGoods.hid, roleId); - if (!hero) return resResult(STATUS.HERO_NOT_MAX); - if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) { - let residueFragment = await calUpSixColorsResidueFragment(roleId, hero, dicGoods.hid); - if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - // return resResult(STATUS.HERO_NOT_MAX); - } - - // 检查自己的数量 - let cost = [{ - id: goodsId, count - }]; - let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.RECYCLE_SOUL); - if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - - let reward: RewardInter[] = []; - switch (dicGoods.quality) { - case HERO_QUALITY_TYPE.BLUE: - reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break; - case HERO_QUALITY_TYPE.PURPLE: - reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break; - case HERO_QUALITY_TYPE.GOLD: - reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break; - case HERO_QUALITY_TYPE.UR: - reward = parseGoodStr(SHOP.HERO_SOUL_UR); break; - } - // 增加货币 - let goods = await addItems(roleId, roleName, sid, reward.map(cur => { return { id: cur.id, count: cur.count * count } }), ITEM_CHANGE_REASON.RECYCLE_SOUL); - - return resResult(STATUS.SUCCESS, { - goodsId, count, - goods - }); - } - - - /** - * 将魂一键回收 - * @param msg - * @param session - * @returns - */ - async recycleSoulFast(msg: { recycleSoulFastPara: recycleSoulFastPara[] }, session: BackendSession) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - - let { recycleSoulFastPara } = msg; - // 检测参数,防止hid重复 - let checkHid = new Map(); - for (let { hid, count } of recycleSoulFastPara) { - if (checkHid.get(hid)) return resResult(STATUS.WRONG_PARMS); - checkHid.set(hid, 1); - } - - // 从db获取所有武将数据 - const dbHeros = await HeroModel.findByHidsAndRole(roleId, recycleSoulFastPara.map(obj => obj.hid)) as HeroType[]; - let heroesMap = new Map(); - let items = [] - for (const val of dbHeros) { - let hid = val.hid - heroesMap.set(hid, val); - - let dicHero = gameData.hero.get(hid); - if (!dicHero || !dicHero.pieceId) continue; - items.push(dicHero.pieceId); - } - // 从db获取相关碎片道具数据 - if (!items || items.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - const dbItems = await ItemModel.findbyRoleAndIds(roleId, items); - if (!dbItems || dbItems.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - const itemsMap = arrToMap(dbItems, obj => obj.id); - - let allAddItem = []; - let allCostItem = []; - for (let { hid, count } of recycleSoulFastPara) { - let residueFragment = 0; - let goodsId = gameData.hero.get(hid)?.pieceId || 0; - const curItemCount = itemsMap.get(goodsId)?.count || 0; - if (curItemCount <= 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - - let hero = heroesMap.get(hid); - if (!hero) return resResult(STATUS.HERO_IS_HIDDEN); - - if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) { - residueFragment = await calUpSixColorsResidueFragment(roleId, hero, hid, curItemCount); - if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); - } - - allCostItem.push({ id: goodsId, count: count }); - - let dicGoods = gameData.goods.get(goodsId); - if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND) - - let reward: RewardInter[] = []; - switch (dicGoods.quality) { - case HERO_QUALITY_TYPE.BLUE: - reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break; - case HERO_QUALITY_TYPE.PURPLE: - reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break; - case HERO_QUALITY_TYPE.GOLD: - reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break; - case HERO_QUALITY_TYPE.UR: - reward = parseGoodStr(SHOP.HERO_SOUL_UR); break; - } - allAddItem.push(...reward.map(cur => { return { id: cur.id, count: cur.count * count } })); - } - - let costResult = await handleCost(roleId, sid, allCostItem, ITEM_CHANGE_REASON.RECYCLE_SOUL); - if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); - // 增加货币 - let goods = await addItems(roleId, roleName, sid, allAddItem, ITEM_CHANGE_REASON.RECYCLE_SOUL); - - return resResult(STATUS.SUCCESS, { goods }); - } - - - - // !测试接口。 去除限购次数 - async debugClearPurchaseLimit(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - - await UserShopModel.deleteAccount(roleId); - return resResult(STATUS.SUCCESS); - } -} \ No newline at end of file +import { Application, BackendSession, pinus } from "pinus"; +import { gameData, hasShopType } from "@pubUtils/data"; +import { arrToMap, parseGoodStr, resResult } from "@pubUtils/util"; +import { STATUS, GUILD_STRUCTURE, ITID, CONSUME_TYPE, HERO_QUALITY_TYPE, HERO_GROW_MAX, ITEM_CHANGE_REASON } from "../../../consts"; +import { UserShopModel } from "@db/UserShop"; +import { handleCost, addItems } from "../../../services/role/rewardService"; +import { SHOP } from "@pubUtils/dicParam"; +import { HeroModel, HeroType } from "@db/Hero"; +import { checkShopInPurchase, getShopDicById, getShopListByType, getShopPrice } from "../../../services/shopService"; +import { RewardInter, recycleSoulFastPara } from "@pubUtils/interface"; +import { UserShopTypeModel } from "@db/UserShopType"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { isGoodsHidden, isHeroHidden } from "../../../services/dataService"; +import { RoleModel } from './../../../db/Role'; +import { calUpSixColorsResidueFragment } from "../../../services/role/checkMaterial"; +import { ItemModel } from "@db/Item"; + +export default function (app: Application) { + return new ShopHandler(app); +} + +export class ShopHandler { + constructor(private app: Application) { + } + + // 获得商品列表 + async getShopList(msg: { shop: number, type: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let { shop, type } = msg; + + if (!hasShopType(shop, type)) { + return resResult(STATUS.WRONG_PARMS); + } + + const result = await getShopListByType(shop, type, roleId, serverId); + return resResult(STATUS.SUCCESS, result); + } + + // 读取红点 + async readShop(msg: { shop: number, type: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let { shop, type } = msg; + + if (!hasShopType(shop, type)) { + return resResult(STATUS.WRONG_PARMS); + } + + await UserShopTypeModel.read(roleId, shop, type); + return resResult(STATUS.SUCCESS); + } + + // 购买商品 + async purchase(msg: { activityId: number, shopItemId: number, count: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let serverId = session.get('serverId'); + let seasonNum = pinus.app.get('pvpSeasonNum'); + + let { activityId = 0, shopItemId, count } = msg; + + let dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); + if (!dicShopItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicShopItem['productID'] && dicShopItem['productID'] != '&') return resResult(STATUS.CAN_NOT_PURCHASE); + if (dicShopItem['beginTime'] && dicShopItem['beginTime'] > nowSeconds()) return resResult(STATUS.SHOP_CLOSED); + if (dicShopItem['endTime'] && dicShopItem['endTime'] < nowSeconds()) return resResult(STATUS.SHOP_CLOSED); + + let userShop = await UserShopModel.findByRoleAndItem(roleId, dicShopItem, seasonNum); + + let checkResult = await checkShopInPurchase(session, activityId, count, userShop?.count || 0, dicShopItem); + if (checkResult.code != STATUS.SUCCESS.code) { + return resResult(checkResult); + } + + // 总计可买次数(从配置表读取) + const totalCanBuyTimes = dicShopItem.purchaseLimit; + if (!totalCanBuyTimes || totalCanBuyTimes <= 0) { + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + } + + // 消耗 + let cost = getShopPrice(dicShopItem.money, count, userShop?.count || 0, dicShopItem.price); + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE); + if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + // 次数 + userShop = await UserShopModel.purchase(roleId, roleName, activityId, dicShopItem, count, seasonNum); + if (!userShop || (userShop && userShop.count > totalCanBuyTimes)) { + // rollback 消耗 + let role = await RoleModel.findByRoleId(roleId); + addItems(roleId, role.roleName, sid, cost, ITEM_CHANGE_REASON.SHOP_PURCHASE); + + // rollback 购买次数 + await UserShopModel.updateCount(roleId, dicShopItem, -count, seasonNum) + return resResult(STATUS.BUY_COUNT_OVER); + } + + // 获得 + let reward = [{ + id: dicShopItem.goodId, + count: count * (dicShopItem.num || 1) + }]; + let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE); + + return resResult(STATUS.SUCCESS, { + shopItemId, count, + goods + }); + + } + + // 将魂回收 + async recycleSoul(msg: { goodsId: number, count: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let { goodsId, count } = msg; + + if (isGoodsHidden(goodsId)) return resResult(STATUS.ITEM_IS_HIDDEN); + let dicGoods = gameData.goods.get(goodsId); + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND); + if (dicItid.type != CONSUME_TYPE.SOUL) { + return resResult(STATUS.ITEM_NOT_SOUL); + } + + let hero = await HeroModel.findByHidAndRole(dicGoods.hid, roleId); + if (!hero) return resResult(STATUS.HERO_NOT_MAX); + if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) { + let residueFragment = await calUpSixColorsResidueFragment(roleId, hero, dicGoods.hid); + if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + // return resResult(STATUS.HERO_NOT_MAX); + } + + // 检查自己的数量 + let cost = [{ + id: goodsId, count + }]; + let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.RECYCLE_SOUL); + if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + + let reward: RewardInter[] = []; + switch (dicGoods.quality) { + case HERO_QUALITY_TYPE.BLUE: + reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break; + case HERO_QUALITY_TYPE.PURPLE: + reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break; + case HERO_QUALITY_TYPE.GOLD: + reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break; + case HERO_QUALITY_TYPE.UR: + reward = parseGoodStr(SHOP.HERO_SOUL_UR); break; + } + // 增加货币 + let goods = await addItems(roleId, roleName, sid, reward.map(cur => { return { id: cur.id, count: cur.count * count } }), ITEM_CHANGE_REASON.RECYCLE_SOUL); + + return resResult(STATUS.SUCCESS, { + goodsId, count, + goods + }); + } + + + /** + * 将魂一键回收 + * @param msg + * @param session + * @returns + */ + async recycleSoulFast(msg: { recycleSoulFastPara: recycleSoulFastPara[] }, session: BackendSession) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + + let { recycleSoulFastPara } = msg; + // 检测参数,防止hid重复 + let checkHid = new Map(); + for (let { hid, count } of recycleSoulFastPara) { + if (checkHid.get(hid)) return resResult(STATUS.WRONG_PARMS); + checkHid.set(hid, 1); + } + + // 从db获取所有武将数据 + const dbHeros = await HeroModel.findByHidsAndRole(roleId, recycleSoulFastPara.map(obj => obj.hid)) as HeroType[]; + let heroesMap = new Map(); + let items = [] + for (const val of dbHeros) { + let hid = val.hid + heroesMap.set(hid, val); + + let dicHero = gameData.hero.get(hid); + if (!dicHero || !dicHero.pieceId) continue; + items.push(dicHero.pieceId); + } + // 从db获取相关碎片道具数据 + if (!items || items.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + const dbItems = await ItemModel.findbyRoleAndIds(roleId, items); + if (!dbItems || dbItems.length == 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + const itemsMap = arrToMap(dbItems, obj => obj.id); + + let allAddItem = []; + let allCostItem = []; + for (let { hid, count } of recycleSoulFastPara) { + let residueFragment = 0; + let goodsId = gameData.hero.get(hid)?.pieceId || 0; + const curItemCount = itemsMap.get(goodsId)?.count || 0; + if (curItemCount <= 0) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let hero = heroesMap.get(hid); + if (!hero) return resResult(STATUS.HERO_IS_HIDDEN); + + if (hero.colorStar != HERO_GROW_MAX.COLORSTAR) { + residueFragment = await calUpSixColorsResidueFragment(roleId, hero, hid, curItemCount); + if (!residueFragment || count > residueFragment) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + allCostItem.push({ id: goodsId, count: count }); + + let dicGoods = gameData.goods.get(goodsId); + if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND) + + let reward: RewardInter[] = []; + switch (dicGoods.quality) { + case HERO_QUALITY_TYPE.BLUE: + reward = parseGoodStr(SHOP.HERO_SOUL_BULE); break; + case HERO_QUALITY_TYPE.PURPLE: + reward = parseGoodStr(SHOP.HERO_SOUL_PURPLE); break; + case HERO_QUALITY_TYPE.GOLD: + reward = parseGoodStr(SHOP.HERO_SOUL_GOLDEN); break; + case HERO_QUALITY_TYPE.UR: + reward = parseGoodStr(SHOP.HERO_SOUL_UR); break; + } + allAddItem.push(...reward.map(cur => { return { id: cur.id, count: cur.count * count } })); + } + + let costResult = await handleCost(roleId, sid, allCostItem, ITEM_CHANGE_REASON.RECYCLE_SOUL); + if (!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + // 增加货币 + let goods = await addItems(roleId, roleName, sid, allAddItem, ITEM_CHANGE_REASON.RECYCLE_SOUL); + + return resResult(STATUS.SUCCESS, { goods }); + } + + + + // !测试接口。 去除限购次数 + async debugClearPurchaseLimit(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + + await UserShopModel.deleteAccount(roleId); + return resResult(STATUS.SUCCESS); + } +} + diff --git a/game-server/app/servers/role/handler/taskHandler.ts b/game-server/app/servers/role/handler/taskHandler.ts index 8bda94815..73d644e8a 100644 --- a/game-server/app/servers/role/handler/taskHandler.ts +++ b/game-server/app/servers/role/handler/taskHandler.ts @@ -1,340 +1,341 @@ -import { Application, BackendSession, pinus, HandlerService, } from "pinus"; -import { resResult, parseGoodStr, getRandSingleEelm } from "../../../pubUtils/util"; -import { STATUS, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, KING_EXP_RATIO_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, ACTIVITY_TYPE, TASK_TYPE, PUSH_ROUTE } from "../../../consts"; -import { gameData } from "../../../pubUtils/data"; -import { UserTaskRecModel } from "../../../db/UserTaskRec"; -import { addItems } from "../../../services/role/rewardService"; -import { UserTaskModel } from "../../../db/UserTask"; -import { nowSeconds, getZeroPointD } from "../../../pubUtils/timeUtil"; -import { DicDailyTask, DicAchievement, DicMainTask } from "../../../pubUtils/dictionary/DicTask"; -import { getMainTask, refDailyTaskBox, removeHistoryTask, getCurTask, checkTask, getPvpTask } from "../../../services/task/taskService"; -import { TASK } from "../../../pubUtils/dicParam"; -import { ActivityTaskPointModel, ActivityTaskPointModelType } from "../../../db/ActivityTaskPoint"; -import { ItemInter, RewardInter } from "../../../pubUtils/interface"; -import { RoleModel } from "../../../db/Role"; -import { roleLevelup } from "../../../services/normalBattleService"; -import _ = require("underscore"); -import { addActvityTaskPoint } from "../../../services/activity/activityService"; -import { CheckTask } from "../../../services/task/taskObj"; -import { ServerlistModel } from "../../../db/Serverlist"; -import { sendMessageToUserWithSuc } from "../../../services/pushService"; - -export default function (app: Application) { - new HandlerService(app, {}); - return new ShopHandler(app); -} - -export class ShopHandler { - constructor(private app: Application) { - } - - public async getTaskList(msg: {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - - const res = await getCurTask(roleId, session); - return resResult(STATUS.SUCCESS, res); - } - - public async getPvpTaskList(msg: {}, session: BackendSession) { - const roleId: string = session.get('roleId'); - - const res = await getPvpTask(roleId); - return resResult(STATUS.SUCCESS, res); - } - - // 领取主线任务、每日任务、成就单条任务 - async receiveTask(msg: { type: number, id: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const serverId: number = session.get('serverId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { type, id } = msg; - - let dicTask = gameData.tasks.get(type).get(id); - let { group, taskType, taskReward, condition } = dicTask; - // 检查 - let rec = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); - if (!rec) return resResult(STATUS.TASK_NOT_REACH_CONDITION); - if (rec.count < condition) return resResult(STATUS.TASK_NOT_REACH_CONDITION); - if (rec.received.includes(id)) return resResult(STATUS.TASK_HAS_RECEIVED); - - // 领取记录 - rec = await UserTaskRecModel.receiveTask(roleId, type, taskType, group, id); - - // 每日、成就增加积分 - let point = 0, weeklyPoint = 0, expItem: RewardInter; - if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 - let userTask = await UserTaskModel.findByRole(roleId); - let dic = dicTask; - let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); - if (curWeek > userTask.dailyTaskRefWeekly) { - userTask = await UserTaskModel.resetDailyScore(roleId, dic.point, curWeek); - } else { - userTask = await UserTaskModel.incInfo(roleId, { dailyTaskPoint: dic.point, dailyTaskPointWeekly: dic.point }); - } - point = userTask.dailyTaskPoint; - weeklyPoint = userTask.dailyTaskPointWeekly; - expItem = { id: dic.exp.id, count: dic.exp.count }; - //任务完成后关联活动的积分 - await addActvityTaskPoint(type, dic.point, session ); - - } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { - let dic = dicTask; - let userTask = await UserTaskModel.incInfo(roleId, { achievementPoint: dic.point }); - point = userTask.achievementPoint; - } - - - let goods = await addItems(roleId, roleName, sid, taskReward, ITEM_CHANGE_REASON.TASK_REWARD); - if (expItem && expItem.count > 0) { - await roleLevelup(KING_EXP_RATIO_TYPE.TASK, roleId, expItem.count, session); - goods.push(expItem); - } - - return resResult(STATUS.SUCCESS, { - type, id, count: rec.count, received: rec.received.includes(id), - point, weeklyPoint, - goods - }); - } - - // 领取主线阶段奖励 - async receiveMainStage(msg: { stage: number }, session: BackendSession) { - - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { stage } = msg; - - let dicMainStage = gameData.mainTaskStage.get(stage); - if (!dicMainStage) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - // 检查 - let userTask = await UserTaskModel.findByRole(roleId); - if (userTask.mainTaskStage != stage) { - return resResult(STATUS.WRONG_PARMS); - } - let recs = await UserTaskRecModel.getReceiveRec(roleId, TASK_FUN_TYPE.MAIN); - for (let id of dicMainStage.mainTaskId) { - let curRecs = recs.find(cur => cur.received.includes(id)); - if (!curRecs) return resResult(STATUS.TASK_NOT_ALL_RECEIVED); - } - // 更新数据 - userTask = await UserTaskModel.incInfo(roleId, { mainTaskStage: 1 }); - - let goods = await addItems(roleId, roleName, sid, dicMainStage.reward, ITEM_CHANGE_REASON.TASK_STAGE_REWARD); - let mainTask = await getMainTask(roleId, userTask); - - return resResult(STATUS.SUCCESS, { - type: TASK_FUN_TYPE.MAIN, - ...mainTask, - goods - }); - } - - // 领取每日活跃奖励 - async receiveActiveReward(msg: {}, session: BackendSession) { - - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - - // 检查 - let userTask = await UserTaskModel.findByRole(roleId); - let { dailyTaskPoint } = userTask; - if (dailyTaskPoint < TASK.DAILYTASK_POINT) { - return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); - } - // 更新数据 - userTask = await UserTaskModel.decreaseDailyPoint(roleId, TASK.DAILYTASK_POINT); - if (!userTask) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); - - let reward = parseGoodStr(TASK.DAILYTASK_POINT_REWARD); - let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.TASK_ACTIVE_REWARD); - - return resResult(STATUS.SUCCESS, { - type: TASK_FUN_TYPE.DAILY, - point: userTask.dailyTaskPoint, - goods - }); - } - - // 领取每日周宝箱 - async receiveBox(msg: { type: number, id: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const roleName: string = session.get('roleName'); - const sid: string = session.get('sid'); - const { type, id } = msg; - - let userTask = await UserTaskModel.findByRole(roleId); - let dicTaskBox = gameData.taskBox.get(type)?.get(id); - if (!dicTaskBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let point = 0, weeklyPoint = 0, box: number[] = []; - // 每日、成就增加积分 - if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 - let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); - let shouldRefresh = false; - let { dailyTaskPointWeekly, dailyTaskBox, dailyTaskRefWeekly } = userTask; - - if (curWeek > dailyTaskRefWeekly) { - shouldRefresh = true; - dailyTaskPointWeekly = 0; - dailyTaskBox = []; - } - if (dailyTaskPointWeekly < dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); - if (dailyTaskBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); - - userTask = await UserTaskModel.pushDailyBox(roleId, id, curWeek, shouldRefresh); - - point = userTask.dailyTaskPoint; - box = userTask.dailyTaskBox; - weeklyPoint = userTask.dailyTaskPointWeekly; - - } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { - let { achievementPoint, achievementBox } = userTask; - if (achievementPoint < dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); - if (achievementBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); - - userTask = await UserTaskModel.pushAchievementBox(roleId, id); - - point = userTask.achievementPoint; - box = userTask.achievementBox; - } else { - return resResult(STATUS.WRONG_PARMS); - } - - let goods = await addItems(roleId, roleName, sid, dicTaskBox.reward, ITEM_CHANGE_REASON.TASK_BOX_REWARD); - - return resResult(STATUS.SUCCESS, { - type, - point, weeklyPoint, box, - goods - }); - } - - /** - * @description 随机完成某一个任务 - * @param {{ type: number }} msg - * @param {BackendSession} session - * @memberof TaskHandler - */ - async debugCompleteRandTask(msg: { type: number }, session: BackendSession) { - const roleId: string = session.get('roleId'); - const sid: string = session.get('sid'); - const serverId: number = session.get('serverId'); - - const { type } = msg - let tasks: (DicMainTask | DicDailyTask | DicAchievement)[] = []; - for (let [_id, task] of gameData.tasks.get(type)) { - tasks.push(task); - } - let task = getRandSingleEelm(tasks); - await checkTask(serverId, roleId, sid, task.taskType, { debugInfo: {condition: task.condition} }); - return resResult(STATUS.SUCCESS, { - task - }); - } - - async debugRefTask(msg: { type: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let { type } = msg - let userTask; - if (type == TASK_FUN_TYPE.DAILY) { - // 转移每日任务 - await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.DAILY_TASK_REFRESH, { taskList: [] }, sid); - await refDailyTaskBox(roleId, sid, true); - userTask = await UserTaskModel.updateInfo(roleId, { dailyTaskPoint: 0 }); - - } else if (type == TASK_FUN_TYPE.MAIN) { - await UserTaskModel.updateInfo(roleId, { mainTaskStage: 1 }); - userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); - } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { - await UserTaskModel.updateInfo(roleId, { achievementBox: [], achievementPoint: 0 }); - userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); - } else if (type == TASK_FUN_TYPE.PVP) { - userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); - } - - let curTask = await getCurTask(roleId, session);; - return resResult(STATUS.SUCCESS, curTask); - } - - async debugCompleteMainStage(msg: {}, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - - - // 检查 - let userTask = await UserTaskModel.findByRole(roleId); - let stage = userTask.mainTaskStage; - - let dicMainStage = gameData.mainTaskStage.get(stage); - if (!dicMainStage) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - let recs = await UserTaskRecModel.getReceiveRec(roleId, TASK_FUN_TYPE.MAIN); - for (let id of dicMainStage.mainTaskId) { - let dicTask = gameData.tasks.get(TASK_FUN_TYPE.MAIN)?.get(id); - if (!dicTask) continue; - let curRecs = recs.find(cur => cur.received.includes(id)); - if (!curRecs) { - await UserTaskRecModel.setTaskRec(roleId, TASK_FUN_TYPE.MAIN, dicTask.taskType, dicTask.group, dicTask.condition); - }; - } - let mainTask = await getMainTask(roleId, userTask); - for (let t of mainTask.taskList) { - let dicTask = gameData.tasks.get(TASK_FUN_TYPE.MAIN)?.get(t.id); - await UserTaskRecModel.setTaskRec(roleId, TASK_FUN_TYPE.MAIN, dicTask.taskType, dicTask.group, dicTask.condition); - } - return resResult(STATUS.SUCCESS, { mainTask }); - } - - async debugIncPoint(msg: { type: number, point: number }, session: BackendSession) { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - let { type, point: incPoint } = msg; - - - // 每日、成就增加积分 - let point = 0, weeklyPoint = 0; - if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 - let userTask = await UserTaskModel.findByRole(roleId); - let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); - if (curWeek > userTask.dailyTaskRefWeekly) { - userTask = await UserTaskModel.resetDailyScore(roleId, incPoint, curWeek); - } else { - userTask = await UserTaskModel.incInfo(roleId, { dailyTaskPoint: incPoint, dailyTaskPointWeekly: incPoint }); - } - point = userTask.dailyTaskPoint; - weeklyPoint = userTask.dailyTaskPointWeekly; - } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { - let userTask = await UserTaskModel.incInfo(roleId, { achievementPoint: incPoint }); - point = userTask.achievementPoint; - } - - return resResult(STATUS.SUCCESS, { - type, point, weeklyPoint - }); - } - - - async debugGetDicTask(msg: { magicWord: string }, session: BackendSession) { - const { magicWord } = msg; - if (magicWord !== DEBUG_MAGIC_WORD) { - return resResult(STATUS.TOKEN_ERR); - } - // console.log('******', _.isEqual([1,2], [1,2,2])) - return resResult(STATUS.SUCCESS, { tasks: [...gameData.taskType]}); - } - - async test(msg: { magicWord: string }, session: BackendSession) { - let roleId = session.get('roleId'); - let serverId = session.get('serverId'); - let sid = session.get('sid'); - let role = await RoleModel.findByRoleId(roleId); - let server = await ServerlistModel.findByServerId(serverId); - return resResult(STATUS.SUCCESS) - } -} \ No newline at end of file +import { Application, BackendSession, pinus, HandlerService, } from "pinus"; +import { resResult, parseGoodStr, getRandSingleEelm } from "@pubUtils/util"; +import { STATUS, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, KING_EXP_RATIO_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, ACTIVITY_TYPE, TASK_TYPE, PUSH_ROUTE } from "../../../consts"; +import { gameData } from "@pubUtils/data"; +import { UserTaskRecModel } from "@db/UserTaskRec"; +import { addItems } from "../../../services/role/rewardService"; +import { UserTaskModel } from "@db/UserTask"; +import { nowSeconds, getZeroPointD } from "@pubUtils/timeUtil"; +import { DicDailyTask, DicAchievement, DicMainTask } from "@pubUtils/dictionary/DicTask"; +import { getMainTask, refDailyTaskBox, removeHistoryTask, getCurTask, checkTask, getPvpTask } from "../../../services/task/taskService"; +import { TASK } from "@pubUtils/dicParam"; +import { ActivityTaskPointModel, ActivityTaskPointModelType } from "@db/ActivityTaskPoint"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; +import { RoleModel } from "@db/Role"; +import { roleLevelup } from "../../../services/normalBattleService"; +import _ = require("underscore"); +import { addActvityTaskPoint } from "../../../services/activity/activityService"; +import { CheckTask } from "../../../services/task/taskObj"; +import { ServerlistModel } from "@db/Serverlist"; +import { sendMessageToUserWithSuc } from "../../../services/pushService"; + +export default function (app: Application) { + new HandlerService(app, {}); + return new ShopHandler(app); +} + +export class ShopHandler { + constructor(private app: Application) { + } + + public async getTaskList(msg: {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + + const res = await getCurTask(roleId, session); + return resResult(STATUS.SUCCESS, res); + } + + public async getPvpTaskList(msg: {}, session: BackendSession) { + const roleId: string = session.get('roleId'); + + const res = await getPvpTask(roleId); + return resResult(STATUS.SUCCESS, res); + } + + // 领取主线任务、每日任务、成就单条任务 + async receiveTask(msg: { type: number, id: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const serverId: number = session.get('serverId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { type, id } = msg; + + let dicTask = gameData.tasks.get(type).get(id); + let { group, taskType, taskReward, condition } = dicTask; + // 检查 + let rec = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); + if (!rec) return resResult(STATUS.TASK_NOT_REACH_CONDITION); + if (rec.count < condition) return resResult(STATUS.TASK_NOT_REACH_CONDITION); + if (rec.received.includes(id)) return resResult(STATUS.TASK_HAS_RECEIVED); + + // 领取记录 + rec = await UserTaskRecModel.receiveTask(roleId, type, taskType, group, id); + + // 每日、成就增加积分 + let point = 0, weeklyPoint = 0, expItem: RewardInter; + if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 + let userTask = await UserTaskModel.findByRole(roleId); + let dic = dicTask; + let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); + if (curWeek > userTask.dailyTaskRefWeekly) { + userTask = await UserTaskModel.resetDailyScore(roleId, dic.point, curWeek); + } else { + userTask = await UserTaskModel.incInfo(roleId, { dailyTaskPoint: dic.point, dailyTaskPointWeekly: dic.point }); + } + point = userTask.dailyTaskPoint; + weeklyPoint = userTask.dailyTaskPointWeekly; + expItem = { id: dic.exp.id, count: dic.exp.count }; + //任务完成后关联活动的积分 + await addActvityTaskPoint(type, dic.point, session ); + + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + let dic = dicTask; + let userTask = await UserTaskModel.incInfo(roleId, { achievementPoint: dic.point }); + point = userTask.achievementPoint; + } + + + let goods = await addItems(roleId, roleName, sid, taskReward, ITEM_CHANGE_REASON.TASK_REWARD); + if (expItem && expItem.count > 0) { + await roleLevelup(KING_EXP_RATIO_TYPE.TASK, roleId, expItem.count, session); + goods.push(expItem); + } + + return resResult(STATUS.SUCCESS, { + type, id, count: rec.count, received: rec.received.includes(id), + point, weeklyPoint, + goods + }); + } + + // 领取主线阶段奖励 + async receiveMainStage(msg: { stage: number }, session: BackendSession) { + + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { stage } = msg; + + let dicMainStage = gameData.mainTaskStage.get(stage); + if (!dicMainStage) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + // 检查 + let userTask = await UserTaskModel.findByRole(roleId); + if (userTask.mainTaskStage != stage) { + return resResult(STATUS.WRONG_PARMS); + } + let recs = await UserTaskRecModel.getReceiveRec(roleId, TASK_FUN_TYPE.MAIN); + for (let id of dicMainStage.mainTaskId) { + let curRecs = recs.find(cur => cur.received.includes(id)); + if (!curRecs) return resResult(STATUS.TASK_NOT_ALL_RECEIVED); + } + // 更新数据 + userTask = await UserTaskModel.incInfo(roleId, { mainTaskStage: 1 }); + + let goods = await addItems(roleId, roleName, sid, dicMainStage.reward, ITEM_CHANGE_REASON.TASK_STAGE_REWARD); + let mainTask = await getMainTask(roleId, userTask); + + return resResult(STATUS.SUCCESS, { + type: TASK_FUN_TYPE.MAIN, + ...mainTask, + goods + }); + } + + // 领取每日活跃奖励 + async receiveActiveReward(msg: {}, session: BackendSession) { + + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + + // 检查 + let userTask = await UserTaskModel.findByRole(roleId); + let { dailyTaskPoint } = userTask; + if (dailyTaskPoint < TASK.DAILYTASK_POINT) { + return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + } + // 更新数据 + userTask = await UserTaskModel.decreaseDailyPoint(roleId, TASK.DAILYTASK_POINT); + if (!userTask) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + + let reward = parseGoodStr(TASK.DAILYTASK_POINT_REWARD); + let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.TASK_ACTIVE_REWARD); + + return resResult(STATUS.SUCCESS, { + type: TASK_FUN_TYPE.DAILY, + point: userTask.dailyTaskPoint, + goods + }); + } + + // 领取每日周宝箱 + async receiveBox(msg: { type: number, id: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const roleName: string = session.get('roleName'); + const sid: string = session.get('sid'); + const { type, id } = msg; + + let userTask = await UserTaskModel.findByRole(roleId); + let dicTaskBox = gameData.taskBox.get(type)?.get(id); + if (!dicTaskBox) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let point = 0, weeklyPoint = 0, box: number[] = []; + // 每日、成就增加积分 + if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 + let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); + let shouldRefresh = false; + let { dailyTaskPointWeekly, dailyTaskBox, dailyTaskRefWeekly } = userTask; + + if (curWeek > dailyTaskRefWeekly) { + shouldRefresh = true; + dailyTaskPointWeekly = 0; + dailyTaskBox = []; + } + if (dailyTaskPointWeekly < dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + if (dailyTaskBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); + + userTask = await UserTaskModel.pushDailyBox(roleId, id, curWeek, shouldRefresh); + + point = userTask.dailyTaskPoint; + box = userTask.dailyTaskBox; + weeklyPoint = userTask.dailyTaskPointWeekly; + + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + let { achievementPoint, achievementBox } = userTask; + if (achievementPoint < dicTaskBox.point) return resResult(STATUS.TASK_ACTIVE_NOT_ENOUGH); + if (achievementBox.includes(id)) return resResult(STATUS.TASK_BOX_HAS_RECEIVED); + + userTask = await UserTaskModel.pushAchievementBox(roleId, id); + + point = userTask.achievementPoint; + box = userTask.achievementBox; + } else { + return resResult(STATUS.WRONG_PARMS); + } + + let goods = await addItems(roleId, roleName, sid, dicTaskBox.reward, ITEM_CHANGE_REASON.TASK_BOX_REWARD); + + return resResult(STATUS.SUCCESS, { + type, + point, weeklyPoint, box, + goods + }); + } + + /** + * @description 随机完成某一个任务 + * @param {{ type: number }} msg + * @param {BackendSession} session + * @memberof TaskHandler + */ + async debugCompleteRandTask(msg: { type: number }, session: BackendSession) { + const roleId: string = session.get('roleId'); + const sid: string = session.get('sid'); + const serverId: number = session.get('serverId'); + + const { type } = msg + let tasks: (DicMainTask | DicDailyTask | DicAchievement)[] = []; + for (let [_id, task] of gameData.tasks.get(type)) { + tasks.push(task); + } + let task = getRandSingleEelm(tasks); + await checkTask(serverId, roleId, sid, task.taskType, { debugInfo: {condition: task.condition} }); + return resResult(STATUS.SUCCESS, { + task + }); + } + + async debugRefTask(msg: { type: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let { type } = msg + let userTask; + if (type == TASK_FUN_TYPE.DAILY) { + // 转移每日任务 + await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.DAILY_TASK_REFRESH, { taskList: [] }, sid); + await refDailyTaskBox(roleId, sid, true); + userTask = await UserTaskModel.updateInfo(roleId, { dailyTaskPoint: 0 }); + + } else if (type == TASK_FUN_TYPE.MAIN) { + await UserTaskModel.updateInfo(roleId, { mainTaskStage: 1 }); + userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + await UserTaskModel.updateInfo(roleId, { achievementBox: [], achievementPoint: 0 }); + userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); + } else if (type == TASK_FUN_TYPE.PVP) { + userTask = await removeHistoryTask(roleId, type, new Date(nowSeconds() * 1000 + 86400000)); + } + + let curTask = await getCurTask(roleId, session);; + return resResult(STATUS.SUCCESS, curTask); + } + + async debugCompleteMainStage(msg: {}, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + + + // 检查 + let userTask = await UserTaskModel.findByRole(roleId); + let stage = userTask.mainTaskStage; + + let dicMainStage = gameData.mainTaskStage.get(stage); + if (!dicMainStage) return resResult(STATUS.DIC_DATA_NOT_FOUND); + + let recs = await UserTaskRecModel.getReceiveRec(roleId, TASK_FUN_TYPE.MAIN); + for (let id of dicMainStage.mainTaskId) { + let dicTask = gameData.tasks.get(TASK_FUN_TYPE.MAIN)?.get(id); + if (!dicTask) continue; + let curRecs = recs.find(cur => cur.received.includes(id)); + if (!curRecs) { + await UserTaskRecModel.setTaskRec(roleId, TASK_FUN_TYPE.MAIN, dicTask.taskType, dicTask.group, dicTask.condition); + }; + } + let mainTask = await getMainTask(roleId, userTask); + for (let t of mainTask.taskList) { + let dicTask = gameData.tasks.get(TASK_FUN_TYPE.MAIN)?.get(t.id); + await UserTaskRecModel.setTaskRec(roleId, TASK_FUN_TYPE.MAIN, dicTask.taskType, dicTask.group, dicTask.condition); + } + return resResult(STATUS.SUCCESS, { mainTask }); + } + + async debugIncPoint(msg: { type: number, point: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + let { type, point: incPoint } = msg; + + + // 每日、成就增加积分 + let point = 0, weeklyPoint = 0; + if (type == TASK_FUN_TYPE.DAILY) { // 增加积分 + let userTask = await UserTaskModel.findByRole(roleId); + let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); + if (curWeek > userTask.dailyTaskRefWeekly) { + userTask = await UserTaskModel.resetDailyScore(roleId, incPoint, curWeek); + } else { + userTask = await UserTaskModel.incInfo(roleId, { dailyTaskPoint: incPoint, dailyTaskPointWeekly: incPoint }); + } + point = userTask.dailyTaskPoint; + weeklyPoint = userTask.dailyTaskPointWeekly; + } else if (type == TASK_FUN_TYPE.ACHIEVEMENT) { + let userTask = await UserTaskModel.incInfo(roleId, { achievementPoint: incPoint }); + point = userTask.achievementPoint; + } + + return resResult(STATUS.SUCCESS, { + type, point, weeklyPoint + }); + } + + + async debugGetDicTask(msg: { magicWord: string }, session: BackendSession) { + const { magicWord } = msg; + if (magicWord !== DEBUG_MAGIC_WORD) { + return resResult(STATUS.TOKEN_ERR); + } + // console.log('******', _.isEqual([1,2], [1,2,2])) + return resResult(STATUS.SUCCESS, { tasks: [...gameData.taskType]}); + } + + async test(msg: { magicWord: string }, session: BackendSession) { + let roleId = session.get('roleId'); + let serverId = session.get('serverId'); + let sid = session.get('sid'); + let role = await RoleModel.findByRoleId(roleId); + let server = await ServerlistModel.findByServerId(serverId); + return resResult(STATUS.SUCCESS) + } +} + diff --git a/game-server/app/servers/role/handler/teamHandler.ts b/game-server/app/servers/role/handler/teamHandler.ts index 3471b3034..f14895b47 100644 --- a/game-server/app/servers/role/handler/teamHandler.ts +++ b/game-server/app/servers/role/handler/teamHandler.ts @@ -1,80 +1,81 @@ -import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; -import { STATUS, TEAM_TYPE } from "../../../consts"; -import { gameData } from "../../../pubUtils/data"; -import { resResult } from "../../../pubUtils/util"; -import { PVPConfigModel } from "../../../db/PvpConfig"; -import { PvpSaveDataModel } from "../../../db/PvpSaveData"; -import { LadderMatchModel } from "../../../db/LadderMatch"; -import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank"; -import { GVGTeamModel } from "../../../db/GVGTeam"; -import { PvpDefenseModel } from "../../../db/PvpDefense"; - - - -export default function (app: Application) { - new HandlerService(app, {}); - return new TeamHandler(app); -} - -export class TeamHandler { - channelService: ChannelService; - constructor(private app: Application) { - } - - // 获取每个编队里的武将 - async getTeamHeroes(msg: { }, session: BackendSession) { - const roleId = session.get('roleId'); - - const teams: { type: number, heroes: number[] }[] = []; - - let pvpConfig = await PVPConfigModel.findCurPVPConfig(); - if(pvpConfig) { - let saveDatas = await PvpSaveDataModel.findByRoleId(roleId); - let heroes: number[] = []; - for(let warId of (pvpConfig.warIds||[])) { - let dicWar = gameData.war.get(warId); - if(dicWar && dicWar.selectView == 1) { - let curSaveData = saveDatas.find(cur => cur.warId == warId); - let defenseHeroes = curSaveData?.heroes||[]; - for(let { actorId } of defenseHeroes) heroes.push(actorId); - } - } - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if(pvpDefense && pvpDefense.attack) { - let attackHeroes = pvpDefense.attack.heroes||[]; - for(let { actorId } of attackHeroes) heroes.push(actorId); - } - - teams.push({ type: TEAM_TYPE.PVP, heroes }); - } - - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(ladderData && ladderData.defense) { - let heroes: number[] = []; - let defenseHeroes = ladderData.defense?.heroes||[]; - for(let { actorId } of defenseHeroes) heroes.push(actorId); - teams.push({ type: TEAM_TYPE.LADDER, heroes }); - } - - let vestigeData = await GVGVestigeRankModel.findAllByRole(roleId); - if(vestigeData) { - let heroes: number[] = []; - for(let { lineup = [] } of vestigeData) { - for(let { actorId } of lineup) heroes.push(actorId); - } - teams.push({ type: TEAM_TYPE.VESTIGE, heroes }); - } - - let gvgBattleTeams = await GVGTeamModel.findByRole(roleId, '-_id lineup'); - if(gvgBattleTeams) { - let heroes: number[] = []; - for(let { lineup = [] } of gvgBattleTeams) { - for(let { actorId } of lineup) heroes.push(actorId); - } - teams.push({ type: TEAM_TYPE.GVG_BATTLE, heroes }); - } - - - return resResult(STATUS.SUCCESS, { teams }); - } -} \ No newline at end of file +import { Application, BackendSession, ChannelService, HandlerService } from "pinus"; +import { STATUS, TEAM_TYPE } from "../../../consts"; +import { gameData } from "@pubUtils/data"; +import { resResult } from "@pubUtils/util"; +import { PVPConfigModel } from "@db/PvpConfig"; +import { PvpSaveDataModel } from "@db/PvpSaveData"; +import { LadderMatchModel } from "@db/LadderMatch"; +import { GVGVestigeRankModel } from "@db/GVGVestigeRank"; +import { GVGTeamModel } from "@db/GVGTeam"; +import { PvpDefenseModel } from "@db/PvpDefense"; + + + +export default function (app: Application) { + new HandlerService(app, {}); + return new TeamHandler(app); +} + +export class TeamHandler { + channelService: ChannelService; + constructor(private app: Application) { + } + + // 获取每个编队里的武将 + async getTeamHeroes(msg: { }, session: BackendSession) { + const roleId = session.get('roleId'); + + const teams: { type: number, heroes: number[] }[] = []; + + let pvpConfig = await PVPConfigModel.findCurPVPConfig(); + if(pvpConfig) { + let saveDatas = await PvpSaveDataModel.findByRoleId(roleId); + let heroes: number[] = []; + for(let warId of (pvpConfig.warIds||[])) { + let dicWar = gameData.war.get(warId); + if(dicWar && dicWar.selectView == 1) { + let curSaveData = saveDatas.find(cur => cur.warId == warId); + let defenseHeroes = curSaveData?.heroes||[]; + for(let { actorId } of defenseHeroes) heroes.push(actorId); + } + } + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if(pvpDefense && pvpDefense.attack) { + let attackHeroes = pvpDefense.attack.heroes||[]; + for(let { actorId } of attackHeroes) heroes.push(actorId); + } + + teams.push({ type: TEAM_TYPE.PVP, heroes }); + } + + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(ladderData && ladderData.defense) { + let heroes: number[] = []; + let defenseHeroes = ladderData.defense?.heroes||[]; + for(let { actorId } of defenseHeroes) heroes.push(actorId); + teams.push({ type: TEAM_TYPE.LADDER, heroes }); + } + + let vestigeData = await GVGVestigeRankModel.findAllByRole(roleId); + if(vestigeData) { + let heroes: number[] = []; + for(let { lineup = [] } of vestigeData) { + for(let { actorId } of lineup) heroes.push(actorId); + } + teams.push({ type: TEAM_TYPE.VESTIGE, heroes }); + } + + let gvgBattleTeams = await GVGTeamModel.findByRole(roleId, '-_id lineup'); + if(gvgBattleTeams) { + let heroes: number[] = []; + for(let { lineup = [] } of gvgBattleTeams) { + for(let { actorId } of lineup) heroes.push(actorId); + } + teams.push({ type: TEAM_TYPE.GVG_BATTLE, heroes }); + } + + + return resResult(STATUS.SUCCESS, { teams }); + } +} + diff --git a/game-server/app/servers/role/remote/roleRemote.ts b/game-server/app/servers/role/remote/roleRemote.ts index 7389b0e8b..2d07df4b1 100644 --- a/game-server/app/servers/role/remote/roleRemote.ts +++ b/game-server/app/servers/role/remote/roleRemote.ts @@ -1,225 +1,226 @@ -import { Application, ChannelService, HandlerService, } from 'pinus'; -// import { sendRolesMails } from '../../../services/mailService'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { RankFirstModel, RankFirstType } from '../../../db/RankFirst'; -import { PVPConfigModel, PVPConfigType } from '../../../db/PvpConfig'; -import { treatRoleName, taflush, sendSurveyMail, sendGiftCodeMail } from '../../../services/sdkService'; -import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; -import { errlogger } from '../../../util/logger'; -import { setApiIsClose } from '../../../services/chatService'; -import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; -import { setKvToMemory } from '../../../services/pushService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import { DEBUG_MAGIC_WORD, MAIL_TYPE } from '../../../consts'; -import { ActivityTimeLimitRankModel } from '../../../db/ActivityTimeLimitRank'; -import { RoleModel } from '../../../db/Role'; -import { sendMailToManyPlayerByContent } from '../../../services/mailService'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - new HandlerService(app, {}); - return new RoleRemote(app); -} - -export class RoleRemote { - - constructor(private app: Application) { - this.app = app; - // this.channelService = app.get('channelService'); - this.loadRankFirst(); - } - // private channelService: ChannelService; - - private rankFirstRewards: Map> = new Map(); - - private async loadRankFirst() { - let rankFirstRewards = await RankFirstModel.findAllRankRewards(); - for(let rank of rankFirstRewards) { - if(!this.rankFirstRewards.has(rank.serverId)) { - this.rankFirstRewards.set(rank.serverId, new Map()); - } - this.rankFirstRewards.get(rank.serverId).set(rank.id, rank); - } - this.app.set('rankFirstRewards', this.rankFirstRewards); - } - - public setRankFirst(rank: RankFirstType) { - try { - // console.log('****** setRankFirst', rank.serverId, rank.id, rank) - if(!this.rankFirstRewards.has(rank.serverId)) { - this.rankFirstRewards.set(rank.serverId, new Map()); - } - this.rankFirstRewards.get(rank.serverId).set(rank.id, rank); - this.app.set('rankFirstRewards', this.rankFirstRewards); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - - } - - public getRankFirstById(serverId: number, id: number) { - try { - return this.rankFirstRewards.get(serverId)?.get(id); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { - try { - await setPvpSettleSeasonNum(pvpConfig); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async treatRoleName(roleId: string) { - try { - await treatRoleName(roleId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - try { - setServerMainten(serverIds, startTime, endTime, version); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public stopServerMainten(serverIds: number[]) { - try { - stopServerMainten(serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public getServerMainten(serverId: number) { - try { - return getServerMainten(serverId); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async sendSurveyMail(code: string) { - try { - await sendSurveyMail(code); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - - public async sendGiftCodeMail(message: string) { - try { - await sendGiftCodeMail(message); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async repairTimeLimitRank(magicWord: string, activityId: number, serverIds: number[], ridRoleIds: string[]) { - try { - if(magicWord != DEBUG_MAGIC_WORD) return; - - for(let serverId of serverIds) { - let allRanks = await ActivityTimeLimitRankModel.getRank(serverId, activityId); - let roles = await RoleModel.findAllRoleForTimeLimitRank(serverId, 16); - let roleIds: string[] = []; - - for(let { roleId } of roles) { - let index = allRanks.findIndex(cur => cur.roleId == roleId); - if(index == -1 && ridRoleIds.indexOf(roleId) == -1) roleIds.push(roleId); - } - await sendMailToManyPlayerByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleIds, { - params: ['战力', '200+'], - goods: [{ id: 71002, count: 40 }, { id: 31002, count: 500 }] - }); - - } - - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} +import { Application, ChannelService, HandlerService, } from 'pinus'; +// import { sendRolesMails } from '../../../services/mailService'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { RankFirstModel, RankFirstType } from '@db/RankFirst'; +import { PVPConfigModel, PVPConfigType } from '@db/PvpConfig'; +import { treatRoleName, taflush, sendSurveyMail, sendGiftCodeMail } from '../../../services/sdkService'; +import { getServerMainten, setServerMainten, stopServerMainten } from '../../../services/gmService'; +import { errlogger } from '../../../util/logger'; +import { setApiIsClose } from '../../../services/chatService'; +import { setPvpSeasonNum, setPvpSettleSeasonNum } from '../../../services/timeTaskService'; +import { setKvToMemory } from '../../../services/pushService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import { DEBUG_MAGIC_WORD, MAIL_TYPE } from '../../../consts'; +import { ActivityTimeLimitRankModel } from '@db/ActivityTimeLimitRank'; +import { RoleModel } from '@db/Role'; +import { sendMailToManyPlayerByContent } from '../../../services/mailService'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + new HandlerService(app, {}); + return new RoleRemote(app); +} + +export class RoleRemote { + + constructor(private app: Application) { + this.app = app; + // this.channelService = app.get('channelService'); + this.loadRankFirst(); + } + // private channelService: ChannelService; + + private rankFirstRewards: Map> = new Map(); + + private async loadRankFirst() { + let rankFirstRewards = await RankFirstModel.findAllRankRewards(); + for(let rank of rankFirstRewards) { + if(!this.rankFirstRewards.has(rank.serverId)) { + this.rankFirstRewards.set(rank.serverId, new Map()); + } + this.rankFirstRewards.get(rank.serverId).set(rank.id, rank); + } + this.app.set('rankFirstRewards', this.rankFirstRewards); + } + + public setRankFirst(rank: RankFirstType) { + try { + // console.log('****** setRankFirst', rank.serverId, rank.id, rank) + if(!this.rankFirstRewards.has(rank.serverId)) { + this.rankFirstRewards.set(rank.serverId, new Map()); + } + this.rankFirstRewards.get(rank.serverId).set(rank.id, rank); + this.app.set('rankFirstRewards', this.rankFirstRewards); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + + } + + public getRankFirstById(serverId: number, id: number) { + try { + return this.rankFirstRewards.get(serverId)?.get(id); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSettleSeasonNum(pvpConfig: PVPConfigType) { + try { + await setPvpSettleSeasonNum(pvpConfig); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async treatRoleName(roleId: string) { + try { + await treatRoleName(roleId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + try { + setServerMainten(serverIds, startTime, endTime, version); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public stopServerMainten(serverIds: number[]) { + try { + stopServerMainten(serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public getServerMainten(serverId: number) { + try { + return getServerMainten(serverId); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async sendSurveyMail(code: string) { + try { + await sendSurveyMail(code); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + + public async sendGiftCodeMail(message: string) { + try { + await sendGiftCodeMail(message); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async repairTimeLimitRank(magicWord: string, activityId: number, serverIds: number[], ridRoleIds: string[]) { + try { + if(magicWord != DEBUG_MAGIC_WORD) return; + + for(let serverId of serverIds) { + let allRanks = await ActivityTimeLimitRankModel.getRank(serverId, activityId); + let roles = await RoleModel.findAllRoleForTimeLimitRank(serverId, 16); + let roleIds: string[] = []; + + for(let { roleId } of roles) { + let index = allRanks.findIndex(cur => cur.roleId == roleId); + if(index == -1 && ridRoleIds.indexOf(roleId) == -1) roleIds.push(roleId); + } + await sendMailToManyPlayerByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleIds, { + params: ['战力', '200+'], + goods: [{ id: 71002, count: 40 }, { id: 31002, count: 500 }] + }); + + } + + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/systimer/remote/systimerRemote.ts b/game-server/app/servers/systimer/remote/systimerRemote.ts index 5662286a9..360941b5a 100644 --- a/game-server/app/servers/systimer/remote/systimerRemote.ts +++ b/game-server/app/servers/systimer/remote/systimerRemote.ts @@ -1,320 +1,321 @@ -import { Application, ChannelService } from 'pinus'; -import { guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule, initMaintenance, stopMaintenance, addMailsToSchedule, updateTimeLimitRank, setLadderCountDown, cancelLadderCountDown, initSumSchedule, setPvpSeasonSchedule, initGVGConfigSchedule, gvgBattleStartSchedule, gvgBattleEndSchedule, initHiddenDataSchedule, initVipSignInMailSchedule } from '../../../services/timeTaskService'; -import PvpDefenseType from '../../../db/PvpDefense'; -import { DicGuildActivity } from '../../../pubUtils/dictionary/DicGuildActivity'; -import { gameData, reloadResources } from '../../../pubUtils/data'; -import { setMarquee, cancelMarquee } from '../../../services/gmService'; -import { setDicAuctionTime, setDicGuildActivity } from '../../../services/guildActivity/guildActivityService'; -import { setWeek } from '../../../pubUtils/timeUtil'; -import { ServerlistType } from '../../../db/Serverlist'; -import { MarqueeType } from '../../../db/Marquee'; -import { taflush } from '../../../services/sdkService'; -import { RegionType } from '../../../db/Region'; -import { errlogger } from '../../../util/logger'; -import { MailType } from '../../../db/Mail'; -import { GroupMailType } from '../../../db/GroupMail'; -import { ServerMailType } from '../../../db/ServerMail'; -import { ActivityModelType } from '../../../db/Activity'; -import { GUILD_ACTIVITY_TYPE, LADDER_STATUS } from '../../../consts'; -import { setApiIsClose } from '../../../services/chatService'; -import { setKvToMemory } from '../../../services/pushService'; -import { setServerGroup } from '../../../services/serverService'; -import { setHiddenData } from '../../../services/memoryCache/hiddenData'; -import * as dicParam from '../../../pubUtils/dicParam'; - -export default function (app: Application) { - return new SystimerRemote(app); -} - -export class SystimerRemote { - - constructor(private app: Application) { - this.app = app; - this.channelService = app.get('channelService'); - } - private channelService: ChannelService; - - public async guildActivityStart(dicGuildActivity: DicGuildActivity) { - try { - return await guildActivityStart(dicGuildActivity); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gateActivityEnd() { - try { - return await gateActivityEnd(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async cityActivityEnd() { - try { - return await cityActivityEnd(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async raceActivityEnd() { - try { - return await raceActivityEnd(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 重载json资源 - */ - public async reloadResources(type?: string) { - try { - reloadResources(type); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setDicParam(field1: string, field2: string, value: string|number) { - try { - if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGameDataToApp() { - try { - this.app.set('gameData', gameData); - this.app.set('dicParam', dicParam); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * @description 设置跑马灯配置 - * @param code 跑马灯唯一code - */ - public async setMarquee(marquee: MarqueeType) { - try { - return await setMarquee(marquee); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async cancelMarquee(code: string) { - try { - return await cancelMarquee(code); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的军团活动开始时间&持续时间 - * @param {number} aid 活动 - * @param {number} startSeconds 从现在开始几秒后开启活动 - * @param {number} endSeconds 从开始之后几秒后结束活动 - */ - public async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { - try { - setDicGuildActivity(now, aid, startSeconds, endSeconds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * 改变字典表中的拍卖行时间 - */ - public async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { - try { - setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setGuildActivitySchedule() { - try { - await guildActivitySchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setAuctionSchedule() { - try { - auctionSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - /** - * !! 注意,这条函数会改变内存时间,影响甚大,请考虑清楚后使用 - */ - async setDay(week: number) { - try { - setWeek(week); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async initMaintenance(servers?: ServerlistType[]) { - try { - await initMaintenance(servers); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async stopMaintenance(batchCode: string, serverIds: number[]) { - try { - await stopMaintenance(batchCode, serverIds); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public taflush() { - try { - return taflush(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async addMailsToSchedule(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { - try { - await addMailsToSchedule(mails, groupMails, serverMails); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async updateTimeLimitRank(activities: ActivityModelType[]) { - try { - await updateTimeLimitRank(activities); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async initSumSchedule() { - try { - await initSumSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setLadderCountDown(battleCode: string, time: number, status: LADDER_STATUS) { - try { - await setLadderCountDown(battleCode, time, status); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async cancelLadderCountDown(battleCode: string) { - try { - await cancelLadderCountDown(battleCode); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setApiIsClose(isClose: boolean) { - try { - setApiIsClose(isClose); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setPvpSeasonSchedule(fromBackend: boolean) { - try { - setPvpSeasonSchedule(fromBackend); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setHiddenData(heroes: number[], goods: number[], refTime: number) { - try { - setHiddenData(heroes, goods, refTime); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gmSetHiddenDataSchedule() { - try { - await initHiddenDataSchedule(false); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - try { - setKvToMemory(originK, originV, aesKey, aesIV, now); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async initGVGConfigSchedule() { - try { - await initGVGConfigSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gvgBattleStartSchedule() { - try { - await gvgBattleStartSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async gvgBattleEndSchedule() { - try { - await gvgBattleEndSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async setServerGroup() { - try { - await setServerGroup(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async initVipSignInMailSchedule() { - try { - await initVipSignInMailSchedule(); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } - - public async fun() { - try { - console.log('预留一个函数,用于之后线上维护时需要使用'); - } catch(e) { - errlogger.error(`remote ${__filename} \n ${e.stack}`); - } - } -} +import { Application, ChannelService } from 'pinus'; +import { guildActivityStart, gateActivityEnd, cityActivityEnd, raceActivityEnd, guildActivitySchedule, auctionSchedule, initMaintenance, stopMaintenance, addMailsToSchedule, updateTimeLimitRank, setLadderCountDown, cancelLadderCountDown, initSumSchedule, setPvpSeasonSchedule, initGVGConfigSchedule, gvgBattleStartSchedule, gvgBattleEndSchedule, initHiddenDataSchedule, initVipSignInMailSchedule } from '../../../services/timeTaskService'; +import PvpDefenseType from '@db/PvpDefense'; +import { DicGuildActivity } from '@pubUtils/dictionary/DicGuildActivity'; +import { gameData, reloadResources } from '@pubUtils/data'; +import { setMarquee, cancelMarquee } from '../../../services/gmService'; +import { setDicAuctionTime, setDicGuildActivity } from '../../../services/guildActivity/guildActivityService'; +import { setWeek } from '@pubUtils/timeUtil'; +import { ServerlistType } from '@db/Serverlist'; +import { MarqueeType } from '@db/Marquee'; +import { taflush } from '../../../services/sdkService'; +import { RegionType } from '@db/Region'; +import { errlogger } from '../../../util/logger'; +import { MailType } from '@db/Mail'; +import { GroupMailType } from '@db/GroupMail'; +import { ServerMailType } from '@db/ServerMail'; +import { ActivityModelType } from '@db/Activity'; +import { GUILD_ACTIVITY_TYPE, LADDER_STATUS } from '../../../consts'; +import { setApiIsClose } from '../../../services/chatService'; +import { setKvToMemory } from '../../../services/pushService'; +import { setServerGroup } from '../../../services/serverService'; +import { setHiddenData } from '../../../services/memoryCache/hiddenData'; +import * as dicParam from '@pubUtils/dicParam'; + +export default function (app: Application) { + return new SystimerRemote(app); +} + +export class SystimerRemote { + + constructor(private app: Application) { + this.app = app; + this.channelService = app.get('channelService'); + } + private channelService: ChannelService; + + public async guildActivityStart(dicGuildActivity: DicGuildActivity) { + try { + return await guildActivityStart(dicGuildActivity); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gateActivityEnd() { + try { + return await gateActivityEnd(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async cityActivityEnd() { + try { + return await cityActivityEnd(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async raceActivityEnd() { + try { + return await raceActivityEnd(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 重载json资源 + */ + public async reloadResources(type?: string) { + try { + reloadResources(type); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setDicParam(field1: string, field2: string, value: string|number) { + try { + if(dicParam[field1] && dicParam[field1][field2]) dicParam[field1][field2] = value; + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGameDataToApp() { + try { + this.app.set('gameData', gameData); + this.app.set('dicParam', dicParam); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * @description 设置跑马灯配置 + * @param code 跑马灯唯一code + */ + public async setMarquee(marquee: MarqueeType) { + try { + return await setMarquee(marquee); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async cancelMarquee(code: string) { + try { + return await cancelMarquee(code); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的军团活动开始时间&持续时间 + * @param {number} aid 活动 + * @param {number} startSeconds 从现在开始几秒后开启活动 + * @param {number} endSeconds 从开始之后几秒后结束活动 + */ + public async setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { + try { + setDicGuildActivity(now, aid, startSeconds, endSeconds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * 改变字典表中的拍卖行时间 + */ + public async setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { + try { + setDicAuctionTime(startTime, endActivity, startGuild, endGuild, startWorld, endWorld); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setGuildActivitySchedule() { + try { + await guildActivitySchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setAuctionSchedule() { + try { + auctionSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + /** + * !! 注意,这条函数会改变内存时间,影响甚大,请考虑清楚后使用 + */ + async setDay(week: number) { + try { + setWeek(week); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async initMaintenance(servers?: ServerlistType[]) { + try { + await initMaintenance(servers); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async stopMaintenance(batchCode: string, serverIds: number[]) { + try { + await stopMaintenance(batchCode, serverIds); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public taflush() { + try { + return taflush(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async addMailsToSchedule(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { + try { + await addMailsToSchedule(mails, groupMails, serverMails); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async updateTimeLimitRank(activities: ActivityModelType[]) { + try { + await updateTimeLimitRank(activities); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async initSumSchedule() { + try { + await initSumSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setLadderCountDown(battleCode: string, time: number, status: LADDER_STATUS) { + try { + await setLadderCountDown(battleCode, time, status); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async cancelLadderCountDown(battleCode: string) { + try { + await cancelLadderCountDown(battleCode); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setApiIsClose(isClose: boolean) { + try { + setApiIsClose(isClose); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setPvpSeasonSchedule(fromBackend: boolean) { + try { + setPvpSeasonSchedule(fromBackend); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setHiddenData(heroes: number[], goods: number[], refTime: number) { + try { + setHiddenData(heroes, goods, refTime); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gmSetHiddenDataSchedule() { + try { + await initHiddenDataSchedule(false); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + try { + setKvToMemory(originK, originV, aesKey, aesIV, now); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async initGVGConfigSchedule() { + try { + await initGVGConfigSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleStartSchedule() { + try { + await gvgBattleStartSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async gvgBattleEndSchedule() { + try { + await gvgBattleEndSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async setServerGroup() { + try { + await setServerGroup(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async initVipSignInMailSchedule() { + try { + await initVipSignInMailSchedule(); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } + + public async fun() { + try { + console.log('预留一个函数,用于之后线上维护时需要使用'); + } catch(e) { + errlogger.error(`remote ${__filename} \n ${e.stack}`); + } + } +} + diff --git a/game-server/app/servers/user.rpc.define.ts b/game-server/app/servers/user.rpc.define.ts index 0ea823b50..0f1d44a8c 100644 --- a/game-server/app/servers/user.rpc.define.ts +++ b/game-server/app/servers/user.rpc.define.ts @@ -1,51 +1,51 @@ - -// 这种 - -// UserRpc的命名空间自动合并 -import { FrontendSession, RemoterClass } from 'pinus'; -import { ChatRemote } from './chat/remote/chatRemote'; -import { ComBattleRemote } from './comBattle/remote/comBattleRemote'; -import { BattleRemote } from './battle/remote/battleRemote'; -import { ConnectorRemote } from './connector/remote/connectorRemote'; -import { SystimerRemote } from './systimer/remote/systimerRemote'; -import { GMRemote } from './gm/remote/gmRemote'; -import { RoleRemote } from './role/remote/roleRemote'; -import { GuildActivityRemote } from './guild/remote/guildActivityRemote'; -import { GuildRemote as GuildRemote2 } from './guild/remote/guildRemote'; -import { ActivityRemote } from './activity/remote/activityRemote'; -import { OrderRemote } from './order/remote/orderRemote'; -declare global { - interface UserRpc { - activity: { - activityRemote: RemoterClass; - }; - battle: { - battleRemote: RemoterClass; - }; - comBattle: { - comBattleRemote: RemoterClass; - }; - chat: { - chatRemote: RemoterClass; - }; - connector: { - connectorRemote: RemoterClass; - }; - guild: { - guildRemote: RemoterClass; - guildActivityRemote: RemoterClass; - }, - systimer: { - systimerRemote: RemoterClass; - }, - gm: { - gmRemote: RemoterClass; - }, - role: { - roleRemote: RemoterClass; - }, - order: { - orderRemote: RemoterClass; - } - } -} \ No newline at end of file + +// 这种 + +// UserRpc的命名空间自动合并 +import { FrontendSession, RemoterClass } from 'pinus'; +import { ChatRemote } from './chat/remote/chatRemote'; +import { ComBattleRemote } from './comBattle/remote/comBattleRemote'; +import { BattleRemote } from './battle/remote/battleRemote'; +import { ConnectorRemote } from './connector/remote/connectorRemote'; +import { SystimerRemote } from './systimer/remote/systimerRemote'; +import { GMRemote } from './gm/remote/gmRemote'; +import { RoleRemote } from './role/remote/roleRemote'; +import { GuildActivityRemote } from './guild/remote/guildActivityRemote'; +import { GuildRemote as GuildRemote2 } from './guild/remote/guildRemote'; +import { ActivityRemote } from './activity/remote/activityRemote'; +import { OrderRemote } from './order/remote/orderRemote'; +declare global { + interface UserRpc { + activity: { + activityRemote: RemoterClass; + }; + battle: { + battleRemote: RemoterClass; + }; + comBattle: { + comBattleRemote: RemoterClass; + }; + chat: { + chatRemote: RemoterClass; + }; + connector: { + connectorRemote: RemoterClass; + }; + guild: { + guildRemote: RemoterClass; + guildActivityRemote: RemoterClass; + }, + systimer: { + systimerRemote: RemoterClass; + }, + gm: { + gmRemote: RemoterClass; + }, + role: { + roleRemote: RemoterClass; + }, + order: { + orderRemote: RemoterClass; + } + } +} diff --git a/game-server/app/services/actionPointService.ts b/game-server/app/services/actionPointService.ts index c027b6e0d..ee61d45ba 100644 --- a/game-server/app/services/actionPointService.ts +++ b/game-server/app/services/actionPointService.ts @@ -1,124 +1,124 @@ -/** - * 体力系统 - */ - -import { ActionPointModel, ActionPointType } from '../db/ActionPoint'; -import { TASK_TYPE, STATUS, TA_EVENT, ITEM_CHANGE_REASON, PUSH_ROUTE } from '../consts'; -import { checkTask } from './task/taskService'; -import { getDicApByLv } from '../pubUtils/data'; -import { pinus } from 'pinus'; -import { resResult, shouldRefresh } from '../pubUtils/util'; -import { pick } from 'underscore'; -import { AP } from '../pubUtils/dicParam'; -import { reportTAEvent } from './sdkService'; -import { sendMessageToUserWithSuc } from './pushService'; - -/** - * 获取当前体力 - * @param roleId 玩家id - * @param lv 玩家等级 - */ -export async function getAp(roleId: string, ip: string, lv: number, fromGetAp = false) { - let dataAp = await ActionPointModel.getAp(roleId); - return getApWithDataAp(roleId, ip, lv, dataAp, fromGetAp); -} - -function getApWithDataAp(roleId: string, ip: string, lv: number, dataAp: ActionPointType, fromGetAp = false) { - - const now = Date.now(); - const dicAp = getDicApByLv(lv); - const maxAp = dicAp.maxAp; // 最大体力值 - const per = AP.PERAPRESTORETIME * 1000; // 恢复时间(ms) - let { ap, refTime, buyRefTime = 0, buyTimes = 0, apBefore } = dataAp; - let oldAp = ap; - - if(shouldRefresh(new Date(buyRefTime), new Date())) { - buyTimes = 0; - } - - let result; - if (ap >= maxAp) { - // 体力溢出不需要做时间的处理 - result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore }; - } else { - if (refTime > now) refTime = now; // refTime:每次记录时候最近的一个整的时间点,绝对不会大于now - let n = Math.floor((now - refTime) / per); // 上次记录到现在可以增长多少体力 - ap += n; // 增加上 - if (ap >= maxAp) { // 加上后溢出了 - ap = maxAp; - result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore }; - } else { - refTime += n * per; // 更新refTime到离现在最近的一个整的时间点 - let apRemainTime = Math.floor((refTime + per - now) / 1000); // 恢复下一点需要多少时间 - let apMaxRemainTime = (maxAp - ap - 1) * AP.PERAPRESTORETIME + apRemainTime; - result = { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver: false, buyTimes, buyRefTime, apBefore }; - } - } - // if(result.ap > oldAp) { - // reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: result.ap - oldAp, change_after: result.ap, change_reason: ITEM_CHANGE_REASON.AP_RECOVERY }) - // } - - return fromGetAp?result: pick(result, ['ap', 'maxAp', 'apRemainTime', 'apMaxRemainTime', 'buyTimes', 'apBefore']); -} - -/** - * 增加或减少体力 - * @param roleId 玩家id - * @param lv 玩家等级 - * @param changeAp 体力变化,正是加,负是减 - * @param sid - */ -export async function setAp(serverId: number, roleId: string, ip: string, lv: number, changeAp: number, sid: string, reason: ITEM_CHANGE_REASON) { - // console.log('***** setAp', roleId, ip, lv, changeAp) - const now = Date.now(); - - let ApResult = await getAp(roleId, ip, lv, true); - let { ap: apBefore, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver, buyTimes } = ApResult; // 更新ap - let ap = apBefore + changeAp; - if (ap >= maxAp) { // 溢出 - refTime = now; - apRemainTime = 0; - apMaxRemainTime = 0; - } - if (ap < 0) return null // 体力不足 - let dataAp = await ActionPointModel.saveAp(roleId, ap, apBefore, refTime); - - if (isOver && ap < maxAp) { // 特殊处理,溢出之后做减少体力的操作时 - apRemainTime = AP.PERAPRESTORETIME; - apMaxRemainTime = (maxAp - ap) * AP.PERAPRESTORETIME; - } - - if (changeAp < 0) { - await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_COST_AP, { count: -changeAp }); - // reportTAEvent(roleId, TA_EVENT.AP_CONSUME, { change_count: -1 * changeAp, change_after: ap, change_reason: reason }, ip) - } else if(changeAp > 0){ - reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: changeAp, change_after: ap, change_reason: reason }, ip) - } - let apJson = await getApWithDataAp(roleId, ip, lv, dataAp); - - if (changeAp != 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AP_UPDATE, { apJson: { ...apJson, apBefore } }, sid); - } - - return apJson -} - -export async function setApBuyTimes(roleId: string, ip: string, lv: number, sid: string, incTimes: number) { - if(incTimes <= 0) return false; - - let ApResult = await getAp(roleId, ip, lv, true); - let { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, buyTimes, buyRefTime } = ApResult; // 更新ap - - if(shouldRefresh(new Date(buyRefTime), new Date())) { - buyTimes = 0; - buyRefTime = new Date(); - } - buyTimes += incTimes; - await ActionPointModel.saveBuyTimes(roleId, buyTimes, buyRefTime); - - let apJson = { ap, maxAp, refTime, apMaxRemainTime, apRemainTime, buyTimes }; - if(incTimes != 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AP_UPDATE, { apJson }, sid); - } - return apJson; -} \ No newline at end of file +/** + * 体力系统 + */ + +import { ActionPointModel, ActionPointType } from '@db/ActionPoint'; +import { TASK_TYPE, STATUS, TA_EVENT, ITEM_CHANGE_REASON, PUSH_ROUTE } from '@consts'; +import { checkTask } from './task/taskService'; +import { getDicApByLv } from '@pubUtils/data'; +import { pinus } from 'pinus'; +import { resResult, shouldRefresh } from '@pubUtils/util'; +import { pick } from 'underscore'; +import { AP } from '@pubUtils/dicParam'; +import { reportTAEvent } from './sdkService'; +import { sendMessageToUserWithSuc } from './pushService'; + +/** + * 获取当前体力 + * @param roleId 玩家id + * @param lv 玩家等级 + */ +export async function getAp(roleId: string, ip: string, lv: number, fromGetAp = false) { + let dataAp = await ActionPointModel.getAp(roleId); + return getApWithDataAp(roleId, ip, lv, dataAp, fromGetAp); +} + +function getApWithDataAp(roleId: string, ip: string, lv: number, dataAp: ActionPointType, fromGetAp = false) { + + const now = Date.now(); + const dicAp = getDicApByLv(lv); + const maxAp = dicAp.maxAp; // 最大体力值 + const per = AP.PERAPRESTORETIME * 1000; // 恢复时间(ms) + let { ap, refTime, buyRefTime = 0, buyTimes = 0, apBefore } = dataAp; + let oldAp = ap; + + if(shouldRefresh(new Date(buyRefTime), new Date())) { + buyTimes = 0; + } + + let result; + if (ap >= maxAp) { + // 体力溢出不需要做时间的处理 + result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore }; + } else { + if (refTime > now) refTime = now; // refTime:每次记录时候最近的一个整的时间点,绝对不会大于now + let n = Math.floor((now - refTime) / per); // 上次记录到现在可以增长多少体力 + ap += n; // 增加上 + if (ap >= maxAp) { // 加上后溢出了 + ap = maxAp; + result = { ap, maxAp, refTime: now, apRemainTime: 0, apMaxRemainTime: 0, isOver: true, buyTimes, buyRefTime, apBefore }; + } else { + refTime += n * per; // 更新refTime到离现在最近的一个整的时间点 + let apRemainTime = Math.floor((refTime + per - now) / 1000); // 恢复下一点需要多少时间 + let apMaxRemainTime = (maxAp - ap - 1) * AP.PERAPRESTORETIME + apRemainTime; + result = { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver: false, buyTimes, buyRefTime, apBefore }; + } + } + // if(result.ap > oldAp) { + // reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: result.ap - oldAp, change_after: result.ap, change_reason: ITEM_CHANGE_REASON.AP_RECOVERY }) + // } + + return fromGetAp?result: pick(result, ['ap', 'maxAp', 'apRemainTime', 'apMaxRemainTime', 'buyTimes', 'apBefore']); +} + +/** + * 增加或减少体力 + * @param roleId 玩家id + * @param lv 玩家等级 + * @param changeAp 体力变化,正是加,负是减 + * @param sid + */ +export async function setAp(serverId: number, roleId: string, ip: string, lv: number, changeAp: number, sid: string, reason: ITEM_CHANGE_REASON) { + // console.log('***** setAp', roleId, ip, lv, changeAp) + const now = Date.now(); + + let ApResult = await getAp(roleId, ip, lv, true); + let { ap: apBefore, maxAp, refTime, apRemainTime, apMaxRemainTime, isOver, buyTimes } = ApResult; // 更新ap + let ap = apBefore + changeAp; + if (ap >= maxAp) { // 溢出 + refTime = now; + apRemainTime = 0; + apMaxRemainTime = 0; + } + if (ap < 0) return null // 体力不足 + let dataAp = await ActionPointModel.saveAp(roleId, ap, apBefore, refTime); + + if (isOver && ap < maxAp) { // 特殊处理,溢出之后做减少体力的操作时 + apRemainTime = AP.PERAPRESTORETIME; + apMaxRemainTime = (maxAp - ap) * AP.PERAPRESTORETIME; + } + + if (changeAp < 0) { + await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_COST_AP, { count: -changeAp }); + // reportTAEvent(roleId, TA_EVENT.AP_CONSUME, { change_count: -1 * changeAp, change_after: ap, change_reason: reason }, ip) + } else if(changeAp > 0){ + reportTAEvent(roleId, TA_EVENT.AP_GET, { change_count: changeAp, change_after: ap, change_reason: reason }, ip) + } + let apJson = await getApWithDataAp(roleId, ip, lv, dataAp); + + if (changeAp != 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AP_UPDATE, { apJson: { ...apJson, apBefore } }, sid); + } + + return apJson +} + +export async function setApBuyTimes(roleId: string, ip: string, lv: number, sid: string, incTimes: number) { + if(incTimes <= 0) return false; + + let ApResult = await getAp(roleId, ip, lv, true); + let { ap, maxAp, refTime, apRemainTime, apMaxRemainTime, buyTimes, buyRefTime } = ApResult; // 更新ap + + if(shouldRefresh(new Date(buyRefTime), new Date())) { + buyTimes = 0; + buyRefTime = new Date(); + } + buyTimes += incTimes; + await ActionPointModel.saveBuyTimes(roleId, buyTimes, buyRefTime); + + let apJson = { ap, maxAp, refTime, apMaxRemainTime, apRemainTime, buyTimes }; + if(incTimes != 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AP_UPDATE, { apJson }, sid); + } + return apJson; +} diff --git a/game-server/app/services/activity/activityService.ts b/game-server/app/services/activity/activityService.ts index 337d9e489..faa18bee3 100644 --- a/game-server/app/services/activity/activityService.ts +++ b/game-server/app/services/activity/activityService.ts @@ -1,508 +1,508 @@ -import { ACTIVITY_TYPE, PUSH_ROUTE, STATUS, TASK_FUN_TYPE } from '../../consts'; -import { getPlayerFirstGiftDataShow } from './firstGiftService'; -import { getPlayerSignInData, } from './signInService'; -import { getPlayerGrowthFundData, } from './growthFundService'; -import { getPlayerLimitPackageData, } from './limitPackageService'; -import { getPlayerYuanbaoShopData, } from './yuanbaoService'; -import { getPlayerMonthlyTicketData, } from './monthlyTicketService'; -import { getPlayerRechargeMoneyDataShow, } from './rechargeMoneyService'; -import { getPlayerThirtyDaysData } from './thirtyDaysService'; -import { getPlayerVipRechargeMoneyData, } from './vipRechargeMoneyService'; -import { getPlayerActivityData, } from './selfServiceShopActivityService'; -import { ActivitySelfServiceGoodsModel } from '../../db/ActivitySelfServiceGoods'; -import { getPlayerTreasureHuntDataShow } from './treasureHuntService'; -import { getPopUpShopDataShow } from './popUpShopService'; -import { getPlayerSevenDaysData } from './sevenDaysService'; -import { getPlayerDailyMealData } from './dailyMealService'; -import { getPlayerDailyCoinData } from './dailyCoinService'; -import { getPlayerDailyRMBGiftsData } from './dailyRMBGiftsService'; -import { getPlayerDailyGKData } from './dailyGKService'; -import { getPlayerRefreshShopData } from './refreshShopService'; -import { getPlayerRefreshTaskData } from './refreshTaskService'; -import { getPlayerMonopolyData } from './monopolyService'; -import { getPlayerNewHeroGiftsData, newHeroGiftPoint, getPlayerNewHeroGKData, getPlayerNewHeroGachaData } from './newHeroService'; -import { BackendSession, pinus } from 'pinus'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { getRandSingleEelm, resResult } from '../../pubUtils/util'; -import { SignInData } from '../../domain/activityField/signInField'; -import { ActivityInRemote, transActivityInRemoteToModelType } from '../../domain/activityField/activityField'; -import { getPlayerLuckyTurntableDataShow } from './luckyTurntableService'; -import { getTimeLimitRankDataShow } from './timeLimitRankService'; -import { ActivityTaskPointModel } from '../../db/ActivityTaskPoint'; -import { getRoleOnlineInfo } from '../redisService'; -import { addTaskPassPoint, getTaskPassDataShow } from './taskPassService'; -import { getGuildPayDataShow } from './guildPayService'; -import { PopUpShopItemShow } from '../../domain/activityField/popUpShopField'; -import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from '../pushService'; -import { UserOrderModelType } from '../../db/UserOrder'; -import { isArray } from 'underscore'; -import { getGuideGachaData } from './gachaService'; -import { getPopNoticeData } from './popNoticeService'; -import { _getActivities, _getActivitiesByServerId, _getActivitiesByType, _getActivityById } from '../memoryCache/activityData'; -import { getGroupShopDataShow } from './groupShopService'; -import { getAllSnsLinkDataShow } from './bindPhoneService'; -import { getPlayerForgeDataShow } from './forgeService'; -import { getPlayerMiniGameDataShow } from './miniGameService'; -import { getWeeklyFundDataShow } from './weeklyFundService'; -import { getMonthlyFundData } from './monthlyFundService'; -import { getPlayerRebateDataShow } from './rebateService'; -import { getWebviewDataShow } from './webviewService'; -import { getPlayerDragonBoatDataShow } from './dragonBoatService'; -import { getPlayerEntertainDataShow } from './entertainService'; -import { getPlayerQixiDataShow } from './qixiService'; -import { getPlayerMidAutumnDataShow } from './midAutumnService'; -import { getPlayerAuthorGachaDataShow } from './authorGachaService'; -import { getPlayerChongYangDataShow } from './chongyangService'; -import { getPlayerNovemberDataShow } from './novemberServices'; -import { getPlayerLuckyDataShow } from './luckyService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getActivity(serverId: number, roleId: string, uid: number, guildCode: string, activityId: number, activityType: number) { - try { - let activityData = null; - switch (activityType) { - case ACTIVITY_TYPE.SIGN_IN://签到 4 - case ACTIVITY_TYPE.SIGN_IN_VIP://高级签到 5 - case ACTIVITY_TYPE.NEW_PLAYER_SIGN_IN://新手签到 25 - case ACTIVITY_TYPE.COMMON_SIGN_IN://通用签到 36 - { - activityData = await getPlayerSignInData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN://成长基金 6 - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP://高阶成长基金 7 - case ACTIVITY_TYPE.GROWTH_FUND_TOWER://镇念塔成长基金 8 - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://高阶镇念塔成长基金 9 - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE://精英成长基金 10 - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://高阶精英成长基金 11 - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE://学宫普通密卷 60 - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP://学宫高级密卷 61 - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR://列传普通密卷 62 - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP://列传高级密卷 63 - { - activityData = await getPlayerGrowthFundData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.THIRTY_DAYS://30天目标活动 12 - { - activityData = await getPlayerThirtyDaysData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.SELF_SERVICE_SHOP://自选商店 糜家商队 13 - { - let data = await getPlayerActivityData(activityId, serverId, roleId); - let playerGoods = await ActivitySelfServiceGoodsModel.findData(activityId, roleId, data.roundIndex, true); - if(data.canShow()) { - activityData = { playerData: data, playerGoods: playerGoods ? playerGoods : [] } - } - break; - } - case ACTIVITY_TYPE.FIRST_GIFT://首冲礼包活动 14 - { - activityData = await getPlayerFirstGiftDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE://新手限定RMB购买礼包 15 - { - activityData = await getPlayerLimitPackageData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY://每日限购礼包,RMB购买礼包 16 - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY://每周限购礼包,RMB购买礼包 17 - { - activityData = await getPlayerLimitPackageData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.YUAN_BAO_SHOP://元宝商店 18 - { - activityData = await getPlayerYuanbaoShopData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.MONTHLY_TICKET_1://月卡1 19 - case ACTIVITY_TYPE.MONTHLY_TICKET_2://月卡2 20 - { - activityData = await getPlayerMonthlyTicketData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.RECHARGE_MONEY://累计充值RMB活动 21 - { - activityData = await getPlayerRechargeMoneyDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.DAILY_RMB_GIFTS://每日特惠RMB购买,一次性购买7天礼包 22 - { - activityData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.TREASURE_HUNT://寻宝骑兵活动 23 - { - activityData = await getPlayerTreasureHuntDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.POP_UP_SHOP://弹出商店 24 - { - activityData = await getPopUpShopDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.VIP_RECHARGE_MONEY://vip累计充值活动 26 - { - activityData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.SEVEN_DAY://七天乐活动 27 - case ACTIVITY_TYPE.FOURTEEN_DAY://十四天乐活动 28 - case ACTIVITY_TYPE.COMMON_SEVEN_DAY://通用七天乐活动 29 - { - activityData = await getPlayerSevenDaysData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.DAILY_MEAL://每日领取免费午饭、晚饭活动 30 - { - activityData = await getPlayerDailyMealData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.DAILY_COIN://每日兑换铜币活动 31 - { - activityData = await getPlayerDailyCoinData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.DAILY_GK://每日关卡(每日开启一关) 32 - { - activityData = await getPlayerDailyGKData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) 33 - { - activityData = await getPlayerRefreshShopData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.REFRESH_TASK://通用的刷新任务(分页,可刷新,限制领取次数) 34 - { - activityData = await getPlayerRefreshTaskData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.MONOPOLY://大富翁游戏 35 - { - activityData = await getPlayerMonopolyData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.NEW_HERO_GIFTS://新将好礼(很多红包,用积分兑换一遍结束) 37 - { - activityData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.NEW_HERO_GK://新将演绎 (配置N个武将,每个武将有X个关卡;活动期间,*天(时间自定义)开启每个武将对应的一个关卡,只有第一次通关会获得奖励) - { - activityData = await getPlayerNewHeroGKData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.NEW_HERO_GACHA://新将擢迁(新武将抽取) - { - activityData = await getPlayerNewHeroGachaData(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.LUCKY_TURNTABLE://幸运转盘 - { - activityData = await getPlayerLuckyTurntableDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.TIME_LIMIT_RANK: // 限时排行 - { - activityData = await getTimeLimitRankDataShow(activityId, serverId); - break; - } - case ACTIVITY_TYPE.TASK_PASS: // 战令、朝花夕拾 - { - activityData = await getTaskPassDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.GUILD_PAY: - { - activityData = await getGuildPayDataShow(serverId, activityId, roleId, guildCode); - break - } - case ACTIVITY_TYPE.GUIDE_GACHA: - { - activityData = await getGuideGachaData(serverId, activityId, roleId); - break - } - case ACTIVITY_TYPE.SHOP: - break - case ACTIVITY_TYPE.POP_NOTICE: - { - activityData = await getPopNoticeData(serverId, activityId, roleId); - break - } - case ACTIVITY_TYPE.GROUP_SHOP: - { - activityData = await getGroupShopDataShow(activityId, roleId); - break - } - case ACTIVITY_TYPE.BIND_PHONE: - { - activityData = await getAllSnsLinkDataShow(activityId, roleId, serverId, uid); - break - } - case ACTIVITY_TYPE.FORGE: - { - activityData = await getPlayerForgeDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.MINI_GAME: - { - activityData = await getPlayerMiniGameDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.WEEKLY_FUND: - { - activityData = await getWeeklyFundDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.MONTHLY_FUND: - { - activityData = await getMonthlyFundData(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.REBATE: - { - activityData = await getPlayerRebateDataShow(activityId, serverId, roleId, uid); - break - } - case ACTIVITY_TYPE.WEBVIEW: - { - activityData = await getWebviewDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.DRAGON_BOAT: - { - activityData = await getPlayerDragonBoatDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.ENTERTAIN: - { - activityData = await getPlayerEntertainDataShow(activityId, serverId, roleId); - break - } - case ACTIVITY_TYPE.QIXI: - { - activityData = await getPlayerQixiDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.MID_AUTUMN: - { - activityData = await getPlayerMidAutumnDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.AUTHOR_GACHA: - { - activityData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.CHONGYANG: - { - activityData = await getPlayerChongYangDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.NOVEMBER: - { - activityData = await getPlayerNovemberDataShow(activityId, serverId, roleId); - break; - } - case ACTIVITY_TYPE.LUCKY://幸运转盘新 - { - activityData = await getPlayerLuckyDataShow(activityId, serverId, roleId); - break; - } - default: { - console.log('未知活动类型.........', activityType) - break; - } - } - if(activityData && activityData.canShow && !activityData.canShow()) { - return null - } - return activityData; - } catch(e) { - console.log('activity error', e, activityId, activityType); - return null; - } -} - -export async function getActivityById(activityId: number) { - let serverType = pinus.app.getServerType(); - let activity: ActivityInRemote; - if(serverType == 'activity') { - activity = _getActivityById(activityId); - } else { - let servers = pinus.app.getServersByType('activity'); - let server = getRandSingleEelm(servers); - activity = await pinus.app.rpc.activity.activityRemote.getActivityById.toServer(server.id, activityId); - } - return transActivityInRemoteToModelType(activity) -} - -export async function getActivitiesByType(serverId: number, type: number) { - let serverType = pinus.app.getServerType(); - let activities: ActivityInRemote[] = []; - if(serverType == 'activity') { - activities = _getActivitiesByType(serverId, type); - } else { - let servers = pinus.app.getServersByType('activity'); - let server = getRandSingleEelm(servers); - activities = await pinus.app.rpc.activity.activityRemote.getActivitiesByType.toServer(server.id, serverId, type); - } - return activities.map(transActivityInRemoteToModelType); -} - -export async function getActivitiesByTypes(serverId: number, types: number[]) { - let result: ActivityModelType[] = []; - for(let type of types) { - let activities = await getActivitiesByType(serverId, type); - if(activities && isArray(activities)) result.push(...activities); - } - return result; -} - -export async function getActivities() { - let serverType = pinus.app.getServerType(); - if(serverType == 'activity') { - return _getActivities(); - } else { - let servers = pinus.app.getServersByType('activity'); - let server = getRandSingleEelm(servers); - return await pinus.app.rpc.activity.activityRemote.getActivities.toServer(server.id); - } -} - -export async function getActivityByServerId(serverId: number) { - let activities: ActivityInRemote[] = []; - let serverType = pinus.app.getServerType(); - if(serverType == 'activity') { - activities = _getActivitiesByServerId(serverId); - } else { - let servers = pinus.app.getServersByType('activity'); - let server = getRandSingleEelm(servers); - activities = await pinus.app.rpc.activity.activityRemote.getActivitiesByServerId.toServer(server.id, serverId); - } - return activities.map(transActivityInRemoteToModelType); -} - -export async function checkActivityEditable(activities: ActivityModelType[]) { - let now = new Date(); - - for(let activity of activities) { - if(!activity || (activity.beginTime < now && activity.endTime > now)) { - - if(activity.type == ACTIVITY_TYPE.SIGN_IN || activity.type == ACTIVITY_TYPE.SIGN_IN_VIP) { - // 签到活动的不显示期内也可以编辑 - let signInObj = new SignInData(activity, 0, 0); - if(signInObj.beginTime < now.getTime() && signInObj.endTime > now.getTime() ) { - return false; - } - } else { - return false; - } - } - } - - return true; -} - -/** - * 达成任务可活动活动积分 - * @param type 任务类型,主线、每日、成就 - * @param id - * @param point - * @param session - */ -export async function addActvityTaskPoint(type: number, addPoint: number, session: BackendSession) { - if(type != TASK_FUN_TYPE.DAILY) return - let serverId: number = session.get('serverId'); - let roleId: string = session.get('roleId'); - let sid: string = session.get('sid'); - let result: pushActivityInter[] = []; - let newHeroResult = await newHeroGiftPoint(serverId, roleId, addPoint); - let taskPassResult = await addTaskPassPoint(serverId, roleId, addPoint); - result.push(...newHeroResult, ...taskPassResult); - if(result.length > 0) await pushActivities(result, roleId, sid); -} - - -interface pushActivityParamInter { - ticketCnt?: number; // 木签活动的签数(type21) - totalPoint?: number; // 新将好礼(type37)和战令(type42)更新后的积分 - payMemberCnt?: number; // 军团充值活动,你的军团充值的人数 - payMember?: string; // 军团充值活动,充值人员名字,添加到payRecord里面 - payRecord?: string[]; // 军团全部充值人名字 - popUpShopItems?: PopUpShopItemShow[]; // 弹出礼包 -} - -export interface pushActivityInter { - activityId: number, - activityType: number, - param: pushActivityParamInter; -} - -export async function pushSingleActivity(activityId: number, activityType: number, param: pushActivityParamInter, roleId: string, sid?: string) { - await pushActivities([{ activityId, activityType, param }], roleId, sid); -} - -export async function pushActivities(arr: pushActivityInter[], roleId: string, sid?: string) { - if(!sid) { - let onlineUser = await getRoleOnlineInfo(roleId); - sid = onlineUser.sid; - } - if(!!sid && arr.length > 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_UPDATE, { activities: arr }, sid); - } - return arr -} - -export async function pushActivitiesToGuild(arr: pushActivityInter[], guildCode: string) { - if(arr.length > 0) await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.ACTIVITY_UPDATE, { activities: arr }) -} - -export async function getActivitiesWithOrder(orderInfo: UserOrderModelType) { - let activities: ActivityModelType[] = []; - let curActivity = await getActivityById(orderInfo.activityId); - if(curActivity) activities.push(curActivity); - - let activitiesWithSum = await getActivitiesByTypes(orderInfo.serverId, [ACTIVITY_TYPE.FIRST_GIFT, ACTIVITY_TYPE.RECHARGE_MONEY, ACTIVITY_TYPE.VIP_RECHARGE_MONEY, ACTIVITY_TYPE.GUILD_PAY]); - if(activitiesWithSum && isArray(activitiesWithSum)) activities.push(...activitiesWithSum); - - if(orderInfo.paramStr) { //大富翁商店结算 - try { - let paramObj = JSON.parse(orderInfo.paramStr); - let paramActivity = paramObj.activityId && await getActivityById(paramObj.activityId); - if(paramActivity) activities.push(paramActivity); - } catch(e) { - console.error(e); - } - } - return activities; -} - -export function shouldReplace(activityType: ACTIVITY_TYPE) { - switch(activityType) { - case ACTIVITY_TYPE.TASK_PASS: - // case ACTIVITY_TYPE.SIGN_IN: - // case ACTIVITY_TYPE.SIGN_IN_VIP: - // case ACTIVITY_TYPE.GROWTH_FUND_MAIN: // 成长基金 6 - // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: // 高阶成长基金 7 - // case ACTIVITY_TYPE.GROWTH_FUND_TOWER: // 镇念塔成长基金 8 - // case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP: // 高阶镇念塔成长基金 9 - // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: // 精英成长基金 10 - // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP:// 高阶精英成长基金 11 - case ACTIVITY_TYPE.MONTHLY_FUND:// 月基金 - return true; - default: - return false; - } -} \ No newline at end of file +import { ACTIVITY_TYPE, PUSH_ROUTE, STATUS, TASK_FUN_TYPE } from '@consts'; +import { getPlayerFirstGiftDataShow } from './firstGiftService'; +import { getPlayerSignInData, } from './signInService'; +import { getPlayerGrowthFundData, } from './growthFundService'; +import { getPlayerLimitPackageData, } from './limitPackageService'; +import { getPlayerYuanbaoShopData, } from './yuanbaoService'; +import { getPlayerMonthlyTicketData, } from './monthlyTicketService'; +import { getPlayerRechargeMoneyDataShow, } from './rechargeMoneyService'; +import { getPlayerThirtyDaysData } from './thirtyDaysService'; +import { getPlayerVipRechargeMoneyData, } from './vipRechargeMoneyService'; +import { getPlayerActivityData, } from './selfServiceShopActivityService'; +import { ActivitySelfServiceGoodsModel } from '@db/ActivitySelfServiceGoods'; +import { getPlayerTreasureHuntDataShow } from './treasureHuntService'; +import { getPopUpShopDataShow } from './popUpShopService'; +import { getPlayerSevenDaysData } from './sevenDaysService'; +import { getPlayerDailyMealData } from './dailyMealService'; +import { getPlayerDailyCoinData } from './dailyCoinService'; +import { getPlayerDailyRMBGiftsData } from './dailyRMBGiftsService'; +import { getPlayerDailyGKData } from './dailyGKService'; +import { getPlayerRefreshShopData } from './refreshShopService'; +import { getPlayerRefreshTaskData } from './refreshTaskService'; +import { getPlayerMonopolyData } from './monopolyService'; +import { getPlayerNewHeroGiftsData, newHeroGiftPoint, getPlayerNewHeroGKData, getPlayerNewHeroGachaData } from './newHeroService'; +import { BackendSession, pinus } from 'pinus'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { getRandSingleEelm, resResult } from '@pubUtils/util'; +import { SignInData } from '@domain/activityField/signInField'; +import { ActivityInRemote, transActivityInRemoteToModelType } from '@domain/activityField/activityField'; +import { getPlayerLuckyTurntableDataShow } from './luckyTurntableService'; +import { getTimeLimitRankDataShow } from './timeLimitRankService'; +import { ActivityTaskPointModel } from '@db/ActivityTaskPoint'; +import { getRoleOnlineInfo } from '../redisService'; +import { addTaskPassPoint, getTaskPassDataShow } from './taskPassService'; +import { getGuildPayDataShow } from './guildPayService'; +import { PopUpShopItemShow } from '@domain/activityField/popUpShopField'; +import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from '../pushService'; +import { UserOrderModelType } from '@db/UserOrder'; +import { isArray } from 'underscore'; +import { getGuideGachaData } from './gachaService'; +import { getPopNoticeData } from './popNoticeService'; +import { _getActivities, _getActivitiesByServerId, _getActivitiesByType, _getActivityById } from '../memoryCache/activityData'; +import { getGroupShopDataShow } from './groupShopService'; +import { getAllSnsLinkDataShow } from './bindPhoneService'; +import { getPlayerForgeDataShow } from './forgeService'; +import { getPlayerMiniGameDataShow } from './miniGameService'; +import { getWeeklyFundDataShow } from './weeklyFundService'; +import { getMonthlyFundData } from './monthlyFundService'; +import { getPlayerRebateDataShow } from './rebateService'; +import { getWebviewDataShow } from './webviewService'; +import { getPlayerDragonBoatDataShow } from './dragonBoatService'; +import { getPlayerEntertainDataShow } from './entertainService'; +import { getPlayerQixiDataShow } from './qixiService'; +import { getPlayerMidAutumnDataShow } from './midAutumnService'; +import { getPlayerAuthorGachaDataShow } from './authorGachaService'; +import { getPlayerChongYangDataShow } from './chongyangService'; +import { getPlayerNovemberDataShow } from './novemberServices'; +import { getPlayerLuckyDataShow } from './luckyService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getActivity(serverId: number, roleId: string, uid: number, guildCode: string, activityId: number, activityType: number) { + try { + let activityData = null; + switch (activityType) { + case ACTIVITY_TYPE.SIGN_IN://签到 4 + case ACTIVITY_TYPE.SIGN_IN_VIP://高级签到 5 + case ACTIVITY_TYPE.NEW_PLAYER_SIGN_IN://新手签到 25 + case ACTIVITY_TYPE.COMMON_SIGN_IN://通用签到 36 + { + activityData = await getPlayerSignInData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN://成长基金 6 + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP://高阶成长基金 7 + case ACTIVITY_TYPE.GROWTH_FUND_TOWER://镇念塔成长基金 8 + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://高阶镇念塔成长基金 9 + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE://精英成长基金 10 + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://高阶精英成长基金 11 + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE://学宫普通密卷 60 + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP://学宫高级密卷 61 + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR://列传普通密卷 62 + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP://列传高级密卷 63 + { + activityData = await getPlayerGrowthFundData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.THIRTY_DAYS://30天目标活动 12 + { + activityData = await getPlayerThirtyDaysData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.SELF_SERVICE_SHOP://自选商店 糜家商队 13 + { + let data = await getPlayerActivityData(activityId, serverId, roleId); + let playerGoods = await ActivitySelfServiceGoodsModel.findData(activityId, roleId, data.roundIndex, true); + if(data.canShow()) { + activityData = { playerData: data, playerGoods: playerGoods ? playerGoods : [] } + } + break; + } + case ACTIVITY_TYPE.FIRST_GIFT://首冲礼包活动 14 + { + activityData = await getPlayerFirstGiftDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE://新手限定RMB购买礼包 15 + { + activityData = await getPlayerLimitPackageData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY://每日限购礼包,RMB购买礼包 16 + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY://每周限购礼包,RMB购买礼包 17 + { + activityData = await getPlayerLimitPackageData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.YUAN_BAO_SHOP://元宝商店 18 + { + activityData = await getPlayerYuanbaoShopData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.MONTHLY_TICKET_1://月卡1 19 + case ACTIVITY_TYPE.MONTHLY_TICKET_2://月卡2 20 + { + activityData = await getPlayerMonthlyTicketData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.RECHARGE_MONEY://累计充值RMB活动 21 + { + activityData = await getPlayerRechargeMoneyDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.DAILY_RMB_GIFTS://每日特惠RMB购买,一次性购买7天礼包 22 + { + activityData = await getPlayerDailyRMBGiftsData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.TREASURE_HUNT://寻宝骑兵活动 23 + { + activityData = await getPlayerTreasureHuntDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.POP_UP_SHOP://弹出商店 24 + { + activityData = await getPopUpShopDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.VIP_RECHARGE_MONEY://vip累计充值活动 26 + { + activityData = await getPlayerVipRechargeMoneyData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.SEVEN_DAY://七天乐活动 27 + case ACTIVITY_TYPE.FOURTEEN_DAY://十四天乐活动 28 + case ACTIVITY_TYPE.COMMON_SEVEN_DAY://通用七天乐活动 29 + { + activityData = await getPlayerSevenDaysData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.DAILY_MEAL://每日领取免费午饭、晚饭活动 30 + { + activityData = await getPlayerDailyMealData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.DAILY_COIN://每日兑换铜币活动 31 + { + activityData = await getPlayerDailyCoinData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.DAILY_GK://每日关卡(每日开启一关) 32 + { + activityData = await getPlayerDailyGKData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) 33 + { + activityData = await getPlayerRefreshShopData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.REFRESH_TASK://通用的刷新任务(分页,可刷新,限制领取次数) 34 + { + activityData = await getPlayerRefreshTaskData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.MONOPOLY://大富翁游戏 35 + { + activityData = await getPlayerMonopolyData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.NEW_HERO_GIFTS://新将好礼(很多红包,用积分兑换一遍结束) 37 + { + activityData = await getPlayerNewHeroGiftsData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.NEW_HERO_GK://新将演绎 (配置N个武将,每个武将有X个关卡;活动期间,*天(时间自定义)开启每个武将对应的一个关卡,只有第一次通关会获得奖励) + { + activityData = await getPlayerNewHeroGKData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.NEW_HERO_GACHA://新将擢迁(新武将抽取) + { + activityData = await getPlayerNewHeroGachaData(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.LUCKY_TURNTABLE://幸运转盘 + { + activityData = await getPlayerLuckyTurntableDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.TIME_LIMIT_RANK: // 限时排行 + { + activityData = await getTimeLimitRankDataShow(activityId, serverId); + break; + } + case ACTIVITY_TYPE.TASK_PASS: // 战令、朝花夕拾 + { + activityData = await getTaskPassDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.GUILD_PAY: + { + activityData = await getGuildPayDataShow(serverId, activityId, roleId, guildCode); + break + } + case ACTIVITY_TYPE.GUIDE_GACHA: + { + activityData = await getGuideGachaData(serverId, activityId, roleId); + break + } + case ACTIVITY_TYPE.SHOP: + break + case ACTIVITY_TYPE.POP_NOTICE: + { + activityData = await getPopNoticeData(serverId, activityId, roleId); + break + } + case ACTIVITY_TYPE.GROUP_SHOP: + { + activityData = await getGroupShopDataShow(activityId, roleId); + break + } + case ACTIVITY_TYPE.BIND_PHONE: + { + activityData = await getAllSnsLinkDataShow(activityId, roleId, serverId, uid); + break + } + case ACTIVITY_TYPE.FORGE: + { + activityData = await getPlayerForgeDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.MINI_GAME: + { + activityData = await getPlayerMiniGameDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.WEEKLY_FUND: + { + activityData = await getWeeklyFundDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.MONTHLY_FUND: + { + activityData = await getMonthlyFundData(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.REBATE: + { + activityData = await getPlayerRebateDataShow(activityId, serverId, roleId, uid); + break + } + case ACTIVITY_TYPE.WEBVIEW: + { + activityData = await getWebviewDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.DRAGON_BOAT: + { + activityData = await getPlayerDragonBoatDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.ENTERTAIN: + { + activityData = await getPlayerEntertainDataShow(activityId, serverId, roleId); + break + } + case ACTIVITY_TYPE.QIXI: + { + activityData = await getPlayerQixiDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.MID_AUTUMN: + { + activityData = await getPlayerMidAutumnDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.AUTHOR_GACHA: + { + activityData = await getPlayerAuthorGachaDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.CHONGYANG: + { + activityData = await getPlayerChongYangDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.NOVEMBER: + { + activityData = await getPlayerNovemberDataShow(activityId, serverId, roleId); + break; + } + case ACTIVITY_TYPE.LUCKY://幸运转盘新 + { + activityData = await getPlayerLuckyDataShow(activityId, serverId, roleId); + break; + } + default: { + console.log('未知活动类型.........', activityType) + break; + } + } + if(activityData && activityData.canShow && !activityData.canShow()) { + return null + } + return activityData; + } catch(e) { + console.log('activity error', e, activityId, activityType); + return null; + } +} + +export async function getActivityById(activityId: number) { + let serverType = pinus.app.getServerType(); + let activity: ActivityInRemote; + if(serverType == 'activity') { + activity = _getActivityById(activityId); + } else { + let servers = pinus.app.getServersByType('activity'); + let server = getRandSingleEelm(servers); + activity = await pinus.app.rpc.activity.activityRemote.getActivityById.toServer(server.id, activityId); + } + return transActivityInRemoteToModelType(activity) +} + +export async function getActivitiesByType(serverId: number, type: number) { + let serverType = pinus.app.getServerType(); + let activities: ActivityInRemote[] = []; + if(serverType == 'activity') { + activities = _getActivitiesByType(serverId, type); + } else { + let servers = pinus.app.getServersByType('activity'); + let server = getRandSingleEelm(servers); + activities = await pinus.app.rpc.activity.activityRemote.getActivitiesByType.toServer(server.id, serverId, type); + } + return activities.map(transActivityInRemoteToModelType); +} + +export async function getActivitiesByTypes(serverId: number, types: number[]) { + let result: ActivityModelType[] = []; + for(let type of types) { + let activities = await getActivitiesByType(serverId, type); + if(activities && isArray(activities)) result.push(...activities); + } + return result; +} + +export async function getActivities() { + let serverType = pinus.app.getServerType(); + if(serverType == 'activity') { + return _getActivities(); + } else { + let servers = pinus.app.getServersByType('activity'); + let server = getRandSingleEelm(servers); + return await pinus.app.rpc.activity.activityRemote.getActivities.toServer(server.id); + } +} + +export async function getActivityByServerId(serverId: number) { + let activities: ActivityInRemote[] = []; + let serverType = pinus.app.getServerType(); + if(serverType == 'activity') { + activities = _getActivitiesByServerId(serverId); + } else { + let servers = pinus.app.getServersByType('activity'); + let server = getRandSingleEelm(servers); + activities = await pinus.app.rpc.activity.activityRemote.getActivitiesByServerId.toServer(server.id, serverId); + } + return activities.map(transActivityInRemoteToModelType); +} + +export async function checkActivityEditable(activities: ActivityModelType[]) { + let now = new Date(); + + for(let activity of activities) { + if(!activity || (activity.beginTime < now && activity.endTime > now)) { + + if(activity.type == ACTIVITY_TYPE.SIGN_IN || activity.type == ACTIVITY_TYPE.SIGN_IN_VIP) { + // 签到活动的不显示期内也可以编辑 + let signInObj = new SignInData(activity, 0, 0); + if(signInObj.beginTime < now.getTime() && signInObj.endTime > now.getTime() ) { + return false; + } + } else { + return false; + } + } + } + + return true; +} + +/** + * 达成任务可活动活动积分 + * @param type 任务类型,主线、每日、成就 + * @param id + * @param point + * @param session + */ +export async function addActvityTaskPoint(type: number, addPoint: number, session: BackendSession) { + if(type != TASK_FUN_TYPE.DAILY) return + let serverId: number = session.get('serverId'); + let roleId: string = session.get('roleId'); + let sid: string = session.get('sid'); + let result: pushActivityInter[] = []; + let newHeroResult = await newHeroGiftPoint(serverId, roleId, addPoint); + let taskPassResult = await addTaskPassPoint(serverId, roleId, addPoint); + result.push(...newHeroResult, ...taskPassResult); + if(result.length > 0) await pushActivities(result, roleId, sid); +} + + +interface pushActivityParamInter { + ticketCnt?: number; // 木签活动的签数(type21) + totalPoint?: number; // 新将好礼(type37)和战令(type42)更新后的积分 + payMemberCnt?: number; // 军团充值活动,你的军团充值的人数 + payMember?: string; // 军团充值活动,充值人员名字,添加到payRecord里面 + payRecord?: string[]; // 军团全部充值人名字 + popUpShopItems?: PopUpShopItemShow[]; // 弹出礼包 +} + +export interface pushActivityInter { + activityId: number, + activityType: number, + param: pushActivityParamInter; +} + +export async function pushSingleActivity(activityId: number, activityType: number, param: pushActivityParamInter, roleId: string, sid?: string) { + await pushActivities([{ activityId, activityType, param }], roleId, sid); +} + +export async function pushActivities(arr: pushActivityInter[], roleId: string, sid?: string) { + if(!sid) { + let onlineUser = await getRoleOnlineInfo(roleId); + sid = onlineUser.sid; + } + if(!!sid && arr.length > 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_UPDATE, { activities: arr }, sid); + } + return arr +} + +export async function pushActivitiesToGuild(arr: pushActivityInter[], guildCode: string) { + if(arr.length > 0) await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.ACTIVITY_UPDATE, { activities: arr }) +} + +export async function getActivitiesWithOrder(orderInfo: UserOrderModelType) { + let activities: ActivityModelType[] = []; + let curActivity = await getActivityById(orderInfo.activityId); + if(curActivity) activities.push(curActivity); + + let activitiesWithSum = await getActivitiesByTypes(orderInfo.serverId, [ACTIVITY_TYPE.FIRST_GIFT, ACTIVITY_TYPE.RECHARGE_MONEY, ACTIVITY_TYPE.VIP_RECHARGE_MONEY, ACTIVITY_TYPE.GUILD_PAY]); + if(activitiesWithSum && isArray(activitiesWithSum)) activities.push(...activitiesWithSum); + + if(orderInfo.paramStr) { //大富翁商店结算 + try { + let paramObj = JSON.parse(orderInfo.paramStr); + let paramActivity = paramObj.activityId && await getActivityById(paramObj.activityId); + if(paramActivity) activities.push(paramActivity); + } catch(e) { + console.error(e); + } + } + return activities; +} + +export function shouldReplace(activityType: ACTIVITY_TYPE) { + switch(activityType) { + case ACTIVITY_TYPE.TASK_PASS: + // case ACTIVITY_TYPE.SIGN_IN: + // case ACTIVITY_TYPE.SIGN_IN_VIP: + // case ACTIVITY_TYPE.GROWTH_FUND_MAIN: // 成长基金 6 + // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: // 高阶成长基金 7 + // case ACTIVITY_TYPE.GROWTH_FUND_TOWER: // 镇念塔成长基金 8 + // case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP: // 高阶镇念塔成长基金 9 + // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: // 精英成长基金 10 + // case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP:// 高阶精英成长基金 11 + case ACTIVITY_TYPE.MONTHLY_FUND:// 月基金 + return true; + default: + return false; + } +} diff --git a/game-server/app/services/activity/authorGachaService.ts b/game-server/app/services/activity/authorGachaService.ts index 7c2e25edf..65af3168e 100644 --- a/game-server/app/services/activity/authorGachaService.ts +++ b/game-server/app/services/activity/authorGachaService.ts @@ -1,34 +1,34 @@ -import { ACTIVITY_TYPE } from "../../consts/constModules/activityConst"; -import { ActivityAuthorGachaRecModel } from "../../db/AuthorGachaRec"; -import { UserGachaModel } from "../../db/UserGacha"; -import { AuthorGachaData } from "../../domain/activityField/authorGachaField"; -import { getGachaRemainFloor } from "../../pubUtils/util"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -export async function getPlayerAuthorGachaData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - if(!activityData) return - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new AuthorGachaData(activityData, createTime, serverTime); - if ((playerData?.type || 0) != ACTIVITY_TYPE.AUTHOR_GACHA) return - let playerRecord = await ActivityAuthorGachaRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -export async function getUseGachaData(activityId: number, roleId: string, playerData: AuthorGachaData) { - let userGacha = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); - let count = userGacha?.count || 0; - let remainFloor = getGachaRemainFloor(playerData.gachaId, userGacha?.floor || []); - return { count, remainFloor } -} - -export async function getPlayerAuthorGachaDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerAuthorGachaData(activityId, serverId, roleId); - if (playerData && playerData.canShow && playerData.canShow()) { - return { ...playerData.getShowResult(), ...await getUseGachaData(activityId, roleId, playerData) }; - } - return null -} \ No newline at end of file +import { ACTIVITY_TYPE } from "@consts/constModules/activityConst"; +import { ActivityAuthorGachaRecModel } from "@db/AuthorGachaRec"; +import { UserGachaModel } from "@db/UserGacha"; +import { AuthorGachaData } from "@domain/activityField/authorGachaField"; +import { getGachaRemainFloor } from "@pubUtils/util"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +export async function getPlayerAuthorGachaData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + if(!activityData) return + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new AuthorGachaData(activityData, createTime, serverTime); + if ((playerData?.type || 0) != ACTIVITY_TYPE.AUTHOR_GACHA) return + let playerRecord = await ActivityAuthorGachaRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +export async function getUseGachaData(activityId: number, roleId: string, playerData: AuthorGachaData) { + let userGacha = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); + let count = userGacha?.count || 0; + let remainFloor = getGachaRemainFloor(playerData.gachaId, userGacha?.floor || []); + return { count, remainFloor } +} + +export async function getPlayerAuthorGachaDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerAuthorGachaData(activityId, serverId, roleId); + if (playerData && playerData.canShow && playerData.canShow()) { + return { ...playerData.getShowResult(), ...await getUseGachaData(activityId, roleId, playerData) }; + } + return null +} diff --git a/game-server/app/services/activity/bindPhoneService.ts b/game-server/app/services/activity/bindPhoneService.ts index e98ecf96d..e0d1a1c9c 100644 --- a/game-server/app/services/activity/bindPhoneService.ts +++ b/game-server/app/services/activity/bindPhoneService.ts @@ -1,149 +1,149 @@ -import { isNumber } from 'underscore'; -import { ACTIVITY_TYPE, BIND_PHONE_STATUS, PUBLIC_ACCOUNT_GIFT, PUSH_ROUTE, SDK_37_CONST, SNS_LINK_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityBindPhoneRewardModel } from '../../db/ActivityBindPhoneReward'; -import { ActivityPublicAccountCodeModel } from '../../db/ActivityPublicAccountCode'; -import { LinkModel } from '../../db/Link'; -import { UserModel, UserType } from '../../db/User'; -import { BindPhoneData } from '../../domain/activityField/bindPhoneField'; -import { aes128Encrypt } from '../../pubUtils/util'; -import { getOnlineRoleByUserCode, getRedis, getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivityById } from './activityService'; -import { sendMessageToUserWithSuc } from '../pushService'; - - -/** - * 绑定手机相关数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getAllSnsLinkData(activityId: number, roleId: string, serverId: number, uid: number) { - - let activityData: ActivityModelType = await getActivityById(activityId); - if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new BindPhoneData(activityData, createTime, serverTime); - - let links = await LinkModel.findByServerId(serverId); - playerData.setLinks(links); - - let user: UserType; - if(playerData.bindPhone) { - if(!user) user = await UserModel.findUserByUid(uid); - let receiveRec = await ActivityBindPhoneRewardModel.findByUid(activityId, uid); - playerData.bindPhone.setBindPhoneStatus(user, receiveRec); - } - if(playerData.wxPublicAccount) { - if(!user) user = await UserModel.findUserByUid(uid); - if(user.channelInfo) { - let giftCode = encodeGiftCode(roleId, serverId, user.channelInfo.uid, user.channelInfo.platformAppid, user.channelInfo.childGameId, activityId); - playerData.wxPublicAccount.setEncodeGiftCode(giftCode); - let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, user.channelId); - if(playerRecord) playerData.wxPublicAccount.setPlayerRecord(playerRecord); - } - } - - return playerData; -} - -/** - * 绑定手机相关数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getBindPhoneData(activityId: number, roleId: string, serverId: number, uid: number) { - - let activityData: ActivityModelType = await getActivityById(activityId); - if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new BindPhoneData(activityData, createTime, serverTime); - - let links = await LinkModel.findByServerId(serverId); - playerData.setLinks(links); - - let user: UserType; - if(playerData.bindPhone) { - if(!user) user = await UserModel.findUserByUid(uid); - let receiveRec = await ActivityBindPhoneRewardModel.findByUid(activityId, uid); - playerData.bindPhone.setBindPhoneStatus(user, receiveRec); - } - - return playerData; -} - -/** - * 微信公众号 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPublicAccountData(activityId: number, roleId: string, serverId: number, user: UserType) { - - let activityData: ActivityModelType = await getActivityById(activityId); - if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new BindPhoneData(activityData, createTime, serverTime); - - let links = await LinkModel.findByServerId(serverId); - playerData.setLinks(links); - - if(playerData.wxPublicAccount) { - if(user.channelInfo) { - let giftCode = encodeGiftCode(roleId, serverId, user.channelInfo.uid, user.channelInfo.platformAppid, user.channelInfo.childGameId, activityId); - playerData.wxPublicAccount.setEncodeGiftCode(giftCode); - let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, user.channelId); - if(playerRecord) playerData.wxPublicAccount.setPlayerRecord(playerRecord); - } - } - - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getAllSnsLinkDataShow(activityId: number, roleId: string, serverId: number, uid: number) { - let playerData = await getAllSnsLinkData(activityId, roleId, serverId, uid); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -function encodeGiftCode(roleId: string, serverId: number, uid: number, pid: string, gid: string, activityId: number) { - let encodeResult = aes128Encrypt(`${roleId}|${serverId}|${uid}|${pid}|${gid}|${PUBLIC_ACCOUNT_GIFT}${activityId}|${SDK_37_CONST.GIFT_GAME_ID}`, SDK_37_CONST.PUBLIC_GIFT_KEY); - return `FS${encodeResult}`; -} - -export async function sendPublicAccountGift(message: string) { - let [_activityId, userCode, channelId] = message?.split('|')||[]; - let activityId = parseInt(_activityId); - if(!isNumber(activityId) || !userCode || !channelId) return; - - let onlineRoleId = await getOnlineRoleByUserCode(userCode); - // console.log('##### sendPublicAccountGift', message, userCode, onlineRoleId); - if (!!onlineRoleId) { // 在线,推送消息 - let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, channelId); - await sendMessageToUserWithSuc(onlineRoleId, PUSH_ROUTE.PUBLIC_ACCOUNT_GIFT, { activityId, type: SNS_LINK_TYPE.WX_PUBLIC_ACCOUNT, status: playerRecord.hasReceived? BIND_PHONE_STATUS.RECEIVED: BIND_PHONE_STATUS.HAS_BIND }); - } -} \ No newline at end of file +import { isNumber } from 'underscore'; +import { ACTIVITY_TYPE, BIND_PHONE_STATUS, PUBLIC_ACCOUNT_GIFT, PUSH_ROUTE, SDK_37_CONST, SNS_LINK_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityBindPhoneRewardModel } from '@db/ActivityBindPhoneReward'; +import { ActivityPublicAccountCodeModel } from '@db/ActivityPublicAccountCode'; +import { LinkModel } from '@db/Link'; +import { UserModel, UserType } from '@db/User'; +import { BindPhoneData } from '@domain/activityField/bindPhoneField'; +import { aes128Encrypt } from '@pubUtils/util'; +import { getOnlineRoleByUserCode, getRedis, getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivityById } from './activityService'; +import { sendMessageToUserWithSuc } from '../pushService'; + + +/** + * 绑定手机相关数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getAllSnsLinkData(activityId: number, roleId: string, serverId: number, uid: number) { + + let activityData: ActivityModelType = await getActivityById(activityId); + if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new BindPhoneData(activityData, createTime, serverTime); + + let links = await LinkModel.findByServerId(serverId); + playerData.setLinks(links); + + let user: UserType; + if(playerData.bindPhone) { + if(!user) user = await UserModel.findUserByUid(uid); + let receiveRec = await ActivityBindPhoneRewardModel.findByUid(activityId, uid); + playerData.bindPhone.setBindPhoneStatus(user, receiveRec); + } + if(playerData.wxPublicAccount) { + if(!user) user = await UserModel.findUserByUid(uid); + if(user.channelInfo) { + let giftCode = encodeGiftCode(roleId, serverId, user.channelInfo.uid, user.channelInfo.platformAppid, user.channelInfo.childGameId, activityId); + playerData.wxPublicAccount.setEncodeGiftCode(giftCode); + let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, user.channelId); + if(playerRecord) playerData.wxPublicAccount.setPlayerRecord(playerRecord); + } + } + + return playerData; +} + +/** + * 绑定手机相关数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getBindPhoneData(activityId: number, roleId: string, serverId: number, uid: number) { + + let activityData: ActivityModelType = await getActivityById(activityId); + if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new BindPhoneData(activityData, createTime, serverTime); + + let links = await LinkModel.findByServerId(serverId); + playerData.setLinks(links); + + let user: UserType; + if(playerData.bindPhone) { + if(!user) user = await UserModel.findUserByUid(uid); + let receiveRec = await ActivityBindPhoneRewardModel.findByUid(activityId, uid); + playerData.bindPhone.setBindPhoneStatus(user, receiveRec); + } + + return playerData; +} + +/** + * 微信公众号 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPublicAccountData(activityId: number, roleId: string, serverId: number, user: UserType) { + + let activityData: ActivityModelType = await getActivityById(activityId); + if(!activityData || activityData.type != ACTIVITY_TYPE.BIND_PHONE) return null; + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new BindPhoneData(activityData, createTime, serverTime); + + let links = await LinkModel.findByServerId(serverId); + playerData.setLinks(links); + + if(playerData.wxPublicAccount) { + if(user.channelInfo) { + let giftCode = encodeGiftCode(roleId, serverId, user.channelInfo.uid, user.channelInfo.platformAppid, user.channelInfo.childGameId, activityId); + playerData.wxPublicAccount.setEncodeGiftCode(giftCode); + let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, user.channelId); + if(playerRecord) playerData.wxPublicAccount.setPlayerRecord(playerRecord); + } + } + + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getAllSnsLinkDataShow(activityId: number, roleId: string, serverId: number, uid: number) { + let playerData = await getAllSnsLinkData(activityId, roleId, serverId, uid); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +function encodeGiftCode(roleId: string, serverId: number, uid: number, pid: string, gid: string, activityId: number) { + let encodeResult = aes128Encrypt(`${roleId}|${serverId}|${uid}|${pid}|${gid}|${PUBLIC_ACCOUNT_GIFT}${activityId}|${SDK_37_CONST.GIFT_GAME_ID}`, SDK_37_CONST.PUBLIC_GIFT_KEY); + return `FS${encodeResult}`; +} + +export async function sendPublicAccountGift(message: string) { + let [_activityId, userCode, channelId] = message?.split('|')||[]; + let activityId = parseInt(_activityId); + if(!isNumber(activityId) || !userCode || !channelId) return; + + let onlineRoleId = await getOnlineRoleByUserCode(userCode); + // console.log('##### sendPublicAccountGift', message, userCode, onlineRoleId); + if (!!onlineRoleId) { // 在线,推送消息 + let playerRecord = await ActivityPublicAccountCodeModel.findByChannel(activityId, channelId); + await sendMessageToUserWithSuc(onlineRoleId, PUSH_ROUTE.PUBLIC_ACCOUNT_GIFT, { activityId, type: SNS_LINK_TYPE.WX_PUBLIC_ACCOUNT, status: playerRecord.hasReceived? BIND_PHONE_STATUS.RECEIVED: BIND_PHONE_STATUS.HAS_BIND }); + } +} diff --git a/game-server/app/services/activity/chongyangService.ts b/game-server/app/services/activity/chongyangService.ts index 44178862c..600cdff65 100644 --- a/game-server/app/services/activity/chongyangService.ts +++ b/game-server/app/services/activity/chongyangService.ts @@ -1,23 +1,23 @@ -import { ActivityChongYangRecModel } from "../../db/ActivityChongYangRec"; -import { ChongYangData } from "../../domain/activityField/chongyangField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -export async function getPlayerChongYangData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new ChongYangData(activityData, createTime, serverTime); - let playerRecord = await ActivityChongYangRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -export async function getPlayerChongYangDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerChongYangData(activityId, serverId, roleId); - if (playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityChongYangRecModel } from "@db/ActivityChongYangRec"; +import { ChongYangData } from "@domain/activityField/chongyangField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +export async function getPlayerChongYangData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new ChongYangData(activityData, createTime, serverTime); + let playerRecord = await ActivityChongYangRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +export async function getPlayerChongYangDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerChongYangData(activityId, serverId, roleId); + if (playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/dailyChallengesService.ts b/game-server/app/services/activity/dailyChallengesService.ts index 145a6016f..38df52177 100644 --- a/game-server/app/services/activity/dailyChallengesService.ts +++ b/game-server/app/services/activity/dailyChallengesService.ts @@ -1,54 +1,54 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityDailyChallengesModel, ActivityDailyChallengesModelType } from '../../db/ActivityDailyChallenges'; -import { DailyChallengesData } from '../../domain/activityField/dailyChallengesField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function dailyChallengesActivity(serverId: number, roleId: string) { - - let activityDataArray: ActivityModelType[] = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_DAILY_CHALLENGES); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityData.activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyChallengesData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyChallengesData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - let playerRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyChallengesData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - - return playerData; -} - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityDailyChallengesModel, ActivityDailyChallengesModelType } from '@db/ActivityDailyChallenges'; +import { DailyChallengesData } from '@domain/activityField/dailyChallengesField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function dailyChallengesActivity(serverId: number, roleId: string) { + + let activityDataArray: ActivityModelType[] = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_DAILY_CHALLENGES); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityData.activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyChallengesData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyChallengesData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + let playerRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyChallengesData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + + return playerData; +} + + diff --git a/game-server/app/services/activity/dailyCoinService.ts b/game-server/app/services/activity/dailyCoinService.ts index 7e2aeb4e9..e58f1c744 100644 --- a/game-server/app/services/activity/dailyCoinService.ts +++ b/game-server/app/services/activity/dailyCoinService.ts @@ -1,77 +1,77 @@ -import { ACTIVITY_TYPE, MAIL_TYPE, REFRESH_TIME } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityDailyCoinModel, ActivityDailyCoinModelType } from '../../db/ActivityDailyCoin'; -import { ServerlistType } from '../../db/Serverlist'; -import { DailyCoinData } from '../../domain/activityField/dailyCoinField'; -import { RewardInter } from '../../pubUtils/interface'; -import { stringWithTypeToRewardInter } from '../../pubUtils/roleUtil'; -import { sendMailByContent } from '../mailService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyCoinData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyCoinData(activityData, createTime, serverTime); - - let playerRecord: ActivityDailyCoinModelType = await ActivityDailyCoinModel.findData(serverId, activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -export async function sendUnReceivedActivityDailyCoin(servers: ServerlistType[]) { - let today = new Date().setHours(REFRESH_TIME, 0, 0, 0); - let yesterday = today - 86400000; - let unreceivedRecord = await ActivityDailyCoinModel.findUnreceivedBox(new Date(yesterday), new Date(today)); - for(let { serverId } of servers) { - let serverTime = await getServerCreateTime(serverId); - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_COIN); - for(let activityData of activities) { - for(let playerRecord of unreceivedRecord) { - if(playerRecord.activityId != activityData.activityId) continue; - if(playerRecord.serverId != serverId) continue; - await sendUnReceivedRecor(activityData, playerRecord, serverTime); - } - } - } -} - -async function sendUnReceivedRecor(activityData: ActivityModelType, playerRecord: ActivityDailyCoinModelType, serverTime: number) { - let createTime = await getRoleCreateTime(playerRecord.roleId); - - let playerData = new DailyCoinData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - let unreceivedRecord = playerData.getUnReceivedBox(); - if(unreceivedRecord.length > 0) { - let rewards: RewardInter[] = [], boxIds: number[] = []; - for(let { cellIndex, reward } of unreceivedRecord) { - rewards.push(...stringWithTypeToRewardInter(reward)); - boxIds.push(cellIndex); - } - await sendMailByContent(MAIL_TYPE.DAILY_COIN, playerRecord.roleId, { goods: rewards }); - await ActivityDailyCoinModel.repaireBox(playerRecord._id, boxIds); - } -} - -export function mergeData(data: any[]) { - let newDate = []; - for (let item of data) { - let index = newDate.findIndex(obj => { return obj.id === item.id }); - if (index != -1) { - newDate[index].count += item.count; - } else { - newDate = newDate.concat(item); - } - } - return newDate; -} +import { ACTIVITY_TYPE, MAIL_TYPE, REFRESH_TIME } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityDailyCoinModel, ActivityDailyCoinModelType } from '@db/ActivityDailyCoin'; +import { ServerlistType } from '@db/Serverlist'; +import { DailyCoinData } from '@domain/activityField/dailyCoinField'; +import { RewardInter } from '@pubUtils/interface'; +import { stringWithTypeToRewardInter } from '@pubUtils/roleUtil'; +import { sendMailByContent } from '../mailService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyCoinData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyCoinData(activityData, createTime, serverTime); + + let playerRecord: ActivityDailyCoinModelType = await ActivityDailyCoinModel.findData(serverId, activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +export async function sendUnReceivedActivityDailyCoin(servers: ServerlistType[]) { + let today = new Date().setHours(REFRESH_TIME, 0, 0, 0); + let yesterday = today - 86400000; + let unreceivedRecord = await ActivityDailyCoinModel.findUnreceivedBox(new Date(yesterday), new Date(today)); + for(let { serverId } of servers) { + let serverTime = await getServerCreateTime(serverId); + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_COIN); + for(let activityData of activities) { + for(let playerRecord of unreceivedRecord) { + if(playerRecord.activityId != activityData.activityId) continue; + if(playerRecord.serverId != serverId) continue; + await sendUnReceivedRecor(activityData, playerRecord, serverTime); + } + } + } +} + +async function sendUnReceivedRecor(activityData: ActivityModelType, playerRecord: ActivityDailyCoinModelType, serverTime: number) { + let createTime = await getRoleCreateTime(playerRecord.roleId); + + let playerData = new DailyCoinData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + let unreceivedRecord = playerData.getUnReceivedBox(); + if(unreceivedRecord.length > 0) { + let rewards: RewardInter[] = [], boxIds: number[] = []; + for(let { cellIndex, reward } of unreceivedRecord) { + rewards.push(...stringWithTypeToRewardInter(reward)); + boxIds.push(cellIndex); + } + await sendMailByContent(MAIL_TYPE.DAILY_COIN, playerRecord.roleId, { goods: rewards }); + await ActivityDailyCoinModel.repaireBox(playerRecord._id, boxIds); + } +} + +export function mergeData(data: any[]) { + let newDate = []; + for (let item of data) { + let index = newDate.findIndex(obj => { return obj.id === item.id }); + if (index != -1) { + newDate[index].count += item.count; + } else { + newDate = newDate.concat(item); + } + } + return newDate; +} diff --git a/game-server/app/services/activity/dailyGKService.ts b/game-server/app/services/activity/dailyGKService.ts index 7409ec4da..27e30275e 100644 --- a/game-server/app/services/activity/dailyGKService.ts +++ b/game-server/app/services/activity/dailyGKService.ts @@ -1,77 +1,77 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityDailyGKModel, ActivityDailyGKModelType } from '../../db/ActivityDailyGK'; -import { DailyGKData } from '../../domain/activityField/dailyGKField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function dailyGKActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_GK); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerRecord: ActivityDailyGKModelType = await ActivityDailyGKModel.findData(serverId, activityData.activityId, roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyGKData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyGKData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord: ActivityDailyGKModelType = await ActivityDailyGKModel.findData(serverId, activityId, roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyGKData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - - return playerData; -} - -/** - * 挑战每日关卡成功 - * - * @param {number} activityId 活动id - * @param {number} gk 关卡id - * - */ -export async function challengeDailyGK(serverId: number, roleId: string, activityId: number, gk: number) { - let activityData: ActivityModelType = await getActivityById(activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyGKData(activityData, createTime, serverTime); - let item = playerData.findItemByGK(gk); - if (item) { - let dayIndex = item.dayIndex; - await ActivityDailyGKModel.addRecord(serverId, activityId, roleId, dayIndex); - } else { - console.log('没有找到对应关卡活动数据', activityId, gk) - } - - return playerData; -} - - - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityDailyGKModel, ActivityDailyGKModelType } from '@db/ActivityDailyGK'; +import { DailyGKData } from '@domain/activityField/dailyGKField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function dailyGKActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_GK); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerRecord: ActivityDailyGKModelType = await ActivityDailyGKModel.findData(serverId, activityData.activityId, roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyGKData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyGKData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord: ActivityDailyGKModelType = await ActivityDailyGKModel.findData(serverId, activityId, roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyGKData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + + return playerData; +} + +/** + * 挑战每日关卡成功 + * + * @param {number} activityId 活动id + * @param {number} gk 关卡id + * + */ +export async function challengeDailyGK(serverId: number, roleId: string, activityId: number, gk: number) { + let activityData: ActivityModelType = await getActivityById(activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyGKData(activityData, createTime, serverTime); + let item = playerData.findItemByGK(gk); + if (item) { + let dayIndex = item.dayIndex; + await ActivityDailyGKModel.addRecord(serverId, activityId, roleId, dayIndex); + } else { + console.log('没有找到对应关卡活动数据', activityId, gk) + } + + return playerData; +} + + + + diff --git a/game-server/app/services/activity/dailyGiftsService.ts b/game-server/app/services/activity/dailyGiftsService.ts index 0d03df1e5..2887a30b3 100644 --- a/game-server/app/services/activity/dailyGiftsService.ts +++ b/game-server/app/services/activity/dailyGiftsService.ts @@ -1,52 +1,52 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityDailyGiftsModel, ActivityDailyGiftsModelType } from '../../db/ActivityDailyGifts'; -import { DailyGiftsData } from '../../domain/activityField/dailyGiftsField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function dailyGiftsActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_DISCOUNT_GIFT); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityData.activityId, roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyGiftsData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyGiftsData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyGiftsData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - - return playerData; -} - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityDailyGiftsModel, ActivityDailyGiftsModelType } from '@db/ActivityDailyGifts'; +import { DailyGiftsData } from '@domain/activityField/dailyGiftsField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function dailyGiftsActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_DISCOUNT_GIFT); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityData.activityId, roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyGiftsData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyGiftsData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyGiftsData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + + return playerData; +} + + diff --git a/game-server/app/services/activity/dailyMealService.ts b/game-server/app/services/activity/dailyMealService.ts index 3e09b0a03..73092ae68 100644 --- a/game-server/app/services/activity/dailyMealService.ts +++ b/game-server/app/services/activity/dailyMealService.ts @@ -1,54 +1,54 @@ -import { ACTIVITY_TYPE, DAILY_MEAL_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityDailyMealModel, ActivityDailyMealModelType } from '../../db/ActivityDailyMeal'; -import { DailyMealData } from '../../domain/activityField/dailyMealField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function dailyMealActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_MEAL); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyMealData(activityData, createTime, serverTime); - - let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.roundIndex); - let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.roundIndex); - playerData.setPlayerRecords(playerLunchRecords.concat(playerDinnerRecords)); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyMealData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyMealData(activityData, createTime, serverTime); - - let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.roundIndex); - let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.roundIndex); - playerData.setPlayerRecords(playerLunchRecords.concat(playerDinnerRecords)); - return playerData; -} - - +import { ACTIVITY_TYPE, DAILY_MEAL_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityDailyMealModel, ActivityDailyMealModelType } from '@db/ActivityDailyMeal'; +import { DailyMealData } from '@domain/activityField/dailyMealField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function dailyMealActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_MEAL); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyMealData(activityData, createTime, serverTime); + + let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.roundIndex); + let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.roundIndex); + playerData.setPlayerRecords(playerLunchRecords.concat(playerDinnerRecords)); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyMealData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyMealData(activityData, createTime, serverTime); + + let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.roundIndex); + let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.roundIndex); + playerData.setPlayerRecords(playerLunchRecords.concat(playerDinnerRecords)); + return playerData; +} + + diff --git a/game-server/app/services/activity/dailyRMBGiftsService.ts b/game-server/app/services/activity/dailyRMBGiftsService.ts index bc81647bc..b901e25d7 100644 --- a/game-server/app/services/activity/dailyRMBGiftsService.ts +++ b/game-server/app/services/activity/dailyRMBGiftsService.ts @@ -1,133 +1,133 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityDailyRMBGiftsModel, ActivityDailyRMBGiftsModelType } from '../../db/ActivityDailyRMBGifts'; -import { DailyRMBGiftsData } from '../../domain/activityField/dailyRMBGiftsField'; -import moment = require('moment'); -import { RewardParam } from '../../domain/activityField/rewardField'; -import { addReward, stringToRewardParam } from './giftPackageService'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function dailyRMBGiftsActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_RMB_GIFTS); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerData = await getPlayerDailyRMBGiftsData(activityData.activityId, serverId, roleId); - return playerData -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDailyRMBGiftsData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); - let playerRecords: ActivityDailyRMBGiftsModelType[] = await ActivityDailyRMBGiftsModel.findBuyRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex); - - playerData.setPlayerRecords(playerRecords); - return playerData; -} - -/** - * 结算购买礼包的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeDailyRMBGiftsReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (activityData.type !== ACTIVITY_TYPE.DAILY_RMB_GIFTS) { - return { - code: STATUS.ACTIVITY_TYPE_ERROR, - } - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); - let bigGiftProductID = playerData.productID; - if (bigGiftProductID == productID) {//一次性购买7天礼包 - let hasBoughtTomorrow = await ActivityDailyRMBGiftsModel.checkHasBought(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex + 1); - if(hasBoughtTomorrow) return STATUS.ORDER_CANNOT_BUY; - - let playerRecord: ActivityDailyRMBGiftsModelType = await ActivityDailyRMBGiftsModel.findRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex); - playerData.setPlayerRecords(playerRecord?[playerRecord]: []); - if (playerData.shouldbuyNextDay()) {//今天已经购买过其他奖励 - playerData.todayIndex ++; - } - - for (let i = 0; i < playerData.day; i++) { - let todayIndex = playerData.todayIndex + i; - await ActivityDailyRMBGiftsModel.buyRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), todayIndex, true); - } - let endTime = moment(playerData.endTime).add(playerData.day, 'd').toDate() - return { - code: 0, - data: Object.assign({}, { item: { endTime, receiveCount: 0 } }) - } - } else { - let item = playerData.findProduct(productID); - if (!item) return STATUS.ACTIVITY_NO_PRODUCT; - let hasReceived = await ActivityDailyRMBGiftsModel.checkHasReceive(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, item.id); - if(hasReceived) { - return STATUS.ORDER_CANNOT_BUY - } - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_RMB_GIFT) - await ActivityDailyRMBGiftsModel.receiveRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, [item.id]); - item.isReceive = true; - return { - code: 0, - data: Object.assign(result, { item }) - } - } -} - - -/** - * 检查每日特惠是否可以购买 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function checkDailyRMBGifts(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); - let bigGiftProductID = playerData.productID; - if (bigGiftProductID == productID) {//一次性购买7天礼包 - let hasBoughtTomorrow = await ActivityDailyRMBGiftsModel.checkHasBought(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex + 1); - return !hasBoughtTomorrow; - } else { - let item = playerData.findProduct(productID); - if (!item) return false - let hasReceived = await ActivityDailyRMBGiftsModel.checkHasReceive(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, item.id); - return !hasReceived; - } -} +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityDailyRMBGiftsModel, ActivityDailyRMBGiftsModelType } from '@db/ActivityDailyRMBGifts'; +import { DailyRMBGiftsData } from '@domain/activityField/dailyRMBGiftsField'; +import moment = require('moment'); +import { RewardParam } from '@domain/activityField/rewardField'; +import { addReward, stringToRewardParam } from './giftPackageService'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function dailyRMBGiftsActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_RMB_GIFTS); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerData = await getPlayerDailyRMBGiftsData(activityData.activityId, serverId, roleId); + return playerData +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDailyRMBGiftsData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); + let playerRecords: ActivityDailyRMBGiftsModelType[] = await ActivityDailyRMBGiftsModel.findBuyRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex); + + playerData.setPlayerRecords(playerRecords); + return playerData; +} + +/** + * 结算购买礼包的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeDailyRMBGiftsReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (activityData.type !== ACTIVITY_TYPE.DAILY_RMB_GIFTS) { + return { + code: STATUS.ACTIVITY_TYPE_ERROR, + } + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); + let bigGiftProductID = playerData.productID; + if (bigGiftProductID == productID) {//一次性购买7天礼包 + let hasBoughtTomorrow = await ActivityDailyRMBGiftsModel.checkHasBought(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex + 1); + if(hasBoughtTomorrow) return STATUS.ORDER_CANNOT_BUY; + + let playerRecord: ActivityDailyRMBGiftsModelType = await ActivityDailyRMBGiftsModel.findRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex); + playerData.setPlayerRecords(playerRecord?[playerRecord]: []); + if (playerData.shouldbuyNextDay()) {//今天已经购买过其他奖励 + playerData.todayIndex ++; + } + + for (let i = 0; i < playerData.day; i++) { + let todayIndex = playerData.todayIndex + i; + await ActivityDailyRMBGiftsModel.buyRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), todayIndex, true); + } + let endTime = moment(playerData.endTime).add(playerData.day, 'd').toDate() + return { + code: 0, + data: Object.assign({}, { item: { endTime, receiveCount: 0 } }) + } + } else { + let item = playerData.findProduct(productID); + if (!item) return STATUS.ACTIVITY_NO_PRODUCT; + let hasReceived = await ActivityDailyRMBGiftsModel.checkHasReceive(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, item.id); + if(hasReceived) { + return STATUS.ORDER_CANNOT_BUY + } + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.DAILY_RMB_GIFT) + await ActivityDailyRMBGiftsModel.receiveRecord(serverId, activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, [item.id]); + item.isReceive = true; + return { + code: 0, + data: Object.assign(result, { item }) + } + } +} + + +/** + * 检查每日特惠是否可以购买 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function checkDailyRMBGifts(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DailyRMBGiftsData(activityData, createTime, serverTime); + let bigGiftProductID = playerData.productID; + if (bigGiftProductID == productID) {//一次性购买7天礼包 + let hasBoughtTomorrow = await ActivityDailyRMBGiftsModel.checkHasBought(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex + 1); + return !hasBoughtTomorrow; + } else { + let item = playerData.findProduct(productID); + if (!item) return false + let hasReceived = await ActivityDailyRMBGiftsModel.checkHasReceive(serverId, activityData.activityId, roleId, moment(playerData.beginTime).toDate(), playerData.todayIndex, item.id); + return !hasReceived; + } +} diff --git a/game-server/app/services/activity/dragonBoatService.ts b/game-server/app/services/activity/dragonBoatService.ts index f42a00fc6..7f2a3e482 100644 --- a/game-server/app/services/activity/dragonBoatService.ts +++ b/game-server/app/services/activity/dragonBoatService.ts @@ -1,38 +1,38 @@ -import { ActivityDragonBoatModel } from "../../db/ActivityDragonBoat"; -import { DragonBoatData } from "../../domain/activityField/dragonBoatField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDragonBoatData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new DragonBoatData(activityData, createTime, serverTime); - let playerRecord = await ActivityDragonBoatModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerDragonBoatDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityDragonBoatModel } from "@db/ActivityDragonBoat"; +import { DragonBoatData } from "@domain/activityField/dragonBoatField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDragonBoatData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new DragonBoatData(activityData, createTime, serverTime); + let playerRecord = await ActivityDragonBoatModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerDragonBoatDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerDragonBoatData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/entertainService.ts b/game-server/app/services/activity/entertainService.ts index a5f8b2b37..4d922eb22 100644 --- a/game-server/app/services/activity/entertainService.ts +++ b/game-server/app/services/activity/entertainService.ts @@ -1,38 +1,38 @@ -import { ActivityEntertainRecModel } from "../../db/ActivityEntertainRec"; -import { EntertainData } from "../../domain/activityField/entertainField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerEntertainData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new EntertainData(activityData, createTime, serverTime); - let playerRecord = await ActivityEntertainRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerEntertainDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerEntertainData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityEntertainRecModel } from "@db/ActivityEntertainRec"; +import { EntertainData } from "@domain/activityField/entertainField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerEntertainData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new EntertainData(activityData, createTime, serverTime); + let playerRecord = await ActivityEntertainRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerEntertainDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerEntertainData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/firstGiftService.ts b/game-server/app/services/activity/firstGiftService.ts index 2877d746d..b60f12d31 100644 --- a/game-server/app/services/activity/firstGiftService.ts +++ b/game-server/app/services/activity/firstGiftService.ts @@ -1,88 +1,88 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityFirstGiftModel, ActivityFirstGiftModelType } from '../../db/ActivityFirstGift'; -import { RoleModel, RoleType } from '../../db/Role'; -import { ServerlistModel } from '../../db/Serverlist'; -import { FirstGiftData } from '../../domain/activityField/firstGiftField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - -// /** -// * 获取活动数据 -// * -// * @param {number} serverId 区Id -// * @param {number} type 活动类型 ACTIVITY_TYPE -// * @param {string} roleId 角色Id -// * -// */ - -// export async function firstGiftActivity(serverId: number, roleId: string) { -// let { activityGroupId } = await ServerlistModel.findByServerId(serverId); -// let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, ACTIVITY_TYPE.FIRST_GIFT, 1) - -// if (activityArray.length == 0) { -// return null; -// } -// let activityData = activityArray[0]; -// let playerRecord: ActivityFirstGiftModelType = await ActivityFirstGiftModel.findData(activityData.activityId, roleId); -// if (!playerRecord || playerRecord.isOver) { -// return null; -// } - -// let { createTime } = await RoleModel.findByRoleId(roleId); -// let playerData = new FirstGiftData(activityData, createTime); -// playerData.setPlayerRecords(playerRecord); -// return playerData; -// } - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerFirstGiftData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord = await ActivityFirstGiftModel.findData(activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new FirstGiftData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 获取可显示的数据 - * @param activityId - * @param serverId - * @param roleId - * @returns - */ -export async function getPlayerFirstGiftDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerFirstGiftData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -/** - * 记录玩家首充记录 - * @param {RoleType} role 玩家数据 - * @param {number} serverId 区id - */ -export async function recordFirstGift(role: RoleType, serverId: number) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.FIRST_GIFT); - let serverTime = await getServerCreateTime(serverId); - for (let obj of activities) { - let playerData = new FirstGiftData(obj, role.createTime, serverTime); - for(let { pageIndex, targetMoney } of playerData.list) { - if(role.totalPay >= targetMoney) { - await ActivityFirstGiftModel.begin(obj.activityId, role.roleId, pageIndex ); - } - } - } -} +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityFirstGiftModel, ActivityFirstGiftModelType } from '@db/ActivityFirstGift'; +import { RoleModel, RoleType } from '@db/Role'; +import { ServerlistModel } from '@db/Serverlist'; +import { FirstGiftData } from '@domain/activityField/firstGiftField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + +// /** +// * 获取活动数据 +// * +// * @param {number} serverId 区Id +// * @param {number} type 活动类型 ACTIVITY_TYPE +// * @param {string} roleId 角色Id +// * +// */ + +// export async function firstGiftActivity(serverId: number, roleId: string) { +// let { activityGroupId } = await ServerlistModel.findByServerId(serverId); +// let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, ACTIVITY_TYPE.FIRST_GIFT, 1) + +// if (activityArray.length == 0) { +// return null; +// } +// let activityData = activityArray[0]; +// let playerRecord: ActivityFirstGiftModelType = await ActivityFirstGiftModel.findData(activityData.activityId, roleId); +// if (!playerRecord || playerRecord.isOver) { +// return null; +// } + +// let { createTime } = await RoleModel.findByRoleId(roleId); +// let playerData = new FirstGiftData(activityData, createTime); +// playerData.setPlayerRecords(playerRecord); +// return playerData; +// } + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerFirstGiftData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord = await ActivityFirstGiftModel.findData(activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new FirstGiftData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 获取可显示的数据 + * @param activityId + * @param serverId + * @param roleId + * @returns + */ +export async function getPlayerFirstGiftDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerFirstGiftData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +/** + * 记录玩家首充记录 + * @param {RoleType} role 玩家数据 + * @param {number} serverId 区id + */ +export async function recordFirstGift(role: RoleType, serverId: number) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.FIRST_GIFT); + let serverTime = await getServerCreateTime(serverId); + for (let obj of activities) { + let playerData = new FirstGiftData(obj, role.createTime, serverTime); + for(let { pageIndex, targetMoney } of playerData.list) { + if(role.totalPay >= targetMoney) { + await ActivityFirstGiftModel.begin(obj.activityId, role.roleId, pageIndex ); + } + } + } +} diff --git a/game-server/app/services/activity/forgeService.ts b/game-server/app/services/activity/forgeService.ts index 4707d5997..cb9192a97 100644 --- a/game-server/app/services/activity/forgeService.ts +++ b/game-server/app/services/activity/forgeService.ts @@ -1,42 +1,42 @@ -import { ActivityForgeModel } from "../../db/ActivityForge"; -import { ForgeData } from "../../domain/activityField/forgeField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerForgeData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new ForgeData(activityData, createTime, serverTime); - let playerRecords = await ActivityForgeModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerForgeDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerForgeData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -export function getMetialStr(material: { id: number, count: number }[]) { - return material.map(({id, count}) => `${id}&${count}`).join('|') -} \ No newline at end of file +import { ActivityForgeModel } from "@db/ActivityForge"; +import { ForgeData } from "@domain/activityField/forgeField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerForgeData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new ForgeData(activityData, createTime, serverTime); + let playerRecords = await ActivityForgeModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerForgeDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerForgeData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +export function getMetialStr(material: { id: number, count: number }[]) { + return material.map(({id, count}) => `${id}&${count}`).join('|') +} diff --git a/game-server/app/services/activity/gachaService.ts b/game-server/app/services/activity/gachaService.ts index 037d2da1b..e78a31d01 100644 --- a/game-server/app/services/activity/gachaService.ts +++ b/game-server/app/services/activity/gachaService.ts @@ -1,583 +1,583 @@ -import { Floor as UserFloor, Hope as UserHope, GachaListReturn, GachaResultIndb } from "../../domain/activityField/gachaField";; -import { DicGacha } from "../../pubUtils/dictionary/DicGacha"; -import { UserGachaType, UserGachaModel } from "../../db/UserGacha"; -import { shouldRefresh, getRandEelm, getRandEelmWithWeight, getRandSingleIndex, getRandSingleEelm } from "../../pubUtils/util"; -import { REFRESH_TIME, GACHA_FLOOR_TYPE, HERO_QUALITY_TYPE, IT_TYPE, ITID, CONSUME_TYPE, SPECIAL_ATTR, TIME_OUTPUT_TYPE, GACHA_TYPE, GACHA_PLAN_TYPE } from "../../consts"; -import { getTimeFunD, getZeroPointD } from "../../pubUtils/timeUtil"; -import { gameData } from "../../pubUtils/data"; -import { RewardInter } from "../../pubUtils/interface"; -import { CreateHeroParam } from "../../domain/roleField/hero"; -import { HeroType } from "../../db/Hero"; -import { getActivityById } from "./activityService"; -import { transPiece } from "../role/util"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { SimpleResult, GuideGachaData } from "../../domain/activityField/guideGachaField"; -import { isGoodsHidden, isHeroHidden } from "../dataService"; - -/** - * 获取招募列表 - * @param roleId - */ -export async function getGachaList(roleId: string) { - let userGachaList = await UserGachaModel.findAllByRole(roleId); - let list: GachaListReturn[] = []; - for (let [id, dicGacha] of gameData.gacha) { - if(!dicGacha.showInMainPage) continue; - - let userGacha = userGachaList.find(cur => cur.gachaId == id); - if (userGacha) - userGacha = await refreshGacha(dicGacha, userGacha); - dicGacha = getDicGachaByGachaCnt(dicGacha, userGacha?.count||0); - - let param = new GachaListReturn(dicGacha, userGacha); - list.push(param); - } - return list; -} - -export function getNormalGachaId() { - let ids = gameData.gachaByType.get(GACHA_TYPE.NORMAL); - return ids.find(gachaId => gameData.gacha.get(gachaId)?.showInMainPage == 1); -} - -/** - * 刷新免费次数 - * @param dicGacha - * @param userGacha - */ -export async function refreshGacha(dicGacha: DicGacha, userGacha: UserGachaType) { - let { day, count } = dicGacha.free; - - let { roleId, gachaId, refFreeTime, refHopeTime, hope } = userGacha; - if (count > 0 && shouldRefresh(refFreeTime, new Date(), REFRESH_TIME, day)) { - let ref = getTimeFunD().getAfterDayByGap(refFreeTime, day); - userGacha = await UserGachaModel.refreshFreeCount(roleId, gachaId, 0, ref); - } - if (needRefreshHope(dicGacha.gachaType) && shouldRefresh(refHopeTime, new Date(), REFRESH_TIME)) { - hope = hope.map(cur => { return { ...cur, hasGet: false } }); - let ref = getZeroPointD(); - userGacha = await UserGachaModel.refreshHopeCount(roleId, gachaId, 0, hope, ref); - } - return userGacha -} - -function needRefreshHope(gachaType: GACHA_TYPE) { - switch (gachaType) { - case GACHA_TYPE.NORMAL: return true; - case GACHA_TYPE.ARTIFACT: return true; - } - return false; -} - - -export async function getVisitedHeroList(roleId: string) { - let gachaId = getNormalGachaId(); - let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, gachaId, 0); - if (shouldRefresh(refVisitedTime, new Date())) { - visitedHero = []; - } - - return visitedHero; -} - -class PlayerGachaRecord { - public lv: number; // 玩家等级 - public hope: UserHope[] = []; // 玩家记录的心愿单达成情况 - public floor: UserFloor[] = []; - public pickHero: number = 0; - - public setUserGacha(floor: UserFloor[], hope: UserHope[], pickHero: number ) { - this.floor = floor; - this.hope = hope; - this.pickHero = pickHero; - } - - public getFloorCountById(id: number) { - let userFloor = this.floor.find(cur => cur.id == id); - if(userFloor) { - return { floorCount: userFloor.count, hasGetFloor: userFloor.hasGetFloor } - } else { - return { floorCount: 0, hasGetFloor: false } - } - } - - public setFloorCount(id: number, count: number, hasGetFloor: boolean) { - let index = this.floor.findIndex(cur => cur.id == id); - if(index == -1) { - this.floor.push({ id, count, hasGetFloor }) - } else { - this.floor[index].count = count; - this.floor[index].hasGetFloor = hasGetFloor; - } - } - - public getHopeHero(randHopePosition: number) { - let userHope = this.hope.find(cur => cur.id == randHopePosition); - if(!userHope || userHope.hasGet) return 0; - return userHope.hid||0; - } - - public setUserHope(hid: number) { - if(hid <= 0) return; - let userHope = this.hope.find(cur => cur.hid == hid); - if(userHope && !userHope.hasGet) userHope.hasGet = true; - } - - public getUserGachaParam() { - return { hope: this.hope, floor: this.floor } - } -} - -export class GachaResult { - planId: number = 0; // 计划id - hid: number = 0; // 武将id - isTransfer: boolean = false; // 是否转换为碎片 - id: number = 0; // 道具id - count: number = 0; // 道具数量 - pickHero: number = 0; // 玩家选择的武将 - heroQuality: number = 0; // planId对应的武将品质 - - constructor(planId: number) { - this.planId = planId; - this.heroQuality = gameData.gachaPlanQuality.get(planId); - } - - public changePlan(planId: number, heroQuality: number) { - this.planId = planId; - this.heroQuality = heroQuality; - } - - public isTarget(floor: GachaFloor) { - return floor.heroQuality == this.heroQuality; - } - - public setHero(hid: number, count: number) { - this.hid = hid; - this.count = count; - } - - public setItem(id: number, count: number) { - this.id = id; - if(count) this.count = count; - } -} - -export class GachaResults { - count: number = 0; - list: GachaResult[] = []; - - public addPlan(planId: number) { - this.count++; - this.list.push(new GachaResult(planId)); - } - - public addBySimpleResult(simpleResult: SimpleResult[]) { - for(let { planId, hid } of simpleResult) { - let gachaResult = new GachaResult(planId); - gachaResult.setHero(hid, 1); - this.list.push(gachaResult); - } - } - - public getTargetCnt(floor: GachaFloor) { - let target = this.list.filter(cur => cur.heroQuality == floor.heroQuality); - return target.length; - } - - public getRandomResultOfTarget(floor: GachaFloor, cnt: number) { - let target = this.list.filter(cur => cur.heroQuality == floor.heroQuality); - let targetRemoveLast = target.slice(0, cnt + 1); - return getRandEelm(targetRemoveLast, cnt); - } - - // 具体的卡池 - public processDetail(pickHero?: number, count?: number) { - for(let gachaResult of this.list) { - let detail = this.getRandomDetail(gachaResult.planId); - if(!detail) continue; - - switch(detail.type) { - case GACHA_PLAN_TYPE.HERO: - gachaResult.setHero(detail.content, count||1); - break; - case GACHA_PLAN_TYPE.ASSIGN_HERO: - gachaResult.setHero(pickHero, getPickHeroCnt(pickHero)); - break; - case GACHA_PLAN_TYPE.ITEM: - gachaResult.setItem(detail.content, detail.count); - break; - case GACHA_PLAN_TYPE.ASSIGN_ITEM: - gachaResult.setItem(getPickHeroPiece(pickHero), detail.count); - break; - } - } - } - - private getRandomDetail(planId: number) { - let details = (gameData.gachaPlan.get(planId)||[]).filter(detail => { - switch(detail.type) { - case GACHA_PLAN_TYPE.HERO: - return !isHeroHidden(detail.content); - case GACHA_PLAN_TYPE.ITEM: - return !isGoodsHidden(detail.content); - case GACHA_PLAN_TYPE.ASSIGN_HERO: - case GACHA_PLAN_TYPE.ASSIGN_ITEM: - return true; - } - }); - let { dic } = getRandEelmWithWeight(details); - return dic - } - - public transferToFinalResult(userHeroes: HeroType[]) { - let hids = userHeroes.map(cur => cur.hid); - let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = []; - let newResult: GachaResultIndb[] = []; - for (let result of this.list) { - if (result.hid > 0) { - for(let i = 0; i < result.count; i++) { - newResult.push(new GachaResultIndb(result)); - } - } else { - newResult.push(new GachaResultIndb(result)); - } - } - - for(let result of newResult) { - if (result.hid > 0) { - let hasHero = hids.indexOf(result.hid) != -1; - if (hasHero) { // 已有转换为碎片 - let { pieceId, count } = transPiece(result.hid); - result.transferToPiece(pieceId, count); - items.push({ id: pieceId, count }); - } else { - heroInfo.push({ hid: result.hid, count: 1 })//默认1个英雄 - hids.push(result.hid); - } - } else { - items.push({ id: result.id, count: result.count }); - } - } - - return { items, heroInfo, resultList: newResult } - } - - -} - -class GachaPlan { - index: number; - planId: number; - weight: number; - heroQuality: number; - - constructor(planId: number, weight: number, index: number) { - this.planId = planId; - this.weight = weight; - this.index = index; - this.heroQuality = gameData.gachaPlanQuality.get(planId); - } -} - -class GachaPercent { - percents: GachaPlan[] = []; - - constructor(percent: { planId: number, weight: number }[]) { - for(let i = 1; i <= percent.length; i++) { - let { planId, weight } = percent[i - 1]; - this.percents.push(new GachaPlan(planId, weight, i)); - } - } - - public getRandomPlan() { - let { dic } = getRandEelmWithWeight(this.percents); - return dic - } - - public getReplacePlan(heroQuality: number, isLower: boolean) { - // 低一级顺序按 heroQuality: -1 => weight: 1 => index: -1 排序拿最前面那个 - // 高一级顺序按 heroQuality: 1 => weight: -1 => index: 1 排序最前面那个 - let arr = this.percents.filter(plan => { - return isLower? plan.heroQuality < heroQuality: plan.heroQuality > heroQuality; - }).sort((a, b) => { - if(a.heroQuality != b.heroQuality) { - return isLower? b.heroQuality - a.heroQuality: a.heroQuality - b.heroQuality; - } else if(a.weight != b.weight) { - return isLower? a.weight - b.weight: b.weight - a.weight; - } else { - return isLower? b.index - a.index: a.index - b.index; - } - }); - return arr[0]; - } - - public getFloorTarget(heroQuality: number) { - let arr = this.percents.filter(plan => plan.heroQuality == heroQuality).sort((a, b) => { - if(a.weight != b.weight) { - return a.weight - b.weight; - } else { - return b.index - a.index; - } - }); - return arr[0]; - } -} - -class GachaFloor { - id: number; - floorType: GACHA_FLOOR_TYPE; - heroQuality: number; - param: number; - param2: number = 0; - - constructor(id: number) { - let dicGachaFloor = gameData.gachaFloor.get(id); - if(dicGachaFloor) { - this.id = dicGachaFloor.id; - this.floorType = dicGachaFloor.floorType; - this.heroQuality = dicGachaFloor.heroQuality; - this.param = dicGachaFloor.param; - if(dicGachaFloor.floorType == GACHA_FLOOR_TYPE.TEN_MOST_HIGHER || dicGachaFloor.floorType == GACHA_FLOOR_TYPE.TEN_MOST_LOWER) { - this.param2 = 10; - } else if(dicGachaFloor.floorType == GACHA_FLOOR_TYPE.FIVE_MOST_LOWER) { - this.param2 = 5; - } - - } - } - - isReplaceLower() { - return [ - GACHA_FLOOR_TYPE.MAIN_FLOOR, - GACHA_FLOOR_TYPE.ONLY_ONE, - GACHA_FLOOR_TYPE.TEN_MOST_LOWER, - GACHA_FLOOR_TYPE.FIVE_MOST_LOWER, - ].indexOf(this.floorType) != -1 - } -} - -/** - * 抽卡方法 - */ -export class GachaPull { - private gachaType: GACHA_TYPE; // 抽卡类型 - // 字典 - private floors: GachaFloor[] = []; // 保底次数 - private percent: GachaPercent; - // 玩家数据 - private player: PlayerGachaRecord = new PlayerGachaRecord(); - // 结果 - private result = new GachaResults(); - - constructor(dicGacha: DicGacha, userGacha?: { floor: UserFloor[], hope: UserHope[], pickHero: number }) { - this.gachaType = dicGacha.gachaType; - this.percent = new GachaPercent(dicGacha.percent); - if(userGacha) - this.player.setUserGacha(userGacha.floor, userGacha.hope, userGacha.pickHero); - for(let id of dicGacha.floor) { - let floor = new GachaFloor(id); - if(floor && floor.id) this.floors.push(floor); - } - } - - public pull(count: number, userHeroes: HeroType[]) { - this.pullContent(count); - this.processFloors(); - this.result.processDetail(this.player.pickHero); - this.processHope(); - let { heroInfo, items, resultList } = this.getFinalResult(userHeroes) - return { resultList, heroInfo, items }; - } - - // 根据基础的percent抽基地 - private pullContent(count: number) { - for (let i = 0; i < count; i++) { - // 按照一般概率抽出 - let dic = this.percent.getRandomPlan(); - if(dic) this.result.addPlan(dic.planId); - } - } - - // 保底 - private processFloors() { - for(let floor of this.floors) { - switch(floor.floorType) { - case GACHA_FLOOR_TYPE.MAIN_FLOOR: - this.setMainFloor(floor); - break; - case GACHA_FLOOR_TYPE.ONLY_ONE: - this.setAssignFloor(floor); - break; - case GACHA_FLOOR_TYPE.TEN_MOST_HIGHER: - case GACHA_FLOOR_TYPE.TEN_MOST_LOWER: - case GACHA_FLOOR_TYPE.FIVE_MOST_LOWER: - this.setTenMostFloor(floor); - break; - } - } - } - - // 元宝招募保底,金将保底,按次数给保底,抽到就重新计算次数,单抽也算 - private setMainFloor(floor: GachaFloor) { - let { floorCount: historyCount } = this.player.getFloorCountById(floor.id); - for(let gachaResult of this.result.list) { - if(++historyCount >= floor.param || gachaResult.isTarget(floor)) { - let replacePlan = this.percent.getFloorTarget(floor.heroQuality); - if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); - historyCount = 0; - } - } - this.player.setFloorCount(floor.id, historyCount, false); - } - - // 求贤若渴,和活动抽卡金色保底,伪随机,n次内给且只给一个,单抽也算 - public setAssignFloor(floor: GachaFloor) { - let { floorCount: historyCount, hasGetFloor } = this.player.getFloorCountById(floor.id); - for(let gachaResult of this.result.list) { - if(++historyCount >= floor.param || gachaResult.isTarget(floor)) { - if(hasGetFloor) { // 已经获得过一次保底了, 不给,换个给 - let replacePlan = this.percent.getReplacePlan(gachaResult.heroQuality, floor.isReplaceLower()); - if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); - } else { // 设置为保底 - let replacePlan = this.percent.getFloorTarget(floor.heroQuality); - - if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); - hasGetFloor = true; - } - } - if(historyCount >= floor.param) { - hasGetFloor = false; - historyCount = 0; - } - } - this.player.setFloorCount(floor.id, historyCount, hasGetFloor); - } - - - // 10连最多多少个武将 - private setTenMostFloor(floor: GachaFloor) { - let targetCnt = this.result.getTargetCnt(floor); - if(this.result.count == floor.param2 && targetCnt > floor.param) { - let gachaResults = this.result.getRandomResultOfTarget(floor, targetCnt - floor.param); - for(let gachaResult of gachaResults) { - let replacePlan = this.percent.getReplacePlan(gachaResult.heroQuality, floor.isReplaceLower()); - if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality) - } - } - } - - // 心愿单 - private processHope() { - if(this.gachaType != GACHA_TYPE.NORMAL && this.gachaType != GACHA_TYPE.ARTIFACT) return; - for(let gachaResult of this.result.list) { - if(this.gachaType == GACHA_TYPE.NORMAL && gachaResult.heroQuality != HERO_QUALITY_TYPE.GOLD) continue; // 只有橙将 - if(this.gachaType == GACHA_TYPE.ARTIFACT && gachaResult.heroQuality != HERO_QUALITY_TYPE.UR) continue; // 只有橙将 - let { dic: { id: randHopePosition } } = getRandEelmWithWeight(gameData.gachaHope); - if(randHopePosition > 0) { // 按玩家设置的心愿单塞 - let hopeHero = this.player.getHopeHero(randHopePosition) - if(hopeHero > 0) { - if (this.gachaType == GACHA_TYPE.NORMAL) gachaResult.setHero(hopeHero, 1); - if (this.gachaType == GACHA_TYPE.ARTIFACT) gachaResult.setItem(hopeHero, 1); - } - } - if (this.gachaType == GACHA_TYPE.NORMAL) this.player.setUserHope(gachaResult.hid); // 设置心愿单中了没有 - if (this.gachaType == GACHA_TYPE.ARTIFACT) this.player.setUserHope(gachaResult.id); // 设置心愿单中了没有 - } - } - - // 创建信息 - public getFinalResult(userHeroes: HeroType[]) { - return this.result.transferToFinalResult(userHeroes); - } - - // 获得需要储存的数据 - // 一般抽卡getter - public getUserGachaParam() { - return this.player.getUserGachaParam() - } - - public clear() { - this.floors = undefined; - this.percent = undefined; - this.player = undefined; - this.result = undefined; - } -} - -/** - * 根据品质获得武将池 - * @param quality 品质 - */ -export function getAllHeroByQuality(quality: number) { - let allHero: number[] = []; - let allQuality: number[] = []; - for (let [actorId] of gameData.recruit) { - let dicHero = gameData.hero.get(actorId); - if (dicHero.quality == quality) { - allHero.push(actorId); - } - if (allQuality.indexOf(dicHero.quality) == -1) allQuality.push(dicHero.quality); - } - allQuality.sort((a, b) => a - b); - if (allQuality.length == 0) return []; - if (allHero.length == 0) { - allHero = getAllHeroByQuality(allQuality[0]); - } - return allHero; -} - -function getPickHeroCnt(hid: number) { - let dicHero = gameData.hero.get(hid); - let cnt = gameData.gachaPickHeroCnt.get(dicHero?.quality)||0; - return cnt -} - -function getPickHeroPiece(hid: number) { - let dicHero = gameData.hero.get(hid); - return dicHero?.pieceId??0 -} - -export function getDicGachaByGachaCnt(dicGacha: DicGacha, historyCount: number) { - if(isGachaCntIn(historyCount, dicGacha.gachaCnt.min, dicGacha.gachaCnt.max)) { - return dicGacha; - } - let gachaIds = gameData.gachaByType.get(dicGacha.gachaType); - for(let gachaId of gachaIds) { - let newDicGacha = gameData.gacha.get(gachaId); - if(isGachaCntIn(historyCount, newDicGacha.gachaCnt.min, newDicGacha.gachaCnt.max)) { - return {...newDicGacha, id: dicGacha.id}; - } - } - return null -} - -export function getDicGachas(gachaType: number, historyCount: number, count: number) { - let dics: { dic: DicGacha, min: number, max: number }[] = []; - let gachaIds = gameData.gachaByType.get(gachaType); - for(let gachaId of gachaIds) { - let dicGacha = gameData.gacha.get(gachaId); - if(!dicGacha || (dicGacha.gachaCnt.min > dicGacha.gachaCnt.max && dicGacha.gachaCnt.max != -1)) continue; - if((dicGacha.gachaCnt.max != -1 && dicGacha.gachaCnt.max <= historyCount) || dicGacha.gachaCnt.min > historyCount + count) continue; // dic的范围不包含 - let min = dicGacha.gachaCnt.min > historyCount + 1? dicGacha.gachaCnt.min: historyCount + 1; - let max = (dicGacha.gachaCnt.max == -1 || dicGacha.gachaCnt.max > historyCount + count)? historyCount + count: dicGacha.gachaCnt.max; - dics.push({ dic: dicGacha, min, max }); - } - return dics.sort((a, b) => a.min - b.min); -} - -function isGachaCntIn(historyCount: number, min: number, max: number) { - let nowCnt = historyCount + 1; - return min <= nowCnt && (max >= nowCnt || max == -1); -} - - -export async function getGuideGachaData(serverId: number, activityId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GuideGachaData(activityData, createTime, serverTime); - let userGacha = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); - playerData.setPlayerData(userGacha); - if(playerData.hasChoosen || playerData.neverChoose()) return null; - return playerData; -} \ No newline at end of file +import { Floor as UserFloor, Hope as UserHope, GachaListReturn, GachaResultIndb } from "@domain/activityField/gachaField";; +import { DicGacha } from "@pubUtils/dictionary/DicGacha"; +import { UserGachaType, UserGachaModel } from "@db/UserGacha"; +import { shouldRefresh, getRandEelm, getRandEelmWithWeight, getRandSingleIndex, getRandSingleEelm } from "@pubUtils/util"; +import { REFRESH_TIME, GACHA_FLOOR_TYPE, HERO_QUALITY_TYPE, IT_TYPE, ITID, CONSUME_TYPE, SPECIAL_ATTR, TIME_OUTPUT_TYPE, GACHA_TYPE, GACHA_PLAN_TYPE } from "@consts"; +import { getTimeFunD, getZeroPointD } from "@pubUtils/timeUtil"; +import { gameData } from "@pubUtils/data"; +import { RewardInter } from "@pubUtils/interface"; +import { CreateHeroParam } from "@domain/roleField/hero"; +import { HeroType } from "@db/Hero"; +import { getActivityById } from "./activityService"; +import { transPiece } from "../role/util"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { SimpleResult, GuideGachaData } from "@domain/activityField/guideGachaField"; +import { isGoodsHidden, isHeroHidden } from "../dataService"; + +/** + * 获取招募列表 + * @param roleId + */ +export async function getGachaList(roleId: string) { + let userGachaList = await UserGachaModel.findAllByRole(roleId); + let list: GachaListReturn[] = []; + for (let [id, dicGacha] of gameData.gacha) { + if(!dicGacha.showInMainPage) continue; + + let userGacha = userGachaList.find(cur => cur.gachaId == id); + if (userGacha) + userGacha = await refreshGacha(dicGacha, userGacha); + dicGacha = getDicGachaByGachaCnt(dicGacha, userGacha?.count||0); + + let param = new GachaListReturn(dicGacha, userGacha); + list.push(param); + } + return list; +} + +export function getNormalGachaId() { + let ids = gameData.gachaByType.get(GACHA_TYPE.NORMAL); + return ids.find(gachaId => gameData.gacha.get(gachaId)?.showInMainPage == 1); +} + +/** + * 刷新免费次数 + * @param dicGacha + * @param userGacha + */ +export async function refreshGacha(dicGacha: DicGacha, userGacha: UserGachaType) { + let { day, count } = dicGacha.free; + + let { roleId, gachaId, refFreeTime, refHopeTime, hope } = userGacha; + if (count > 0 && shouldRefresh(refFreeTime, new Date(), REFRESH_TIME, day)) { + let ref = getTimeFunD().getAfterDayByGap(refFreeTime, day); + userGacha = await UserGachaModel.refreshFreeCount(roleId, gachaId, 0, ref); + } + if (needRefreshHope(dicGacha.gachaType) && shouldRefresh(refHopeTime, new Date(), REFRESH_TIME)) { + hope = hope.map(cur => { return { ...cur, hasGet: false } }); + let ref = getZeroPointD(); + userGacha = await UserGachaModel.refreshHopeCount(roleId, gachaId, 0, hope, ref); + } + return userGacha +} + +function needRefreshHope(gachaType: GACHA_TYPE) { + switch (gachaType) { + case GACHA_TYPE.NORMAL: return true; + case GACHA_TYPE.ARTIFACT: return true; + } + return false; +} + + +export async function getVisitedHeroList(roleId: string) { + let gachaId = getNormalGachaId(); + let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, gachaId, 0); + if (shouldRefresh(refVisitedTime, new Date())) { + visitedHero = []; + } + + return visitedHero; +} + +class PlayerGachaRecord { + public lv: number; // 玩家等级 + public hope: UserHope[] = []; // 玩家记录的心愿单达成情况 + public floor: UserFloor[] = []; + public pickHero: number = 0; + + public setUserGacha(floor: UserFloor[], hope: UserHope[], pickHero: number ) { + this.floor = floor; + this.hope = hope; + this.pickHero = pickHero; + } + + public getFloorCountById(id: number) { + let userFloor = this.floor.find(cur => cur.id == id); + if(userFloor) { + return { floorCount: userFloor.count, hasGetFloor: userFloor.hasGetFloor } + } else { + return { floorCount: 0, hasGetFloor: false } + } + } + + public setFloorCount(id: number, count: number, hasGetFloor: boolean) { + let index = this.floor.findIndex(cur => cur.id == id); + if(index == -1) { + this.floor.push({ id, count, hasGetFloor }) + } else { + this.floor[index].count = count; + this.floor[index].hasGetFloor = hasGetFloor; + } + } + + public getHopeHero(randHopePosition: number) { + let userHope = this.hope.find(cur => cur.id == randHopePosition); + if(!userHope || userHope.hasGet) return 0; + return userHope.hid||0; + } + + public setUserHope(hid: number) { + if(hid <= 0) return; + let userHope = this.hope.find(cur => cur.hid == hid); + if(userHope && !userHope.hasGet) userHope.hasGet = true; + } + + public getUserGachaParam() { + return { hope: this.hope, floor: this.floor } + } +} + +export class GachaResult { + planId: number = 0; // 计划id + hid: number = 0; // 武将id + isTransfer: boolean = false; // 是否转换为碎片 + id: number = 0; // 道具id + count: number = 0; // 道具数量 + pickHero: number = 0; // 玩家选择的武将 + heroQuality: number = 0; // planId对应的武将品质 + + constructor(planId: number) { + this.planId = planId; + this.heroQuality = gameData.gachaPlanQuality.get(planId); + } + + public changePlan(planId: number, heroQuality: number) { + this.planId = planId; + this.heroQuality = heroQuality; + } + + public isTarget(floor: GachaFloor) { + return floor.heroQuality == this.heroQuality; + } + + public setHero(hid: number, count: number) { + this.hid = hid; + this.count = count; + } + + public setItem(id: number, count: number) { + this.id = id; + if(count) this.count = count; + } +} + +export class GachaResults { + count: number = 0; + list: GachaResult[] = []; + + public addPlan(planId: number) { + this.count++; + this.list.push(new GachaResult(planId)); + } + + public addBySimpleResult(simpleResult: SimpleResult[]) { + for(let { planId, hid } of simpleResult) { + let gachaResult = new GachaResult(planId); + gachaResult.setHero(hid, 1); + this.list.push(gachaResult); + } + } + + public getTargetCnt(floor: GachaFloor) { + let target = this.list.filter(cur => cur.heroQuality == floor.heroQuality); + return target.length; + } + + public getRandomResultOfTarget(floor: GachaFloor, cnt: number) { + let target = this.list.filter(cur => cur.heroQuality == floor.heroQuality); + let targetRemoveLast = target.slice(0, cnt + 1); + return getRandEelm(targetRemoveLast, cnt); + } + + // 具体的卡池 + public processDetail(pickHero?: number, count?: number) { + for(let gachaResult of this.list) { + let detail = this.getRandomDetail(gachaResult.planId); + if(!detail) continue; + + switch(detail.type) { + case GACHA_PLAN_TYPE.HERO: + gachaResult.setHero(detail.content, count||1); + break; + case GACHA_PLAN_TYPE.ASSIGN_HERO: + gachaResult.setHero(pickHero, getPickHeroCnt(pickHero)); + break; + case GACHA_PLAN_TYPE.ITEM: + gachaResult.setItem(detail.content, detail.count); + break; + case GACHA_PLAN_TYPE.ASSIGN_ITEM: + gachaResult.setItem(getPickHeroPiece(pickHero), detail.count); + break; + } + } + } + + private getRandomDetail(planId: number) { + let details = (gameData.gachaPlan.get(planId)||[]).filter(detail => { + switch(detail.type) { + case GACHA_PLAN_TYPE.HERO: + return !isHeroHidden(detail.content); + case GACHA_PLAN_TYPE.ITEM: + return !isGoodsHidden(detail.content); + case GACHA_PLAN_TYPE.ASSIGN_HERO: + case GACHA_PLAN_TYPE.ASSIGN_ITEM: + return true; + } + }); + let { dic } = getRandEelmWithWeight(details); + return dic + } + + public transferToFinalResult(userHeroes: HeroType[]) { + let hids = userHeroes.map(cur => cur.hid); + let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = []; + let newResult: GachaResultIndb[] = []; + for (let result of this.list) { + if (result.hid > 0) { + for(let i = 0; i < result.count; i++) { + newResult.push(new GachaResultIndb(result)); + } + } else { + newResult.push(new GachaResultIndb(result)); + } + } + + for(let result of newResult) { + if (result.hid > 0) { + let hasHero = hids.indexOf(result.hid) != -1; + if (hasHero) { // 已有转换为碎片 + let { pieceId, count } = transPiece(result.hid); + result.transferToPiece(pieceId, count); + items.push({ id: pieceId, count }); + } else { + heroInfo.push({ hid: result.hid, count: 1 })//默认1个英雄 + hids.push(result.hid); + } + } else { + items.push({ id: result.id, count: result.count }); + } + } + + return { items, heroInfo, resultList: newResult } + } + + +} + +class GachaPlan { + index: number; + planId: number; + weight: number; + heroQuality: number; + + constructor(planId: number, weight: number, index: number) { + this.planId = planId; + this.weight = weight; + this.index = index; + this.heroQuality = gameData.gachaPlanQuality.get(planId); + } +} + +class GachaPercent { + percents: GachaPlan[] = []; + + constructor(percent: { planId: number, weight: number }[]) { + for(let i = 1; i <= percent.length; i++) { + let { planId, weight } = percent[i - 1]; + this.percents.push(new GachaPlan(planId, weight, i)); + } + } + + public getRandomPlan() { + let { dic } = getRandEelmWithWeight(this.percents); + return dic + } + + public getReplacePlan(heroQuality: number, isLower: boolean) { + // 低一级顺序按 heroQuality: -1 => weight: 1 => index: -1 排序拿最前面那个 + // 高一级顺序按 heroQuality: 1 => weight: -1 => index: 1 排序最前面那个 + let arr = this.percents.filter(plan => { + return isLower? plan.heroQuality < heroQuality: plan.heroQuality > heroQuality; + }).sort((a, b) => { + if(a.heroQuality != b.heroQuality) { + return isLower? b.heroQuality - a.heroQuality: a.heroQuality - b.heroQuality; + } else if(a.weight != b.weight) { + return isLower? a.weight - b.weight: b.weight - a.weight; + } else { + return isLower? b.index - a.index: a.index - b.index; + } + }); + return arr[0]; + } + + public getFloorTarget(heroQuality: number) { + let arr = this.percents.filter(plan => plan.heroQuality == heroQuality).sort((a, b) => { + if(a.weight != b.weight) { + return a.weight - b.weight; + } else { + return b.index - a.index; + } + }); + return arr[0]; + } +} + +class GachaFloor { + id: number; + floorType: GACHA_FLOOR_TYPE; + heroQuality: number; + param: number; + param2: number = 0; + + constructor(id: number) { + let dicGachaFloor = gameData.gachaFloor.get(id); + if(dicGachaFloor) { + this.id = dicGachaFloor.id; + this.floorType = dicGachaFloor.floorType; + this.heroQuality = dicGachaFloor.heroQuality; + this.param = dicGachaFloor.param; + if(dicGachaFloor.floorType == GACHA_FLOOR_TYPE.TEN_MOST_HIGHER || dicGachaFloor.floorType == GACHA_FLOOR_TYPE.TEN_MOST_LOWER) { + this.param2 = 10; + } else if(dicGachaFloor.floorType == GACHA_FLOOR_TYPE.FIVE_MOST_LOWER) { + this.param2 = 5; + } + + } + } + + isReplaceLower() { + return [ + GACHA_FLOOR_TYPE.MAIN_FLOOR, + GACHA_FLOOR_TYPE.ONLY_ONE, + GACHA_FLOOR_TYPE.TEN_MOST_LOWER, + GACHA_FLOOR_TYPE.FIVE_MOST_LOWER, + ].indexOf(this.floorType) != -1 + } +} + +/** + * 抽卡方法 + */ +export class GachaPull { + private gachaType: GACHA_TYPE; // 抽卡类型 + // 字典 + private floors: GachaFloor[] = []; // 保底次数 + private percent: GachaPercent; + // 玩家数据 + private player: PlayerGachaRecord = new PlayerGachaRecord(); + // 结果 + private result = new GachaResults(); + + constructor(dicGacha: DicGacha, userGacha?: { floor: UserFloor[], hope: UserHope[], pickHero: number }) { + this.gachaType = dicGacha.gachaType; + this.percent = new GachaPercent(dicGacha.percent); + if(userGacha) + this.player.setUserGacha(userGacha.floor, userGacha.hope, userGacha.pickHero); + for(let id of dicGacha.floor) { + let floor = new GachaFloor(id); + if(floor && floor.id) this.floors.push(floor); + } + } + + public pull(count: number, userHeroes: HeroType[]) { + this.pullContent(count); + this.processFloors(); + this.result.processDetail(this.player.pickHero); + this.processHope(); + let { heroInfo, items, resultList } = this.getFinalResult(userHeroes) + return { resultList, heroInfo, items }; + } + + // 根据基础的percent抽基地 + private pullContent(count: number) { + for (let i = 0; i < count; i++) { + // 按照一般概率抽出 + let dic = this.percent.getRandomPlan(); + if(dic) this.result.addPlan(dic.planId); + } + } + + // 保底 + private processFloors() { + for(let floor of this.floors) { + switch(floor.floorType) { + case GACHA_FLOOR_TYPE.MAIN_FLOOR: + this.setMainFloor(floor); + break; + case GACHA_FLOOR_TYPE.ONLY_ONE: + this.setAssignFloor(floor); + break; + case GACHA_FLOOR_TYPE.TEN_MOST_HIGHER: + case GACHA_FLOOR_TYPE.TEN_MOST_LOWER: + case GACHA_FLOOR_TYPE.FIVE_MOST_LOWER: + this.setTenMostFloor(floor); + break; + } + } + } + + // 元宝招募保底,金将保底,按次数给保底,抽到就重新计算次数,单抽也算 + private setMainFloor(floor: GachaFloor) { + let { floorCount: historyCount } = this.player.getFloorCountById(floor.id); + for(let gachaResult of this.result.list) { + if(++historyCount >= floor.param || gachaResult.isTarget(floor)) { + let replacePlan = this.percent.getFloorTarget(floor.heroQuality); + if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); + historyCount = 0; + } + } + this.player.setFloorCount(floor.id, historyCount, false); + } + + // 求贤若渴,和活动抽卡金色保底,伪随机,n次内给且只给一个,单抽也算 + public setAssignFloor(floor: GachaFloor) { + let { floorCount: historyCount, hasGetFloor } = this.player.getFloorCountById(floor.id); + for(let gachaResult of this.result.list) { + if(++historyCount >= floor.param || gachaResult.isTarget(floor)) { + if(hasGetFloor) { // 已经获得过一次保底了, 不给,换个给 + let replacePlan = this.percent.getReplacePlan(gachaResult.heroQuality, floor.isReplaceLower()); + if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); + } else { // 设置为保底 + let replacePlan = this.percent.getFloorTarget(floor.heroQuality); + + if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality); + hasGetFloor = true; + } + } + if(historyCount >= floor.param) { + hasGetFloor = false; + historyCount = 0; + } + } + this.player.setFloorCount(floor.id, historyCount, hasGetFloor); + } + + + // 10连最多多少个武将 + private setTenMostFloor(floor: GachaFloor) { + let targetCnt = this.result.getTargetCnt(floor); + if(this.result.count == floor.param2 && targetCnt > floor.param) { + let gachaResults = this.result.getRandomResultOfTarget(floor, targetCnt - floor.param); + for(let gachaResult of gachaResults) { + let replacePlan = this.percent.getReplacePlan(gachaResult.heroQuality, floor.isReplaceLower()); + if(replacePlan) gachaResult.changePlan(replacePlan.planId, replacePlan.heroQuality) + } + } + } + + // 心愿单 + private processHope() { + if(this.gachaType != GACHA_TYPE.NORMAL && this.gachaType != GACHA_TYPE.ARTIFACT) return; + for(let gachaResult of this.result.list) { + if(this.gachaType == GACHA_TYPE.NORMAL && gachaResult.heroQuality != HERO_QUALITY_TYPE.GOLD) continue; // 只有橙将 + if(this.gachaType == GACHA_TYPE.ARTIFACT && gachaResult.heroQuality != HERO_QUALITY_TYPE.UR) continue; // 只有橙将 + let { dic: { id: randHopePosition } } = getRandEelmWithWeight(gameData.gachaHope); + if(randHopePosition > 0) { // 按玩家设置的心愿单塞 + let hopeHero = this.player.getHopeHero(randHopePosition) + if(hopeHero > 0) { + if (this.gachaType == GACHA_TYPE.NORMAL) gachaResult.setHero(hopeHero, 1); + if (this.gachaType == GACHA_TYPE.ARTIFACT) gachaResult.setItem(hopeHero, 1); + } + } + if (this.gachaType == GACHA_TYPE.NORMAL) this.player.setUserHope(gachaResult.hid); // 设置心愿单中了没有 + if (this.gachaType == GACHA_TYPE.ARTIFACT) this.player.setUserHope(gachaResult.id); // 设置心愿单中了没有 + } + } + + // 创建信息 + public getFinalResult(userHeroes: HeroType[]) { + return this.result.transferToFinalResult(userHeroes); + } + + // 获得需要储存的数据 + // 一般抽卡getter + public getUserGachaParam() { + return this.player.getUserGachaParam() + } + + public clear() { + this.floors = undefined; + this.percent = undefined; + this.player = undefined; + this.result = undefined; + } +} + +/** + * 根据品质获得武将池 + * @param quality 品质 + */ +export function getAllHeroByQuality(quality: number) { + let allHero: number[] = []; + let allQuality: number[] = []; + for (let [actorId] of gameData.recruit) { + let dicHero = gameData.hero.get(actorId); + if (dicHero.quality == quality) { + allHero.push(actorId); + } + if (allQuality.indexOf(dicHero.quality) == -1) allQuality.push(dicHero.quality); + } + allQuality.sort((a, b) => a - b); + if (allQuality.length == 0) return []; + if (allHero.length == 0) { + allHero = getAllHeroByQuality(allQuality[0]); + } + return allHero; +} + +function getPickHeroCnt(hid: number) { + let dicHero = gameData.hero.get(hid); + let cnt = gameData.gachaPickHeroCnt.get(dicHero?.quality)||0; + return cnt +} + +function getPickHeroPiece(hid: number) { + let dicHero = gameData.hero.get(hid); + return dicHero?.pieceId??0 +} + +export function getDicGachaByGachaCnt(dicGacha: DicGacha, historyCount: number) { + if(isGachaCntIn(historyCount, dicGacha.gachaCnt.min, dicGacha.gachaCnt.max)) { + return dicGacha; + } + let gachaIds = gameData.gachaByType.get(dicGacha.gachaType); + for(let gachaId of gachaIds) { + let newDicGacha = gameData.gacha.get(gachaId); + if(isGachaCntIn(historyCount, newDicGacha.gachaCnt.min, newDicGacha.gachaCnt.max)) { + return {...newDicGacha, id: dicGacha.id}; + } + } + return null +} + +export function getDicGachas(gachaType: number, historyCount: number, count: number) { + let dics: { dic: DicGacha, min: number, max: number }[] = []; + let gachaIds = gameData.gachaByType.get(gachaType); + for(let gachaId of gachaIds) { + let dicGacha = gameData.gacha.get(gachaId); + if(!dicGacha || (dicGacha.gachaCnt.min > dicGacha.gachaCnt.max && dicGacha.gachaCnt.max != -1)) continue; + if((dicGacha.gachaCnt.max != -1 && dicGacha.gachaCnt.max <= historyCount) || dicGacha.gachaCnt.min > historyCount + count) continue; // dic的范围不包含 + let min = dicGacha.gachaCnt.min > historyCount + 1? dicGacha.gachaCnt.min: historyCount + 1; + let max = (dicGacha.gachaCnt.max == -1 || dicGacha.gachaCnt.max > historyCount + count)? historyCount + count: dicGacha.gachaCnt.max; + dics.push({ dic: dicGacha, min, max }); + } + return dics.sort((a, b) => a.min - b.min); +} + +function isGachaCntIn(historyCount: number, min: number, max: number) { + let nowCnt = historyCount + 1; + return min <= nowCnt && (max >= nowCnt || max == -1); +} + + +export async function getGuideGachaData(serverId: number, activityId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GuideGachaData(activityData, createTime, serverTime); + let userGacha = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); + playerData.setPlayerData(userGacha); + if(playerData.hasChoosen || playerData.neverChoose()) return null; + return playerData; +} diff --git a/game-server/app/services/activity/giftPackageService.ts b/game-server/app/services/activity/giftPackageService.ts index 3f6588f03..f7752b2a0 100644 --- a/game-server/app/services/activity/giftPackageService.ts +++ b/game-server/app/services/activity/giftPackageService.ts @@ -1,321 +1,321 @@ -import { GIFT_PACKAGE_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; -import { gameData } from '../../pubUtils/data'; -import { addItems } from '../role/rewardService'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { CreateHeroParam } from '../../domain/roleField/hero'; -import { DicGiftPackage } from '../../pubUtils/dictionary/DicGiftPackage'; -import { ItemInter, RewardInter } from '../../pubUtils/interface'; -import { decodeArrayListStr, getRandEelmWithWeight, resResult } from '../../pubUtils/util'; -import { createHeroes } from '../role/createHero'; -import { GuildModel } from '../../db/Guild'; -import { pushGuildInfoUpdate } from '../guildService'; -import { combineItems } from '../role/util'; -import { recordGuildFund } from './timeLimitRankService'; -import { filterGoods, isGoodsHidden, isHeroHidden } from '../dataService'; -import { DicGiftPackagePlan } from '../../pubUtils/dictionary/DicGiftPackagePlan'; -import { Floor, GiftPackageFloorModel, GiftPackageFloorType } from '../../db/GiftPackageFloor'; -import { isNumber } from 'underscore'; - - - -/** - * 兑换礼包 - * @param giftID 礼包id - * @param roleId 角色id - * @param roleName 角色名称 - * @param giftCount 一共消耗多少个礼包 - * @param sid - */ -export async function useGiftPackage(roleId: string, roleName: string, sid: string, serverId: number, guildCode: string, giftID: number, selected: Array = [], giftCount: number) { - console.log("bbbbbbbb", giftID, selected) - let result: { goods: {id: number, count: number, seqId?: number|string, isBag?: boolean}[], addHeros: any[]} = { goods: [], addHeros: [] } - let giftPackageData = gameData.giftPackage.get(giftID); - if (!giftPackageData) { - return resResult(STATUS.SUCCESS, result); - } - console.log('dddddddddddddd', giftID, JSON.stringify(giftPackageData)) - let giftType = giftPackageData.type;//礼包类型 - let dicGiftPackagePlan = gameData.giftPackagePlan.get(giftPackageData.id)||[]; - - switch (giftType) { - case GIFT_PACKAGE_TYPE.ALL://全部 - { - let allReward = []; - for (let obj of dicGiftPackagePlan) { - allReward.push({ type: obj.contentType, id: obj.content, count: obj.count * giftCount }); - } - - result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); - break; - } - case GIFT_PACKAGE_TYPE.SELECTED_X://手选 - { - let count = giftPackageData.count;//选择个数 - if (selected.length != count) { - break; - } - let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); - let selectedReward = getSelectedReward(pool, selected) - let allReward: { type: number, id: number, count: number }[] = []; - for (let obj of selectedReward) { - allReward.push({ type: obj.type, id: obj.id, count: obj.count * giftCount }); - } - let gids = allReward.filter(cur => cur.type == 2).map(cur => cur.id); - if(gids.length > 0 && isGoodsHidden(...gids)) return resResult(STATUS.ITEM_IS_HIDDEN); - let hids = allReward.filter(cur => cur.type == 1).map(cur => cur.id); - if(hids.length > 0 && isHeroHidden(...gids)) return resResult(STATUS.HERO_IS_HIDDEN); - - result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); - break; - } - case GIFT_PACKAGE_TYPE.RANDOM_X://随机 - { - let count = giftPackageData.count;//随机个数 - let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); - if(pool.length <= 0) return resResult(STATUS.DIC_DATA_NOT_FOUND); - let allReward: { type: number, id: number, count: number }[] = []; - let giftPackage = { giftPackageId: giftID }; - const floorPlans = groupByFloorId(pool); - let dropHistory = (floorPlans && Object.keys(floorPlans).length > 0) ? await GiftPackageFloorModel.findByGiftPackageId(roleId, giftID): { floors: [], getSum: 0, allSum: 0 }; - for (let i = 0; i < giftCount; i++) { - let { rewards, floors } = await randomSelectedData(dropHistory, pool, roleId, giftID, count); - allReward.push(...rewards); - giftPackage['floors'] = floors; - } - await GiftPackageFloorModel.updateByGiftPackageId(roleId, giftID, { - floors: dropHistory.floors, getSum: dropHistory.getSum, allSum: dropHistory.allSum - }); - result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); - Object.assign(result, { giftPackage }); - break; - } - case GIFT_PACKAGE_TYPE.GUILD_FUND: // 军团资金 - { - console.log('ccccc',guildCode, giftPackageData.count, giftCount) - if(!guildCode) return resResult(STATUS.ITEM_CANNOT_RECEIVE_NO_GUILD); - const guild = await GuildModel.updateInfo(guildCode, {}, { fund: giftPackageData.count * giftCount }); - await pushGuildInfoUpdate(guildCode, { fund: guild.fund }); - recordGuildFund(serverId, guild, giftPackageData.count * giftCount); - break; - } - default: - break; - } - - return resResult(STATUS.SUCCESS, result); -} - -//结算奖励的内容 -export async function addReward(roleId: string, roleName: string, sid: string, serverId: number, reward: Array, reason: number) { - let giftReward = rewardItemData(reward); - let goodArray = giftReward.goods; - let heroArray = giftReward.heroes; - - //兑换物品 - let goods = await addItems(roleId, roleName, sid, goodArray, reason) - let addHeros = []; - if (heroArray.length > 0) { - let heroResult = await createHeroes(roleId, roleName, sid, serverId, heroArray); - goods = goods.concat(heroResult.goods) - addHeros = addHeros.concat(heroResult.heroes); - } - - return { goods: combineItems(goods), addHeros } -} - -//表中的奖励数据(包括礼包)转换成具体对应奖励物品的实例 -export function rewardItemData(reward: Array) { - let goods: Array = []; - let heroes: Array = []; - for (let obj of reward) { - switch (obj.type) { - case ACTIVITY_RESOURCES_TYPE.HERO: - heroes.push({ hid: obj.id, count: obj.count }) - break; - case ACTIVITY_RESOURCES_TYPE.GOODS: - goods.push({ id: obj.id, count: obj.count, expireTime: obj.expireTime }) - break; - case ACTIVITY_RESOURCES_TYPE.GIFTPACKAGE://配置成礼包会立刻兑换,配置成物品会把礼包放入背包中 - let goodData = gameData.goods.get(obj.id);//礼包物品 - let giftPackageData = gameData.giftPackage.get(goodData.gift);//礼包数据 - let giftReward = rewardItemData(giftPackageData.reward) - goods = goods.concat(giftReward.goods) - heroes = heroes.concat(giftReward.heroes) - break; - default: - break; - } - } - return { goods, heroes } -} - -export function getSelectedReward(plans: DicGiftPackagePlan[], selected: Array): Array { - - let selectedReward: Array = []; - for (let i = 0; i < selected.length; i++) { - let index = selected[i]; - if (plans.length > index) { - let { contentType, content, count } = plans[index]; - selectedReward.push({ type: contentType, id: content, count }); - } - } - return selectedReward; -} - -// 根据是否触发保底,更新抽取次数 -function updateFloorCount(floors: Floor[], maxQaulity: number, isTrigger: boolean) { - for (let floor of floors) { - if (!isTrigger) { - floor.count++; - } else { - if (floor.quality <= maxQaulity) { - floor.count = 0; - } else { - floor.count++; - } - } - } - return floors; -} - -// 将随机池子根据保底 id 进行分组 -function groupByFloorId(plans: DicGiftPackagePlan[]): { [key: number]: DicGiftPackagePlan[] } { - return plans.reduce((acc, cur) => { - if (cur.floorId !== 0) { - if (!acc[cur.floorId]) acc[cur.floorId] = []; - acc[cur.floorId].push(cur); - } - return acc; - }, {} as { [key: number]: DicGiftPackagePlan[] }); -} - -// 初始化用户某个礼包的保底数据 -async function initFloorData(floors: Floor[], floorPlans: { [key: number]: DicGiftPackagePlan[] }) { - for (let floorId in floorPlans) { - let hasFloorFlag = false; - for (let floor of floors) { - if (floor.id === parseInt(floorId)) { - hasFloorFlag = true; - continue; - } - } - if (!hasFloorFlag) { - floors.push({ id: parseInt(floorId), count: 0, quality: gameData.giftPackageFloor.get(parseInt(floorId)).quality }); - } - } -} - -async function randomSelectedData(dropHistory: {floors: Floor[], getSum: number, allSum: number }, pool: DicGiftPackagePlan[], roleId: string, giftPackageId: number, count: number) { - let rewards: RewardParam[] = []; - const floorPlans = groupByFloorId(pool); - let { floors = [], getSum = 0, allSum = 0 } = dropHistory; - - for (let i = 0; i < count; i++) { - let randResult = getRandEelmWithWeight(pool)?.dic; - if (!randResult) continue; - // 如果没有保底池子,直接返回 - if (!floorPlans || Object.keys(floorPlans).length === 0) { - rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); - continue; - } - - initFloorData(floors, floorPlans); - - // 检查随机结果的 id 是否在 floorPlans 中,是的话抽中保底 - let flag = false; - for (let floorId in floorPlans) { - if (floorPlans[floorId].findIndex(cur => cur.id === randResult.id) !== -1) { - flag = true; - break; - } - } - - // 检查是否达到了保底次数,并且记录最大品质的 floorId - let maxQaulityFloorId = 0; // 最大品质的 floorId - let maxQaulity = 0; - for (let floor of floors) { - if (floor.count + 1 >= gameData.giftPackageFloor.get(floor.id).times) { - flag = true; - if (gameData.giftPackageFloor.get(floor.id).quality > maxQaulity) { - maxQaulityFloorId = floor.id; - maxQaulity = gameData.giftPackageFloor.get(floor.id).quality; - } - } - } - - // 更新抽取次数,确定要返回的物品 - if (flag && maxQaulityFloorId == 0) { // 抽到了保底物品 - const quality = gameData.giftPackageFloor.get(randResult.floorId).quality; - rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); - updateFloorCount(floors, quality, true); - getSum++; - console.log('got floorId a: ', randResult.floorId, quality); - } else if (flag && maxQaulityFloorId > 0) { // 次数保底 - let floorResult = getRandEelmWithWeight(floorPlans[maxQaulityFloorId])?.dic; - if (!floorResult) continue; - rewards.push({ type: floorResult.contentType, id: floorResult.content, count: floorResult.count }); - updateFloorCount(floors, maxQaulity, true); - getSum++; - console.log('got floorId b: ', maxQaulityFloorId, maxQaulity); - } else { // 未达到保底次数 - rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); - updateFloorCount(floors, 0, false); - console.log('got floorId c: ', randResult.floorId, 0); - } - allSum++; - } - - let result; - result = Object.assign({}, { rewards }) - if(floorPlans && Object.keys(floorPlans).length > 0) { - dropHistory.floors = floors; - dropHistory.getSum = getSum; - dropHistory.allSum = allSum; - Object.assign(result, { giftPackageId, floors }); - } - return result; -} - -//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 活动奖励 -export function stringToRewardParam(rewardStr: string): Array { - let result = new Array<{ type: number, id: number, count: number }>(); - if (!rewardStr) return result; - let decodeArr = decodeArrayListStr(rewardStr); - for (let [type, id, count] of decodeArr) { - if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { - continue; - } - result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); - } - return result -} - -//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 资源消耗 -export function stringToConsumeParam(...rewardStrs: string[]) { - let result = new Array<{ type: number, id: number, count: number }>(); - for(let rewardStr of rewardStrs) { - if(!rewardStr) continue; - let decodeArr = decodeArrayListStr(rewardStr); - for (let [type, id, count] of decodeArr) { - if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { - throw new Error('data table format wrong'); - } - result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); - } - } - return combineItems(result); -} - -//数据格式转换'id&数量|id&数量|' ->> Array 老资源格式 -export function stringToRewardInter(rewardStr: string): Array { - let result = new Array<{ id: number, count: number }>(); - if (!rewardStr) return result; - let decodeArr = decodeArrayListStr(rewardStr); - for (let [type, id, count] of decodeArr) { - if (isNaN(parseInt(id)) || isNaN(parseInt(count))) { - throw new Error('data table format wrong'); - } - result.push({ id: parseInt(id), count: parseInt(count) }); - } - return result -} +import { GIFT_PACKAGE_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON, STATUS } from '@consts'; +import { gameData } from '@pubUtils/data'; +import { addItems } from '../role/rewardService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { CreateHeroParam } from '@domain/roleField/hero'; +import { DicGiftPackage } from '@pubUtils/dictionary/DicGiftPackage'; +import { ItemInter, RewardInter } from '@pubUtils/interface'; +import { decodeArrayListStr, getRandEelmWithWeight, resResult } from '@pubUtils/util'; +import { createHeroes } from '../role/createHero'; +import { GuildModel } from '@db/Guild'; +import { pushGuildInfoUpdate } from '../guildService'; +import { combineItems } from '../role/util'; +import { recordGuildFund } from './timeLimitRankService'; +import { filterGoods, isGoodsHidden, isHeroHidden } from '../dataService'; +import { DicGiftPackagePlan } from '@pubUtils/dictionary/DicGiftPackagePlan'; +import { Floor, GiftPackageFloorModel, GiftPackageFloorType } from '@db/GiftPackageFloor'; +import { isNumber } from 'underscore'; + + + +/** + * 兑换礼包 + * @param giftID 礼包id + * @param roleId 角色id + * @param roleName 角色名称 + * @param giftCount 一共消耗多少个礼包 + * @param sid + */ +export async function useGiftPackage(roleId: string, roleName: string, sid: string, serverId: number, guildCode: string, giftID: number, selected: Array = [], giftCount: number) { + console.log("bbbbbbbb", giftID, selected) + let result: { goods: {id: number, count: number, seqId?: number|string, isBag?: boolean}[], addHeros: any[]} = { goods: [], addHeros: [] } + let giftPackageData = gameData.giftPackage.get(giftID); + if (!giftPackageData) { + return resResult(STATUS.SUCCESS, result); + } + console.log('dddddddddddddd', giftID, JSON.stringify(giftPackageData)) + let giftType = giftPackageData.type;//礼包类型 + let dicGiftPackagePlan = gameData.giftPackagePlan.get(giftPackageData.id)||[]; + + switch (giftType) { + case GIFT_PACKAGE_TYPE.ALL://全部 + { + let allReward = []; + for (let obj of dicGiftPackagePlan) { + allReward.push({ type: obj.contentType, id: obj.content, count: obj.count * giftCount }); + } + + result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); + break; + } + case GIFT_PACKAGE_TYPE.SELECTED_X://手选 + { + let count = giftPackageData.count;//选择个数 + if (selected.length != count) { + break; + } + let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); + let selectedReward = getSelectedReward(pool, selected) + let allReward: { type: number, id: number, count: number }[] = []; + for (let obj of selectedReward) { + allReward.push({ type: obj.type, id: obj.id, count: obj.count * giftCount }); + } + let gids = allReward.filter(cur => cur.type == 2).map(cur => cur.id); + if(gids.length > 0 && isGoodsHidden(...gids)) return resResult(STATUS.ITEM_IS_HIDDEN); + let hids = allReward.filter(cur => cur.type == 1).map(cur => cur.id); + if(hids.length > 0 && isHeroHidden(...gids)) return resResult(STATUS.HERO_IS_HIDDEN); + + result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); + break; + } + case GIFT_PACKAGE_TYPE.RANDOM_X://随机 + { + let count = giftPackageData.count;//随机个数 + let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content)); + if(pool.length <= 0) return resResult(STATUS.DIC_DATA_NOT_FOUND); + let allReward: { type: number, id: number, count: number }[] = []; + let giftPackage = { giftPackageId: giftID }; + const floorPlans = groupByFloorId(pool); + let dropHistory = (floorPlans && Object.keys(floorPlans).length > 0) ? await GiftPackageFloorModel.findByGiftPackageId(roleId, giftID): { floors: [], getSum: 0, allSum: 0 }; + for (let i = 0; i < giftCount; i++) { + let { rewards, floors } = await randomSelectedData(dropHistory, pool, roleId, giftID, count); + allReward.push(...rewards); + giftPackage['floors'] = floors; + } + await GiftPackageFloorModel.updateByGiftPackageId(roleId, giftID, { + floors: dropHistory.floors, getSum: dropHistory.getSum, allSum: dropHistory.allSum + }); + result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE); + Object.assign(result, { giftPackage }); + break; + } + case GIFT_PACKAGE_TYPE.GUILD_FUND: // 军团资金 + { + console.log('ccccc',guildCode, giftPackageData.count, giftCount) + if(!guildCode) return resResult(STATUS.ITEM_CANNOT_RECEIVE_NO_GUILD); + const guild = await GuildModel.updateInfo(guildCode, {}, { fund: giftPackageData.count * giftCount }); + await pushGuildInfoUpdate(guildCode, { fund: guild.fund }); + recordGuildFund(serverId, guild, giftPackageData.count * giftCount); + break; + } + default: + break; + } + + return resResult(STATUS.SUCCESS, result); +} + +//结算奖励的内容 +export async function addReward(roleId: string, roleName: string, sid: string, serverId: number, reward: Array, reason: number) { + let giftReward = rewardItemData(reward); + let goodArray = giftReward.goods; + let heroArray = giftReward.heroes; + + //兑换物品 + let goods = await addItems(roleId, roleName, sid, goodArray, reason) + let addHeros = []; + if (heroArray.length > 0) { + let heroResult = await createHeroes(roleId, roleName, sid, serverId, heroArray); + goods = goods.concat(heroResult.goods) + addHeros = addHeros.concat(heroResult.heroes); + } + + return { goods: combineItems(goods), addHeros } +} + +//表中的奖励数据(包括礼包)转换成具体对应奖励物品的实例 +export function rewardItemData(reward: Array) { + let goods: Array = []; + let heroes: Array = []; + for (let obj of reward) { + switch (obj.type) { + case ACTIVITY_RESOURCES_TYPE.HERO: + heroes.push({ hid: obj.id, count: obj.count }) + break; + case ACTIVITY_RESOURCES_TYPE.GOODS: + goods.push({ id: obj.id, count: obj.count, expireTime: obj.expireTime }) + break; + case ACTIVITY_RESOURCES_TYPE.GIFTPACKAGE://配置成礼包会立刻兑换,配置成物品会把礼包放入背包中 + let goodData = gameData.goods.get(obj.id);//礼包物品 + let giftPackageData = gameData.giftPackage.get(goodData.gift);//礼包数据 + let giftReward = rewardItemData(giftPackageData.reward) + goods = goods.concat(giftReward.goods) + heroes = heroes.concat(giftReward.heroes) + break; + default: + break; + } + } + return { goods, heroes } +} + +export function getSelectedReward(plans: DicGiftPackagePlan[], selected: Array): Array { + + let selectedReward: Array = []; + for (let i = 0; i < selected.length; i++) { + let index = selected[i]; + if (plans.length > index) { + let { contentType, content, count } = plans[index]; + selectedReward.push({ type: contentType, id: content, count }); + } + } + return selectedReward; +} + +// 根据是否触发保底,更新抽取次数 +function updateFloorCount(floors: Floor[], maxQaulity: number, isTrigger: boolean) { + for (let floor of floors) { + if (!isTrigger) { + floor.count++; + } else { + if (floor.quality <= maxQaulity) { + floor.count = 0; + } else { + floor.count++; + } + } + } + return floors; +} + +// 将随机池子根据保底 id 进行分组 +function groupByFloorId(plans: DicGiftPackagePlan[]): { [key: number]: DicGiftPackagePlan[] } { + return plans.reduce((acc, cur) => { + if (cur.floorId !== 0) { + if (!acc[cur.floorId]) acc[cur.floorId] = []; + acc[cur.floorId].push(cur); + } + return acc; + }, {} as { [key: number]: DicGiftPackagePlan[] }); +} + +// 初始化用户某个礼包的保底数据 +async function initFloorData(floors: Floor[], floorPlans: { [key: number]: DicGiftPackagePlan[] }) { + for (let floorId in floorPlans) { + let hasFloorFlag = false; + for (let floor of floors) { + if (floor.id === parseInt(floorId)) { + hasFloorFlag = true; + continue; + } + } + if (!hasFloorFlag) { + floors.push({ id: parseInt(floorId), count: 0, quality: gameData.giftPackageFloor.get(parseInt(floorId)).quality }); + } + } +} + +async function randomSelectedData(dropHistory: {floors: Floor[], getSum: number, allSum: number }, pool: DicGiftPackagePlan[], roleId: string, giftPackageId: number, count: number) { + let rewards: RewardParam[] = []; + const floorPlans = groupByFloorId(pool); + let { floors = [], getSum = 0, allSum = 0 } = dropHistory; + + for (let i = 0; i < count; i++) { + let randResult = getRandEelmWithWeight(pool)?.dic; + if (!randResult) continue; + // 如果没有保底池子,直接返回 + if (!floorPlans || Object.keys(floorPlans).length === 0) { + rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); + continue; + } + + initFloorData(floors, floorPlans); + + // 检查随机结果的 id 是否在 floorPlans 中,是的话抽中保底 + let flag = false; + for (let floorId in floorPlans) { + if (floorPlans[floorId].findIndex(cur => cur.id === randResult.id) !== -1) { + flag = true; + break; + } + } + + // 检查是否达到了保底次数,并且记录最大品质的 floorId + let maxQaulityFloorId = 0; // 最大品质的 floorId + let maxQaulity = 0; + for (let floor of floors) { + if (floor.count + 1 >= gameData.giftPackageFloor.get(floor.id).times) { + flag = true; + if (gameData.giftPackageFloor.get(floor.id).quality > maxQaulity) { + maxQaulityFloorId = floor.id; + maxQaulity = gameData.giftPackageFloor.get(floor.id).quality; + } + } + } + + // 更新抽取次数,确定要返回的物品 + if (flag && maxQaulityFloorId == 0) { // 抽到了保底物品 + const quality = gameData.giftPackageFloor.get(randResult.floorId).quality; + rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); + updateFloorCount(floors, quality, true); + getSum++; + console.log('got floorId a: ', randResult.floorId, quality); + } else if (flag && maxQaulityFloorId > 0) { // 次数保底 + let floorResult = getRandEelmWithWeight(floorPlans[maxQaulityFloorId])?.dic; + if (!floorResult) continue; + rewards.push({ type: floorResult.contentType, id: floorResult.content, count: floorResult.count }); + updateFloorCount(floors, maxQaulity, true); + getSum++; + console.log('got floorId b: ', maxQaulityFloorId, maxQaulity); + } else { // 未达到保底次数 + rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count }); + updateFloorCount(floors, 0, false); + console.log('got floorId c: ', randResult.floorId, 0); + } + allSum++; + } + + let result; + result = Object.assign({}, { rewards }) + if(floorPlans && Object.keys(floorPlans).length > 0) { + dropHistory.floors = floors; + dropHistory.getSum = getSum; + dropHistory.allSum = allSum; + Object.assign(result, { giftPackageId, floors }); + } + return result; +} + +//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 活动奖励 +export function stringToRewardParam(rewardStr: string): Array { + let result = new Array<{ type: number, id: number, count: number }>(); + if (!rewardStr) return result; + let decodeArr = decodeArrayListStr(rewardStr); + for (let [type, id, count] of decodeArr) { + if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { + continue; + } + result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); + } + return result +} + +//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array 资源消耗 +export function stringToConsumeParam(...rewardStrs: string[]) { + let result = new Array<{ type: number, id: number, count: number }>(); + for(let rewardStr of rewardStrs) { + if(!rewardStr) continue; + let decodeArr = decodeArrayListStr(rewardStr); + for (let [type, id, count] of decodeArr) { + if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) { + throw new Error('data table format wrong'); + } + result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) }); + } + } + return combineItems(result); +} + +//数据格式转换'id&数量|id&数量|' ->> Array 老资源格式 +export function stringToRewardInter(rewardStr: string): Array { + let result = new Array<{ id: number, count: number }>(); + if (!rewardStr) return result; + let decodeArr = decodeArrayListStr(rewardStr); + for (let [type, id, count] of decodeArr) { + if (isNaN(parseInt(id)) || isNaN(parseInt(count))) { + throw new Error('data table format wrong'); + } + result.push({ id: parseInt(id), count: parseInt(count) }); + } + return result +} diff --git a/game-server/app/services/activity/groupShopService.ts b/game-server/app/services/activity/groupShopService.ts index 53887b48c..c764cf80f 100644 --- a/game-server/app/services/activity/groupShopService.ts +++ b/game-server/app/services/activity/groupShopService.ts @@ -1,115 +1,115 @@ -import { ACTIVITY_TYPE, GROUP_SHOP_PRICE_STATUS, MAIL_TYPE, PUSH_ROUTE } from "../../consts"; -import { ActivityModel, ActivityModelType } from "../../db/Activity"; -import { ActivityGroupShopRecModel } from "../../db/ActivityGroupShopRec"; -import { ActivityGroupShopRefundModel, RefundRec } from "../../db/ActivityGroupShopRefund"; -import { ActivityGroupShopUserRecModel } from "../../db/ActivityGroupShopUserRec"; -import { GroupShopData } from "../../domain/activityField/groupShopField"; -import { gameData } from "../../pubUtils/data"; -import { RewardInter } from "../../pubUtils/interface"; -import { sendMailByContent } from "../mailService"; -import { sendMessageToGroupShopWithSuc } from "../pushService"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getGoldObject } from "../role/rewardService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getGroupShopData(activityId: number, roleId: string) { - let activityData = await getActivityById(activityId); - if(!activityData) return null - let createTime = await getRoleCreateTime(roleId); - - let playerData = new GroupShopData(activityData, createTime, 0); - let serverRecords = await ActivityGroupShopRecModel.findByActivity(activityId); - playerData.setRecords(serverRecords); - let playerRecords = await ActivityGroupShopUserRecModel.findByActivityAndRoleId(activityId, roleId); - playerData.setPlayerRecord(playerRecords); - - return playerData; -} - -export async function getGroupShopDataShow(activityId: number, roleId: string) { - let playerData = await getGroupShopData(activityId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -export function getGroupShopPriceStatus(clientPrice: number, price: number) { - if(clientPrice == price) return GROUP_SHOP_PRICE_STATUS.NORMAL; - if(clientPrice < price) return GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH; - return GROUP_SHOP_PRICE_STATUS.OVER; -} - -export async function getGroupShopServerData(activityData: ActivityModelType) { - let playerData = new GroupShopData(activityData, 0, 0); - let serverRecords = await ActivityGroupShopRecModel.findByActivity(activityData.activityId); - playerData.setRecords(serverRecords); - - return playerData; -} - -export async function getGroupShopTimers(activity: ActivityModelType) { - if(!activity) return []; - let playerData = await getGroupShopServerData(activity); - return playerData?.timer||[]; -} - -export async function setGroupShopToSetSum(arr: { activityId: number, itemId: number, sum: number }[]) { - console.log('###### setGroupShopToSetSum', JSON.stringify(arr)); - for(let { activityId, itemId, sum } of arr) { - let serverRecord = await ActivityGroupShopRecModel.setSum(activityId, itemId, sum); - if(serverRecord) { - let activityData = await getActivityById(activityId); - let playerData = new GroupShopData(activityData, 0, 0); - playerData.setRecords([serverRecord]); - - let item = playerData.findItemById(itemId); - let nextDiscount = item.getCurDiscount(); - // 推送频道 - await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId, sum, itemId, curDiscount: nextDiscount }); - } - } -} - -export async function refundGroupShop(isDebug = false) { - console.log('###### refundGroupShop') - let activities = await ActivityModel.findActivityByType(ACTIVITY_TYPE.GROUP_SHOP); - - for(let activityData of activities) { - let hasRefund = await ActivityGroupShopRefundModel.check(activityData.activityId); - if(!isDebug && hasRefund) continue; - - let playerData = await getGroupShopServerData(activityData); - if(!isDebug && playerData.endTime >= Date.now()) continue; - - let items = playerData.items||[]; - let refundRecs: RefundRec[] = []; - for(let item of items) { - let curDiscount = item.getCurDiscount(); - let playerRecords = await ActivityGroupShopUserRecModel.findByPrice(activityData.activityId, item.itemId, item.getCurDiscount().price); - for(let { roleId, records } of playerRecords) { - let rewards: {id: number, count: number}[] = [], sumGold = 0; - for(let { price, buyCnt } of records) { - if(price <= curDiscount.price) continue; - let diff = (price - curDiscount.price) * buyCnt; - rewards.push(getGoldObject(diff)); - sumGold += diff; - refundRecs.push({ roleId, itemId: item.itemId, diff }); - } - let itemName = gameData.goods.get(item.id)?.name?? `${item.id}`; - let resultDiscount = curDiscount.discount; - await sendMailByContent(MAIL_TYPE.GROUP_SHOP_REFUND, roleId, { goods: rewards, params: [itemName, `${resultDiscount}`, `${sumGold}`] }); - } - } - console.log('###### refundGroupShop refund complete', activityData.activityId) - await ActivityGroupShopRefundModel.refund(activityData.activityId, refundRecs); - } -} \ No newline at end of file +import { ACTIVITY_TYPE, GROUP_SHOP_PRICE_STATUS, MAIL_TYPE, PUSH_ROUTE } from "@consts"; +import { ActivityModel, ActivityModelType } from "@db/Activity"; +import { ActivityGroupShopRecModel } from "@db/ActivityGroupShopRec"; +import { ActivityGroupShopRefundModel, RefundRec } from "@db/ActivityGroupShopRefund"; +import { ActivityGroupShopUserRecModel } from "@db/ActivityGroupShopUserRec"; +import { GroupShopData } from "@domain/activityField/groupShopField"; +import { gameData } from "@pubUtils/data"; +import { RewardInter } from "@pubUtils/interface"; +import { sendMailByContent } from "../mailService"; +import { sendMessageToGroupShopWithSuc } from "../pushService"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getGoldObject } from "../role/rewardService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getGroupShopData(activityId: number, roleId: string) { + let activityData = await getActivityById(activityId); + if(!activityData) return null + let createTime = await getRoleCreateTime(roleId); + + let playerData = new GroupShopData(activityData, createTime, 0); + let serverRecords = await ActivityGroupShopRecModel.findByActivity(activityId); + playerData.setRecords(serverRecords); + let playerRecords = await ActivityGroupShopUserRecModel.findByActivityAndRoleId(activityId, roleId); + playerData.setPlayerRecord(playerRecords); + + return playerData; +} + +export async function getGroupShopDataShow(activityId: number, roleId: string) { + let playerData = await getGroupShopData(activityId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +export function getGroupShopPriceStatus(clientPrice: number, price: number) { + if(clientPrice == price) return GROUP_SHOP_PRICE_STATUS.NORMAL; + if(clientPrice < price) return GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH; + return GROUP_SHOP_PRICE_STATUS.OVER; +} + +export async function getGroupShopServerData(activityData: ActivityModelType) { + let playerData = new GroupShopData(activityData, 0, 0); + let serverRecords = await ActivityGroupShopRecModel.findByActivity(activityData.activityId); + playerData.setRecords(serverRecords); + + return playerData; +} + +export async function getGroupShopTimers(activity: ActivityModelType) { + if(!activity) return []; + let playerData = await getGroupShopServerData(activity); + return playerData?.timer||[]; +} + +export async function setGroupShopToSetSum(arr: { activityId: number, itemId: number, sum: number }[]) { + console.log('###### setGroupShopToSetSum', JSON.stringify(arr)); + for(let { activityId, itemId, sum } of arr) { + let serverRecord = await ActivityGroupShopRecModel.setSum(activityId, itemId, sum); + if(serverRecord) { + let activityData = await getActivityById(activityId); + let playerData = new GroupShopData(activityData, 0, 0); + playerData.setRecords([serverRecord]); + + let item = playerData.findItemById(itemId); + let nextDiscount = item.getCurDiscount(); + // 推送频道 + await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId, sum, itemId, curDiscount: nextDiscount }); + } + } +} + +export async function refundGroupShop(isDebug = false) { + console.log('###### refundGroupShop') + let activities = await ActivityModel.findActivityByType(ACTIVITY_TYPE.GROUP_SHOP); + + for(let activityData of activities) { + let hasRefund = await ActivityGroupShopRefundModel.check(activityData.activityId); + if(!isDebug && hasRefund) continue; + + let playerData = await getGroupShopServerData(activityData); + if(!isDebug && playerData.endTime >= Date.now()) continue; + + let items = playerData.items||[]; + let refundRecs: RefundRec[] = []; + for(let item of items) { + let curDiscount = item.getCurDiscount(); + let playerRecords = await ActivityGroupShopUserRecModel.findByPrice(activityData.activityId, item.itemId, item.getCurDiscount().price); + for(let { roleId, records } of playerRecords) { + let rewards: {id: number, count: number}[] = [], sumGold = 0; + for(let { price, buyCnt } of records) { + if(price <= curDiscount.price) continue; + let diff = (price - curDiscount.price) * buyCnt; + rewards.push(getGoldObject(diff)); + sumGold += diff; + refundRecs.push({ roleId, itemId: item.itemId, diff }); + } + let itemName = gameData.goods.get(item.id)?.name?? `${item.id}`; + let resultDiscount = curDiscount.discount; + await sendMailByContent(MAIL_TYPE.GROUP_SHOP_REFUND, roleId, { goods: rewards, params: [itemName, `${resultDiscount}`, `${sumGold}`] }); + } + } + console.log('###### refundGroupShop refund complete', activityData.activityId) + await ActivityGroupShopRefundModel.refund(activityData.activityId, refundRecs); + } +} diff --git a/game-server/app/services/activity/growthFundService.ts b/game-server/app/services/activity/growthFundService.ts index d4f4612c1..af512e694 100644 --- a/game-server/app/services/activity/growthFundService.ts +++ b/game-server/app/services/activity/growthFundService.ts @@ -1,207 +1,207 @@ -import { ACTIVITY_TYPE, STATUS, TASK_TYPE } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityGrowthFundModel, ActivityGrowthFundModelType } from '../../db/ActivityGrowthFund'; -import { ActivityBuyRecordsModel } from '../../db/ActivityBuyRecords'; -import { RoleModel } from '../../db/Role'; -import { GrowthFundData } from '../../domain/activityField/growthFundField'; -import { ServerlistModel } from '../../db/Serverlist'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { RougelikeExtendModel } from '../../db/RougelikeExtend'; -import { AuthorBookModel } from '../../db/AuthorBook'; -import * as util from 'util'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ -/*ACTIVITY_TYPE类型 - GROWTH_FUND_MAIN = 6, // 主线成长基金 - GROWTH_FUND_MAIN_VIP = 7, // 主线成长基金(高阶) - GROWTH_FUND_TOWER = 8, // 镇念塔成长基金 - GROWTH_FUND_TOWER_VIP = 9, // 镇念塔成长基金(高阶) - GROWTH_FUND_MAIN_ELITE = 10, // 精英成长基金 - GROWTH_FUND_MAIN_ELITE_VIP = 11, // 精英成长基金(高阶) - GROWTH_FUND_ROUGE = 60, //学宫普通密卷 - GROWTH_FUND_ROUGE_VIP = 61, //学宫高级密卷 - GROWTH_FUND_AUTHOR = 62, //列传普通密卷 - GROWTH_FUND_AUTHOR_VIP = 63, //列传高级密卷 - -*/ -export async function growthFundActivity(type: number, serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, type); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0] - let playerData = await getPlayerGrowthFundData(activityData.activityId, serverId, roleId); - if (playerData.isComplete()) { - return null; - } - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerGrowthFundData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecords: ActivityGrowthFundModelType[] = await ActivityGrowthFundModel.findData(activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GrowthFundData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - if (playerData.isVipActivity()) {//vip高阶需要购买 - let buyRecords = await ActivityBuyRecordsModel.findRecordsByActivityId(activityData.activityId, roleId); - playerData.initBuyRecords(buyRecords); - } - - let activityType = activityData.type; - switch (activityType) { - case ACTIVITY_TYPE.GROWTH_FUND_MAIN://主线 - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP://主线vip - { - let role = await RoleModel.findByRoleId(roleId); - let { warStar = new Array<{ id: number, warType: number, star: number }>() } = role; - let warIDs = warStar.map(cur => cur.id); - for (let page of playerData.list) { - for (let item of page.items) { - if (item.taskType == TASK_TYPE.BATTLE_MAIN) { - let index = warIDs.findIndex(id => { return id === item.taskParamArray[1] }) - if (index != -1) { - item.isComplete = true; - } - } - } - } - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_TOWER://镇念塔 - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP:////镇念塔vip - { - let { towerLv } = await RoleModel.findByRoleId(roleId); - for (let page of playerData.list) { - for (let item of page.items) { - if (item.taskType == TASK_TYPE.BATTLE_TOWER_LV) { - if (towerLv >= item.condition) { - item.isComplete = true; - } - } - } - } - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: //精英 - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP: //精英VIP - { - let role = await RoleModel.findByRoleId(roleId); - let { warStar = new Array<{ id: number, warType: number, star: number }>() } = role; - let warIDs = warStar.map(cur => cur.id); - for (let page of playerData.list) { - for (let item of page.items) { - if (item.taskType == TASK_TYPE.BATTLE_MAIN_ELITE) { - let index = warIDs.findIndex(id => { return id === item.taskParamArray[1] }) - if (index != -1) { - item.isComplete = true; - } - } - } - } - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE: //学宫普通密卷 - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP: //学宫高级密卷 - { - const dbRougeExtends = await RougelikeExtendModel.findByRoleId(roleId); - if (dbRougeExtends.length <= 0) break; - const limitIdMap = dbRougeExtends.reduce((result, cur) => { result.set(cur.limitId, cur.limitId); return result; }, new Map()); - for (let page of playerData.list) { - for (let item of page.items) { - if (item.taskType == TASK_TYPE.FUND_ROUGE) { - if (limitIdMap.has(item.taskParamArray[0])) item.isComplete = true; - } - } - } - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR: //列传普通密卷 - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP: //列传高级密卷 - { - const progress = await AuthorBookModel.findProgressByRoleId(roleId); - for (let page of playerData.list) { - for (let item of page.items) { - if (item.taskType == TASK_TYPE.FUND_AUTHOR) { - if (progress >= item.taskParamArray[0]) item.isComplete = true; - } - } - } - break; - } - - default: - break; - } - - return playerData; -} - - - - -/** - * 购买高阶版 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeGrowthFund(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP - && activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP - && activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP - && activityData.type != ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP - && activityData.type != ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP ) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GrowthFundData(activityData, createTime, serverTime); - let pageData = playerData.findPageByProductID(productID); - let pageIndex = pageData.pageIndex; - let checkResult = await ActivityBuyRecordsModel.checkRecord(activityId, roleId, activityData.type, pageIndex); - if(checkResult) return STATUS.ORDER_CANNOT_BUY; - - await ActivityBuyRecordsModel.addRecord(activityId, roleId, activityData.type, pageIndex, true); - return { - code: 0, - data: Object.assign({}, { item: { pageIndex }, activityId: activityId }) - } -} - -export async function checkGrowthFund(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GrowthFundData(activityData, createTime, serverTime); - let pageData = playerData.findPageByProductID(productID); - let pageIndex = pageData.pageIndex; - let checkResult = await ActivityBuyRecordsModel.checkRecord(activityData.activityId, roleId, activityData.type, pageIndex); - return !checkResult; -} \ No newline at end of file +import { ACTIVITY_TYPE, STATUS, TASK_TYPE } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityGrowthFundModel, ActivityGrowthFundModelType } from '@db/ActivityGrowthFund'; +import { ActivityBuyRecordsModel } from '@db/ActivityBuyRecords'; +import { RoleModel } from '@db/Role'; +import { GrowthFundData } from '@domain/activityField/growthFundField'; +import { ServerlistModel } from '@db/Serverlist'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { RougelikeExtendModel } from '@db/RougelikeExtend'; +import { AuthorBookModel } from '@db/AuthorBook'; +import * as util from 'util'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ +/*ACTIVITY_TYPE类型 + GROWTH_FUND_MAIN = 6, // 主线成长基金 + GROWTH_FUND_MAIN_VIP = 7, // 主线成长基金(高阶) + GROWTH_FUND_TOWER = 8, // 镇念塔成长基金 + GROWTH_FUND_TOWER_VIP = 9, // 镇念塔成长基金(高阶) + GROWTH_FUND_MAIN_ELITE = 10, // 精英成长基金 + GROWTH_FUND_MAIN_ELITE_VIP = 11, // 精英成长基金(高阶) + GROWTH_FUND_ROUGE = 60, //学宫普通密卷 + GROWTH_FUND_ROUGE_VIP = 61, //学宫高级密卷 + GROWTH_FUND_AUTHOR = 62, //列传普通密卷 + GROWTH_FUND_AUTHOR_VIP = 63, //列传高级密卷 + +*/ +export async function growthFundActivity(type: number, serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, type); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0] + let playerData = await getPlayerGrowthFundData(activityData.activityId, serverId, roleId); + if (playerData.isComplete()) { + return null; + } + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerGrowthFundData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecords: ActivityGrowthFundModelType[] = await ActivityGrowthFundModel.findData(activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GrowthFundData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + if (playerData.isVipActivity()) {//vip高阶需要购买 + let buyRecords = await ActivityBuyRecordsModel.findRecordsByActivityId(activityData.activityId, roleId); + playerData.initBuyRecords(buyRecords); + } + + let activityType = activityData.type; + switch (activityType) { + case ACTIVITY_TYPE.GROWTH_FUND_MAIN://主线 + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP://主线vip + { + let role = await RoleModel.findByRoleId(roleId); + let { warStar = new Array<{ id: number, warType: number, star: number }>() } = role; + let warIDs = warStar.map(cur => cur.id); + for (let page of playerData.list) { + for (let item of page.items) { + if (item.taskType == TASK_TYPE.BATTLE_MAIN) { + let index = warIDs.findIndex(id => { return id === item.taskParamArray[1] }) + if (index != -1) { + item.isComplete = true; + } + } + } + } + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_TOWER://镇念塔 + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP:////镇念塔vip + { + let { towerLv } = await RoleModel.findByRoleId(roleId); + for (let page of playerData.list) { + for (let item of page.items) { + if (item.taskType == TASK_TYPE.BATTLE_TOWER_LV) { + if (towerLv >= item.condition) { + item.isComplete = true; + } + } + } + } + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: //精英 + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP: //精英VIP + { + let role = await RoleModel.findByRoleId(roleId); + let { warStar = new Array<{ id: number, warType: number, star: number }>() } = role; + let warIDs = warStar.map(cur => cur.id); + for (let page of playerData.list) { + for (let item of page.items) { + if (item.taskType == TASK_TYPE.BATTLE_MAIN_ELITE) { + let index = warIDs.findIndex(id => { return id === item.taskParamArray[1] }) + if (index != -1) { + item.isComplete = true; + } + } + } + } + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE: //学宫普通密卷 + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP: //学宫高级密卷 + { + const dbRougeExtends = await RougelikeExtendModel.findByRoleId(roleId); + if (dbRougeExtends.length <= 0) break; + const limitIdMap = dbRougeExtends.reduce((result, cur) => { result.set(cur.limitId, cur.limitId); return result; }, new Map()); + for (let page of playerData.list) { + for (let item of page.items) { + if (item.taskType == TASK_TYPE.FUND_ROUGE) { + if (limitIdMap.has(item.taskParamArray[0])) item.isComplete = true; + } + } + } + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR: //列传普通密卷 + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP: //列传高级密卷 + { + const progress = await AuthorBookModel.findProgressByRoleId(roleId); + for (let page of playerData.list) { + for (let item of page.items) { + if (item.taskType == TASK_TYPE.FUND_AUTHOR) { + if (progress >= item.taskParamArray[0]) item.isComplete = true; + } + } + } + break; + } + + default: + break; + } + + return playerData; +} + + + + +/** + * 购买高阶版 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeGrowthFund(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP + && activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP + && activityData.type !== ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP + && activityData.type != ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP + && activityData.type != ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP ) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GrowthFundData(activityData, createTime, serverTime); + let pageData = playerData.findPageByProductID(productID); + let pageIndex = pageData.pageIndex; + let checkResult = await ActivityBuyRecordsModel.checkRecord(activityId, roleId, activityData.type, pageIndex); + if(checkResult) return STATUS.ORDER_CANNOT_BUY; + + await ActivityBuyRecordsModel.addRecord(activityId, roleId, activityData.type, pageIndex, true); + return { + code: 0, + data: Object.assign({}, { item: { pageIndex }, activityId: activityId }) + } +} + +export async function checkGrowthFund(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GrowthFundData(activityData, createTime, serverTime); + let pageData = playerData.findPageByProductID(productID); + let pageIndex = pageData.pageIndex; + let checkResult = await ActivityBuyRecordsModel.checkRecord(activityData.activityId, roleId, activityData.type, pageIndex); + return !checkResult; +} diff --git a/game-server/app/services/activity/growthService.ts b/game-server/app/services/activity/growthService.ts index 225201627..5df6bc6c6 100644 --- a/game-server/app/services/activity/growthService.ts +++ b/game-server/app/services/activity/growthService.ts @@ -1,59 +1,59 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityGrowthModel, ActivityGrowthModelType } from '../../db/ActivityGrowth'; -import { ActivityGrowthPointModel, ActivityGrowthPointModelType } from '../../db/ActivityGrowthPoint'; -import { HeroModel } from '../../db/Hero'; -import { GrowthData } from '../../domain/activityField/growthField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function growthActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_GROWTH); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityData.activityId, roleId); - let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityData.activityId, roleId); - - let userHeroes = await HeroModel.findByRole(roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GrowthData(activityData, createTime, serverTime); - await playerData.setPlayerRecords(playerRecords, roleId, userHeroes); - playerData.setPlayerPointRecord(playerPointRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerGrowthData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - let playerRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); - let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); - - let userHeroes = await HeroModel.findByRole(roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GrowthData(activityData, createTime, serverTime); - await playerData.setPlayerRecords(playerRecords, roleId, userHeroes); - playerData.setPlayerPointRecord(playerPointRecord); - return playerData; -} - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityGrowthModel, ActivityGrowthModelType } from '@db/ActivityGrowth'; +import { ActivityGrowthPointModel, ActivityGrowthPointModelType } from '@db/ActivityGrowthPoint'; +import { HeroModel } from '@db/Hero'; +import { GrowthData } from '@domain/activityField/growthField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function growthActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_GROWTH); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityData.activityId, roleId); + let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityData.activityId, roleId); + + let userHeroes = await HeroModel.findByRole(roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GrowthData(activityData, createTime, serverTime); + await playerData.setPlayerRecords(playerRecords, roleId, userHeroes); + playerData.setPlayerPointRecord(playerPointRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerGrowthData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + let playerRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); + let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); + + let userHeroes = await HeroModel.findByRole(roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GrowthData(activityData, createTime, serverTime); + await playerData.setPlayerRecords(playerRecords, roleId, userHeroes); + playerData.setPlayerPointRecord(playerPointRecord); + return playerData; +} + + diff --git a/game-server/app/services/activity/guildPayService.ts b/game-server/app/services/activity/guildPayService.ts index ffd55df15..c293b5052 100644 --- a/game-server/app/services/activity/guildPayService.ts +++ b/game-server/app/services/activity/guildPayService.ts @@ -1,106 +1,106 @@ -import { ACTIVITY_TYPE } from "../../consts"; -import { ActivityGuildPayModel } from "../../db/ActivityGuildPay"; -import { RoleType } from "../../db/Role"; -import { GuildPayData } from "../../domain/activityField/guildPay"; -import { getActivitiesByType, getActivityById, pushActivities, pushActivitiesToGuild, pushActivityInter } from "./activityService"; -import { ServerlistModel } from '../../db/Serverlist'; -import { ActivityGuildPayRecordModel } from "../../db/ActivityGuildPayRecord"; -import { getServerCreateTime } from "../redisService"; - - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getGuildPayData(serverId: number, activityId: number, roleId: string, guildCode: string) { - let activityData = await getActivityById(activityId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new GuildPayData(activityData, 0, serverTime); - let receiveRecord = await ActivityGuildPayRecordModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setReceiveRecord(receiveRecord); - if(guildCode) { - let guildRecord = await ActivityGuildPayModel.findData(serverId, activityId, playerData.roundIndex, guildCode); - playerData.setGuildRecord(guildRecord); - } - - return playerData; -} - -export async function getGuildPayDataShow(serverId: number, activityId: number, roleId: string, guildCode: string) { - let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null; -} - -export async function addGuildPay(role: RoleType, price: number) { - let { hasGuild, roleId, roleName, serverId, guildCode } = role; - if(!hasGuild) return; - let serverTime = await getServerCreateTime(serverId); - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let { activityId, type: activityType } = activityData; - let obj = new GuildPayData(activityData, 0, serverTime); - if(obj && obj.canPay()) { - let { isNew, result } = await ActivityGuildPayModel.addRecord(serverId, activityId, obj.roundIndex, guildCode, { - roleId, roleName, price, hasQuit: false - }); - if(isNew) { - let { memberRecord = [] } = result; - let payMemberCnt = memberRecord.filter(member => !member.hasQuit).length; - pushResult.push({ activityId, activityType, param: { payMember: roleName, payMemberCnt } }); - } - } - } - console.log('##### addGuildPay', pushResult.length) - await pushActivitiesToGuild(pushResult, guildCode); -} - -export async function guildPayQuitGuild(serverId: number, guildCode: string, roleId: string) { - if(!guildCode) return; - - let serverTime = await getServerCreateTime(serverId); - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let { activityId, type: activityType } = activityData; - let obj = new GuildPayData(activityData, 0, serverTime); - if(obj && obj.canPay()) { - let result = await ActivityGuildPayModel.quitGuild(serverId, activityId, obj.roundIndex, guildCode, roleId); - if(result) { - let { memberRecord = [] } = result; - let records = memberRecord.filter(member => !member.hasQuit); - let payRecord = records.map(member => member.roleName); - pushResult.push({ activityId, activityType, param: { payRecord, payMemberCnt: payRecord.length } }); - } - } - } - await pushActivitiesToGuild(pushResult, guildCode); -} - -export async function changeGuildActivity(guildCode: string, serverId: number, roleId: string, sid: string) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let { activityId, type: activityType } = activityData; - let obj = await getGuildPayData(serverId, activityId, roleId, guildCode); - pushResult.push({ activityId, activityType, param: { payRecord: obj.payRecord, payMemberCnt: obj.payMemberCnt } }); - } - await pushActivities(pushResult, roleId, sid); -} - -export async function guildDismisActivity(guildCode: string, serverId: number) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let { activityId, type: activityType } = activityData; - pushResult.push({ activityId, activityType, param: { payRecord: [], payMemberCnt: 0 } }); - } - await pushActivitiesToGuild(pushResult, guildCode); -} \ No newline at end of file +import { ACTIVITY_TYPE } from "@consts"; +import { ActivityGuildPayModel } from "@db/ActivityGuildPay"; +import { RoleType } from "@db/Role"; +import { GuildPayData } from "@domain/activityField/guildPay"; +import { getActivitiesByType, getActivityById, pushActivities, pushActivitiesToGuild, pushActivityInter } from "./activityService"; +import { ServerlistModel } from '@db/Serverlist'; +import { ActivityGuildPayRecordModel } from "@db/ActivityGuildPayRecord"; +import { getServerCreateTime } from "../redisService"; + + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getGuildPayData(serverId: number, activityId: number, roleId: string, guildCode: string) { + let activityData = await getActivityById(activityId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new GuildPayData(activityData, 0, serverTime); + let receiveRecord = await ActivityGuildPayRecordModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setReceiveRecord(receiveRecord); + if(guildCode) { + let guildRecord = await ActivityGuildPayModel.findData(serverId, activityId, playerData.roundIndex, guildCode); + playerData.setGuildRecord(guildRecord); + } + + return playerData; +} + +export async function getGuildPayDataShow(serverId: number, activityId: number, roleId: string, guildCode: string) { + let playerData = await getGuildPayData(serverId, activityId, roleId, guildCode); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null; +} + +export async function addGuildPay(role: RoleType, price: number) { + let { hasGuild, roleId, roleName, serverId, guildCode } = role; + if(!hasGuild) return; + let serverTime = await getServerCreateTime(serverId); + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let { activityId, type: activityType } = activityData; + let obj = new GuildPayData(activityData, 0, serverTime); + if(obj && obj.canPay()) { + let { isNew, result } = await ActivityGuildPayModel.addRecord(serverId, activityId, obj.roundIndex, guildCode, { + roleId, roleName, price, hasQuit: false + }); + if(isNew) { + let { memberRecord = [] } = result; + let payMemberCnt = memberRecord.filter(member => !member.hasQuit).length; + pushResult.push({ activityId, activityType, param: { payMember: roleName, payMemberCnt } }); + } + } + } + console.log('##### addGuildPay', pushResult.length) + await pushActivitiesToGuild(pushResult, guildCode); +} + +export async function guildPayQuitGuild(serverId: number, guildCode: string, roleId: string) { + if(!guildCode) return; + + let serverTime = await getServerCreateTime(serverId); + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let { activityId, type: activityType } = activityData; + let obj = new GuildPayData(activityData, 0, serverTime); + if(obj && obj.canPay()) { + let result = await ActivityGuildPayModel.quitGuild(serverId, activityId, obj.roundIndex, guildCode, roleId); + if(result) { + let { memberRecord = [] } = result; + let records = memberRecord.filter(member => !member.hasQuit); + let payRecord = records.map(member => member.roleName); + pushResult.push({ activityId, activityType, param: { payRecord, payMemberCnt: payRecord.length } }); + } + } + } + await pushActivitiesToGuild(pushResult, guildCode); +} + +export async function changeGuildActivity(guildCode: string, serverId: number, roleId: string, sid: string) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let { activityId, type: activityType } = activityData; + let obj = await getGuildPayData(serverId, activityId, roleId, guildCode); + pushResult.push({ activityId, activityType, param: { payRecord: obj.payRecord, payMemberCnt: obj.payMemberCnt } }); + } + await pushActivities(pushResult, roleId, sid); +} + +export async function guildDismisActivity(guildCode: string, serverId: number) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.GUILD_PAY); + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let { activityId, type: activityType } = activityData; + pushResult.push({ activityId, activityType, param: { payRecord: [], payMemberCnt: 0 } }); + } + await pushActivitiesToGuild(pushResult, guildCode); +} diff --git a/game-server/app/services/activity/limitPackageService.ts b/game-server/app/services/activity/limitPackageService.ts index 19e57e3b5..929597b5f 100644 --- a/game-server/app/services/activity/limitPackageService.ts +++ b/game-server/app/services/activity/limitPackageService.ts @@ -1,157 +1,157 @@ -import moment = require('moment'); -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityShopModel, ActivityShopModelType } from '../../db/ActivityShop'; -import { RoleModel } from '../../db/Role'; -import { ServerlistModel } from '../../db/Serverlist'; -import { LimitShopData } from '../../domain/activityField/limitShopField'; -import { deltaDays } from '../../pubUtils/util'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { addReward, stringToRewardParam } from './giftPackageService'; - -/** - * 获取新手玩家限购礼包活动数据 新手限定作为开服七天乐的延伸礼包。只存在于开服前七天,七天时间过去,玩家无法购买 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function newPlayerLimitPackageActivity(serverId: number, roleId: string) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE); - if (activities.length == 0) { - return null; - } - let activityData = activities[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LimitShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 每日、每周限购礼包活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerLimitPackageData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LimitShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -/** - * 获取每日/每周限购礼包数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function limitPackageActivity(serverId: number, roleId: string, type: number) { - let activityArray = await getActivitiesByType(serverId, type); - activityArray = activityArray.sort((a, b) => { - return b.activityId - a.activityId - }); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerData = await getPlayerLimitPackageData(activityData.activityId, serverId, roleId); - return playerData -} - -/** - * 玩家活动第几天 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function newPlayerActivityDays(roleId: string) { - let { createTime } = await RoleModel.findByRoleId(roleId); - let createDate = moment(createTime * 1000).toDate(); - let todayIndex = deltaDays(createDate, new Date, true) + 1; - return todayIndex; -} - - - - -/** - * 结算购买的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeLimitPackageReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE && - activityData.type !== ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY && - activityData.type !== ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LimitShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - - let item = playerData.findItemByProductID(productID); - if (!item) { - return STATUS.ACTIVITY_NO_PRODUCT; - } - if (item.countMax > 0 && item.buyCount >= item.countMax) { - return STATUS.ACTIVITY_MAX_COUNT; - } - - let rewardArray = stringToRewardParam(item.reward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); - - await ActivityShopModel.addRecord(activityId, roleId, playerData.roundIndex, item.id, 1); - - item.buyCount += 1; - return { - code: 0, - data: Object.assign(result, { item: item, activityId: activityId }) - } -} - -export async function checkLimitPackageCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LimitShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - - let item = playerData.findItemByProductID(productID); - if (!item) return false - if (item.countMax > 0 && item.buyCount >= item.countMax) return false; - return true; -} \ No newline at end of file +import moment = require('moment'); +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityShopModel, ActivityShopModelType } from '@db/ActivityShop'; +import { RoleModel } from '@db/Role'; +import { ServerlistModel } from '@db/Serverlist'; +import { LimitShopData } from '@domain/activityField/limitShopField'; +import { deltaDays } from '@pubUtils/util'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { addReward, stringToRewardParam } from './giftPackageService'; + +/** + * 获取新手玩家限购礼包活动数据 新手限定作为开服七天乐的延伸礼包。只存在于开服前七天,七天时间过去,玩家无法购买 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function newPlayerLimitPackageActivity(serverId: number, roleId: string) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE); + if (activities.length == 0) { + return null; + } + let activityData = activities[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LimitShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 每日、每周限购礼包活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerLimitPackageData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LimitShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +/** + * 获取每日/每周限购礼包数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function limitPackageActivity(serverId: number, roleId: string, type: number) { + let activityArray = await getActivitiesByType(serverId, type); + activityArray = activityArray.sort((a, b) => { + return b.activityId - a.activityId + }); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerData = await getPlayerLimitPackageData(activityData.activityId, serverId, roleId); + return playerData +} + +/** + * 玩家活动第几天 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function newPlayerActivityDays(roleId: string) { + let { createTime } = await RoleModel.findByRoleId(roleId); + let createDate = moment(createTime * 1000).toDate(); + let todayIndex = deltaDays(createDate, new Date, true) + 1; + return todayIndex; +} + + + + +/** + * 结算购买的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeLimitPackageReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE && + activityData.type !== ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY && + activityData.type !== ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LimitShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + + let item = playerData.findItemByProductID(productID); + if (!item) { + return STATUS.ACTIVITY_NO_PRODUCT; + } + if (item.countMax > 0 && item.buyCount >= item.countMax) { + return STATUS.ACTIVITY_MAX_COUNT; + } + + let rewardArray = stringToRewardParam(item.reward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_LIMIT_PACKAGE); + + await ActivityShopModel.addRecord(activityId, roleId, playerData.roundIndex, item.id, 1); + + item.buyCount += 1; + return { + code: 0, + data: Object.assign(result, { item: item, activityId: activityId }) + } +} + +export async function checkLimitPackageCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LimitShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityShopModelType = await ActivityShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + + let item = playerData.findItemByProductID(productID); + if (!item) return false + if (item.countMax > 0 && item.buyCount >= item.countMax) return false; + return true; +} diff --git a/game-server/app/services/activity/luckyService.ts b/game-server/app/services/activity/luckyService.ts index 7195ac475..4d4c92bc4 100644 --- a/game-server/app/services/activity/luckyService.ts +++ b/game-server/app/services/activity/luckyService.ts @@ -1,35 +1,35 @@ -import { ActivityLuckyModel } from "../../db/ActivityLuckyRec"; -import { LuckyData } from "../../domain/activityField/luckyField"; -import { shouldRefresh } from "../../pubUtils/util"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPlayerLuckyData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LuckyData(activityData, createTime, serverTime); - - let playerRecord = await ActivityLuckyModel.findByActivityId(serverId, activityId, roleId, playerData.roundIndex); - if(playerRecord && shouldRefresh(playerRecord.refTodayCount, new Date())) { - playerRecord = await ActivityLuckyModel.refreshTodayCount(serverId, activityId, roleId, playerData.roundIndex); - } - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -export async function getPlayerLuckyDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerLuckyData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityLuckyModel } from "@db/ActivityLuckyRec"; +import { LuckyData } from "@domain/activityField/luckyField"; +import { shouldRefresh } from "@pubUtils/util"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPlayerLuckyData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LuckyData(activityData, createTime, serverTime); + + let playerRecord = await ActivityLuckyModel.findByActivityId(serverId, activityId, roleId, playerData.roundIndex); + if(playerRecord && shouldRefresh(playerRecord.refTodayCount, new Date())) { + playerRecord = await ActivityLuckyModel.refreshTodayCount(serverId, activityId, roleId, playerData.roundIndex); + } + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +export async function getPlayerLuckyDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerLuckyData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/luckyTurntableService.ts b/game-server/app/services/activity/luckyTurntableService.ts index 113cb4d59..88de816d0 100644 --- a/game-server/app/services/activity/luckyTurntableService.ts +++ b/game-server/app/services/activity/luckyTurntableService.ts @@ -1,35 +1,35 @@ -import { ActivityTurntableModel } from "../../db/ActivityTurntableRec"; -import { LuckyTurntableData } from "../../domain/activityField/luckyTurntableField"; -import { shouldRefresh } from "../../pubUtils/util"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPlayerLuckyTurntableData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new LuckyTurntableData(activityData, createTime, serverTime); - - let playerRecord = await ActivityTurntableModel.findByActivityId(serverId, activityId, roleId, playerData.roundIndex); - if(playerRecord && shouldRefresh(playerRecord.refTodayCount, new Date())) { - playerRecord = await ActivityTurntableModel.refreshTodayCount(serverId, activityId, roleId, playerData.roundIndex); - } - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -export async function getPlayerLuckyTurntableDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityTurntableModel } from "@db/ActivityTurntableRec"; +import { LuckyTurntableData } from "@domain/activityField/luckyTurntableField"; +import { shouldRefresh } from "@pubUtils/util"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPlayerLuckyTurntableData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new LuckyTurntableData(activityData, createTime, serverTime); + + let playerRecord = await ActivityTurntableModel.findByActivityId(serverId, activityId, roleId, playerData.roundIndex); + if(playerRecord && shouldRefresh(playerRecord.refTodayCount, new Date())) { + playerRecord = await ActivityTurntableModel.refreshTodayCount(serverId, activityId, roleId, playerData.roundIndex); + } + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +export async function getPlayerLuckyTurntableDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerLuckyTurntableData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/midAutumnService.ts b/game-server/app/services/activity/midAutumnService.ts index 9de906635..febc72cd1 100644 --- a/game-server/app/services/activity/midAutumnService.ts +++ b/game-server/app/services/activity/midAutumnService.ts @@ -1,38 +1,38 @@ -import { ActivityMidAutumnRecModel } from "../../db/ActivityMidAutumnRec"; -import { MidAutumnData } from "../../domain/activityField/midAutumnField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMidAutumnData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MidAutumnData(activityData, createTime, serverTime); - let playerRecord = await ActivityMidAutumnRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMidAutumnDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityMidAutumnRecModel } from "@db/ActivityMidAutumnRec"; +import { MidAutumnData } from "@domain/activityField/midAutumnField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMidAutumnData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MidAutumnData(activityData, createTime, serverTime); + let playerRecord = await ActivityMidAutumnRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMidAutumnDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerMidAutumnData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/miniGameService.ts b/game-server/app/services/activity/miniGameService.ts index c3c7b0036..f479de355 100644 --- a/game-server/app/services/activity/miniGameService.ts +++ b/game-server/app/services/activity/miniGameService.ts @@ -1,46 +1,46 @@ -import { ActivityForgeModel } from "../../db/ActivityForge"; -import { ActivityMiniGameModel } from "../../db/ActivityMiniGame"; -import { ActivityMiniGameRecModel } from "../../db/ActivityMiniGameRec"; -import { MiniGameData } from "../../domain/activityField/miniGameField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMiniGameData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MiniGameData(activityData, createTime, serverTime); - let playerRecord = await ActivityMiniGameModel.findData(serverId, activityId, playerData.roundIndex, roleId); - let records = await ActivityMiniGameRecModel.findRecords(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerData(playerRecord); - playerData.setPlayerRecords(records); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMiniGameDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -export function getMetialStr(material: { id: number, count: number }[]) { - return material.map(({id, count}) => `${id}&${count}`).join('|') -} \ No newline at end of file +import { ActivityForgeModel } from "@db/ActivityForge"; +import { ActivityMiniGameModel } from "@db/ActivityMiniGame"; +import { ActivityMiniGameRecModel } from "@db/ActivityMiniGameRec"; +import { MiniGameData } from "@domain/activityField/miniGameField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMiniGameData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MiniGameData(activityData, createTime, serverTime); + let playerRecord = await ActivityMiniGameModel.findData(serverId, activityId, playerData.roundIndex, roleId); + let records = await ActivityMiniGameRecModel.findRecords(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerData(playerRecord); + playerData.setPlayerRecords(records); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMiniGameDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerMiniGameData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +export function getMetialStr(material: { id: number, count: number }[]) { + return material.map(({id, count}) => `${id}&${count}`).join('|') +} diff --git a/game-server/app/services/activity/monopolyService.ts b/game-server/app/services/activity/monopolyService.ts index 4709d5936..cba6bb5be 100644 --- a/game-server/app/services/activity/monopolyService.ts +++ b/game-server/app/services/activity/monopolyService.ts @@ -1,69 +1,69 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivityMonopolyModel, ActivityMonopolyModelType } from '../../db/ActivityMonopoly'; -import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '../../db/ActivityMonopolyLand'; -import { MonopolyData } from '../../domain/activityField/monopolyField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getMonopolyActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.MONOPOLY); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityData.activityId, roleId); - let playerLandData: ActivityMonopolyLandModelType[] = await ActivityMonopolyLandModel.findData(serverId, activityData.activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonopolyData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerMonopolyData, playerLandData); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMonopolyData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - if (!activityData) { - return null; - } - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityData.activityId, roleId); - let playerLandData: ActivityMonopolyLandModelType[] = await ActivityMonopolyLandModel.findData(serverId, activityData.activityId, roleId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonopolyData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerMonopolyData, playerLandData); - return playerData; -} - -/** - * 玩家玩家活动数据 - * - * @param {number} position 当前位置 - * @param {number} addStep 移动步数 - * @param {number} max 最大位置 - * - */ -export function nextPosition(position: number, addStep: number, max: number) { - let temp = (position + addStep) % max; - return (temp == 0) ? max : temp; -} - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivityMonopolyModel, ActivityMonopolyModelType } from '@db/ActivityMonopoly'; +import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '@db/ActivityMonopolyLand'; +import { MonopolyData } from '@domain/activityField/monopolyField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getMonopolyActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.MONOPOLY); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityData.activityId, roleId); + let playerLandData: ActivityMonopolyLandModelType[] = await ActivityMonopolyLandModel.findData(serverId, activityData.activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonopolyData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerMonopolyData, playerLandData); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMonopolyData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + if (!activityData) { + return null; + } + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityData.activityId, roleId); + let playerLandData: ActivityMonopolyLandModelType[] = await ActivityMonopolyLandModel.findData(serverId, activityData.activityId, roleId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonopolyData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerMonopolyData, playerLandData); + return playerData; +} + +/** + * 玩家玩家活动数据 + * + * @param {number} position 当前位置 + * @param {number} addStep 移动步数 + * @param {number} max 最大位置 + * + */ +export function nextPosition(position: number, addStep: number, max: number) { + let temp = (position + addStep) % max; + return (temp == 0) ? max : temp; +} + diff --git a/game-server/app/services/activity/monthlyFundService.ts b/game-server/app/services/activity/monthlyFundService.ts index 372380ec1..866dcc76b 100644 --- a/game-server/app/services/activity/monthlyFundService.ts +++ b/game-server/app/services/activity/monthlyFundService.ts @@ -1,96 +1,96 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "../../consts"; -import { ActivityModelType } from "../../db/Activity"; -import { ActivityMonthlyFundModel } from "../../db/ActivityMonthlyFund"; -import { MonthlyFundData } from "../../domain/activityField/monthlyFundField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; -import { stringToRewardParam, addReward } from "./giftPackageService"; - -/** - * 月基金玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getMonthlyFundData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyFundData(activityData, createTime, serverTime); - let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - -/** - * 月基金 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getMonthlyFundDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getMonthlyFundData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -/** - * 月基金 是否可以购买 - * @param roleId 玩家id - * @param serverId 服 - * @param activityData 活动数据 - * @returns - */ -export async function checkMonthlyFund(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData || activityData.type !== ACTIVITY_TYPE.MONTHLY_FUND) return false; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyFundData(activityData, createTime, serverTime); - let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityData.activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecords); - let page = playerData.findByProductID(productID); - return !page.hasBought; -} - -/** - * 周基金购买 - * @param roleId 玩家id - * @param roleName 玩家名 - * @param sid - * @param serverId 服 - * @param activityId 活动 - * @param productID 商品id - * @returns - */ -export async function makeMonthlyFund(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.MONTHLY_FUND) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyFundData(activityData, createTime, serverTime); - let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityData.activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecords); - let page = playerData.findByProductID(productID); - if(page.hasBought) return STATUS.ORDER_CANNOT_BUY; - - await ActivityMonthlyFundModel.buy(serverId, activityId, roleId, playerData.roundIndex, page.pageIndex, productID); - - let rewardParamArr = stringToRewardParam(page.onceReward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_BUY); - - return { - code: 0, - data: Object.assign(result, { activityId: activityId, pageIndex: page.pageIndex, roundIndex: playerData.roundIndex }) - } -} \ No newline at end of file +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "@consts"; +import { ActivityModelType } from "@db/Activity"; +import { ActivityMonthlyFundModel } from "@db/ActivityMonthlyFund"; +import { MonthlyFundData } from "@domain/activityField/monthlyFundField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; +import { stringToRewardParam, addReward } from "./giftPackageService"; + +/** + * 月基金玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getMonthlyFundData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyFundData(activityData, createTime, serverTime); + let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + +/** + * 月基金 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getMonthlyFundDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getMonthlyFundData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +/** + * 月基金 是否可以购买 + * @param roleId 玩家id + * @param serverId 服 + * @param activityData 活动数据 + * @returns + */ +export async function checkMonthlyFund(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData || activityData.type !== ACTIVITY_TYPE.MONTHLY_FUND) return false; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyFundData(activityData, createTime, serverTime); + let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityData.activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecords); + let page = playerData.findByProductID(productID); + return !page.hasBought; +} + +/** + * 周基金购买 + * @param roleId 玩家id + * @param roleName 玩家名 + * @param sid + * @param serverId 服 + * @param activityId 活动 + * @param productID 商品id + * @returns + */ +export async function makeMonthlyFund(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.MONTHLY_FUND) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyFundData(activityData, createTime, serverTime); + let playerRecords = await ActivityMonthlyFundModel.findData(serverId, activityData.activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecords); + let page = playerData.findByProductID(productID); + if(page.hasBought) return STATUS.ORDER_CANNOT_BUY; + + await ActivityMonthlyFundModel.buy(serverId, activityId, roleId, playerData.roundIndex, page.pageIndex, productID); + + let rewardParamArr = stringToRewardParam(page.onceReward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_BUY); + + return { + code: 0, + data: Object.assign(result, { activityId: activityId, pageIndex: page.pageIndex, roundIndex: playerData.roundIndex }) + } +} diff --git a/game-server/app/services/activity/monthlyTicketService.ts b/game-server/app/services/activity/monthlyTicketService.ts index f5ab783ef..f229da985 100644 --- a/game-server/app/services/activity/monthlyTicketService.ts +++ b/game-server/app/services/activity/monthlyTicketService.ts @@ -1,240 +1,240 @@ -import { ACTIVITY_TYPE, HANG_UP_CONSTS, ITEM_CHANGE_REASON, MAIL_TYPE, REFRESH_TIME, STATUS } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityMonthlyTicketModel, ActivityMonthlyTicketModelType } from '../../db/ActivityMonthlyTicket'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { MonthlyTicketData } from '../../domain/activityField/monthlyTicketField'; -import { addReward, stringToRewardParam } from './giftPackageService'; -import moment = require('moment'); -import { ServerlistModel } from '../../db/Serverlist'; -import { sendMailByContent } from './../mailService'; -import { RoleModel, RoleType } from '../../db/Role'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { RewardInter } from '../../pubUtils/interface'; -import { DUNGEON_CONST, PVP, VIP } from '../../pubUtils/dicParam'; -import { cal, } from '../../pubUtils/util'; -import { stringWithTypeToRewardInter } from '../../pubUtils/roleUtil'; -import { pinus } from 'pinus'; -import { getGoldId } from '../role/rewardService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function monthlyTicketActivity(serverId: number, roleId: string, type: number) { - let activityArray = await getActivitiesByType(serverId, type); - activityArray = activityArray.sort((a, b) => { - return b.activityId - a.activityId - }); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityData.activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyTicketData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - - if ((playerData.price > 0 && playerData.isOpen) || playerData.price === 0) { - if (playerData.todayIndex - 1 > playerData.dayIndex) {//过期还没领取 - //下发邮件奖励 - for (let i = playerData.dayIndex + 1; i < playerData.todayIndex; i++) { - let goods = stringWithTypeToRewardInter(playerData.baseReward) - await sendMailByContent(MAIL_TYPE.MONTHLY_REWARD, roleId, { params: [], goods }); - } - await ActivityMonthlyTicketModel.setDayIndex(serverId, roleId, playerData.activityId, playerData.todayIndex - 1); - playerData.dayIndex = playerData.todayIndex - 1; - } - } - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMonthlyTicketData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyTicketData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家月卡当天的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerMonthlyTicketDayReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number,) { - let activityData: ActivityModelType = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyTicketData(activityData, createTime, serverTime); - - let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityId); - if (playerData.price > 0 && !playerRecord) {//没有购买过 - return null; - } - - playerData.setPlayerRecords(playerRecord); - if ((playerData.price > 0 && playerData.isOpen) || playerData.price == 0) { - if (playerData.todayIndex > playerData.dayIndex) {//今天还没领取 - await ActivityMonthlyTicketModel.setDayIndex(serverId, roleId, activityId, playerData.todayIndex); - let rewardParamArr: Array = stringToRewardParam(playerData.baseReward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.MONTHLY_TICKET_DAILY) - return result - } - } - return null -} - -/** - * 结算首次购买月卡的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeMonthlyTicketReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (activityData.type !== ACTIVITY_TYPE.MONTHLY_TICKET_1 && activityData.type !== ACTIVITY_TYPE.MONTHLY_TICKET_2) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - - if(!await checkMonthlyTicket(roleId, serverId, activityData)) return STATUS.ORDER_CANNOT_BUY; - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new MonthlyTicketData(activityData, createTime, serverTime); - - let endTime = playerData.isForever? moment(playerData.endTime).toDate(): moment(new Date()).startOf('d').add(playerData.days, 'day').add(REFRESH_TIME, 'h').toDate(); - console.log('endTime', playerData.isForever, moment(new Date()).startOf('d'), endTime, playerData.days) - - await ActivityMonthlyTicketModel.buyMonthlyTicket(serverId, roleId, activityId, activityData.type, endTime, playerData.isForever) - if(activityData.type == ACTIVITY_TYPE.MONTHLY_TICKET_2) { - let role = await RoleModel.buyForeverTicket(roleId); - if(sid) await pinus.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, vipStartTime: role.vipStartTime }]); - } - let firstReward = playerData.firstReward; - let rewardParamArr: Array = stringToRewardParam(firstReward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.MONTHLY_TICKET_FIRST) - return { - code: 0, - data: Object.assign(result, { item: { isOpen: true, todayIndex: 1 }, activityId: activityData.activityId }) - } -} - -// 是否可以购买月卡 -export async function checkMonthlyTicket(roleId: string, serverId: number, activityData: ActivityModelType) { - if(!activityData) return false; - - let result = await ActivityMonthlyTicketModel.checkHasBought(serverId, roleId, activityData.activityId, activityData.type); - return !result; -} - -// 军团捐献消耗 -export function getVipDonateConsume(originConsume: RewardInter, vipStartTime: number) { - if(vipStartTime > 0) { - if(originConsume.id == getGoldId()) { - return [{ id: originConsume.id, count: Math.floor(originConsume.count * VIP.VIP_GUILD_DONATE_COST_GOLD_RATIO) }]; - } else { - return [originConsume]; - } - } else { - return [originConsume]; - } -} - -export function getVipHungupReward(startTime: number, endTime: number, baseReward: RewardInter[], notReceivedGoods: {gid: number, count: number}[], vipStartTime: number) { - let multi = Math.floor((endTime - startTime) / HANG_UP_CONSTS.UNIT_TIME); - if(vipStartTime > 0) { - if(vipStartTime > startTime) { // 开始挂机之后买的月卡 - let isNotVipNum = Math.floor((vipStartTime - startTime) / HANG_UP_CONSTS.UNIT_TIME); // 不是vip的时间段数 - let isVipNum = multi - isNotVipNum; // 是vip的时间段数 - multi = cal.add(isNotVipNum, cal.mul(isVipNum, VIP.VIP_TOWER_HUNG_UP_RATIO)); - } else { - multi = cal.mul(multi, VIP.VIP_TOWER_HUNG_UP_RATIO); - } - } - - let needReceiveGoods: {gid: number, count: number}[] = [];// 由于小数,未能领取的奖励 - let timeReward: {id: number, count: number}[] = []; // 本次奖励 - for (let { id, count } of baseReward) { - let newCount = cal.mul(count, multi); - let oldGoods = notReceivedGoods.find(cur => cur.gid == id); - if (oldGoods) newCount = cal.add(newCount, oldGoods.count); - let roundCount = Math.floor(newCount); - if (newCount > roundCount) { - needReceiveGoods.push({ gid: id, count: cal.sub(newCount, roundCount) }); - } - if (roundCount > 0) { - timeReward.push({ id, count: roundCount }) - } - } - return { needReceiveGoods, timeReward } -} - -export async function getVipPvpChallengeMaxCnt(roleId: string, vipStartTime?: number) { - if(vipStartTime == undefined) { - let role = await RoleModel.findByRoleId(roleId, 'vipStartTime'); - vipStartTime = role.vipStartTime; - } - let count = PVP.PVP_CHALLENGE_COUNTS; - if(vipStartTime > 0) { - count += VIP.VIP_PVP_CHALLENGE_COUNTS_ADD; - } - return count; -} - -export function getVipDailyCnt(timesPerDay: number, role: RoleType) { - let vipStartTime = role.vipStartTime; - if(vipStartTime > 0) { - timesPerDay += VIP.VIP_DAILY_TIMERS_PER_DAY_ADD; - } - return timesPerDay -} - -export function getVipDungeonCnt(vipStartTime: number) { - let count = DUNGEON_CONST.DUNGEON_CONST_FREE; - if(vipStartTime > 0) { - count += VIP.VIP_DUNGEON_CONST_FREE_ADD; - } - return count -} - -export function getVipRegretCnt(vipStartTime: number) { - let count = VIP.VIP_REGRET_CNT_WITHOUT_VIP; - if(vipStartTime > 0) { - count = VIP.VIP_REGRET_CNT_WITH_VIP; - } - return count; -} - -export function vipCanSkipTower(recommendCeSum: number, heroesCeSum: number, vipStartTime: number) { - let ratio = vipStartTime > 0? VIP.VIP_TOWER_SKIP_CE_RATIO_WITH_VIP: VIP.VIP_TOWER_SKIP_CE_RATIO_WITHOUT_VIP; - return heroesCeSum > recommendCeSum * ratio; -} - -export function vipCanSkipExpedition(recommendCe: number, topLineupCe: number, vipStartTime: number) { - return vipStartTime > 0 && topLineupCe > recommendCe * VIP.EXPENDITION_SKIP_CE_RATIO_WITH_VIP; -} \ No newline at end of file +import { ACTIVITY_TYPE, HANG_UP_CONSTS, ITEM_CHANGE_REASON, MAIL_TYPE, REFRESH_TIME, STATUS } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityMonthlyTicketModel, ActivityMonthlyTicketModelType } from '@db/ActivityMonthlyTicket'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { MonthlyTicketData } from '@domain/activityField/monthlyTicketField'; +import { addReward, stringToRewardParam } from './giftPackageService'; +import moment = require('moment'); +import { ServerlistModel } from '@db/Serverlist'; +import { sendMailByContent } from './../mailService'; +import { RoleModel, RoleType } from '@db/Role'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { RewardInter } from '@pubUtils/interface'; +import { DUNGEON_CONST, PVP, VIP } from '@pubUtils/dicParam'; +import { cal, } from '@pubUtils/util'; +import { stringWithTypeToRewardInter } from '@pubUtils/roleUtil'; +import { pinus } from 'pinus'; +import { getGoldId } from '../role/rewardService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function monthlyTicketActivity(serverId: number, roleId: string, type: number) { + let activityArray = await getActivitiesByType(serverId, type); + activityArray = activityArray.sort((a, b) => { + return b.activityId - a.activityId + }); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityData.activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyTicketData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + + if ((playerData.price > 0 && playerData.isOpen) || playerData.price === 0) { + if (playerData.todayIndex - 1 > playerData.dayIndex) {//过期还没领取 + //下发邮件奖励 + for (let i = playerData.dayIndex + 1; i < playerData.todayIndex; i++) { + let goods = stringWithTypeToRewardInter(playerData.baseReward) + await sendMailByContent(MAIL_TYPE.MONTHLY_REWARD, roleId, { params: [], goods }); + } + await ActivityMonthlyTicketModel.setDayIndex(serverId, roleId, playerData.activityId, playerData.todayIndex - 1); + playerData.dayIndex = playerData.todayIndex - 1; + } + } + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMonthlyTicketData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyTicketData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家月卡当天的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerMonthlyTicketDayReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number,) { + let activityData: ActivityModelType = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyTicketData(activityData, createTime, serverTime); + + let playerRecord: ActivityMonthlyTicketModelType = await ActivityMonthlyTicketModel.findMonthlyTicket(serverId, roleId, activityId); + if (playerData.price > 0 && !playerRecord) {//没有购买过 + return null; + } + + playerData.setPlayerRecords(playerRecord); + if ((playerData.price > 0 && playerData.isOpen) || playerData.price == 0) { + if (playerData.todayIndex > playerData.dayIndex) {//今天还没领取 + await ActivityMonthlyTicketModel.setDayIndex(serverId, roleId, activityId, playerData.todayIndex); + let rewardParamArr: Array = stringToRewardParam(playerData.baseReward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.MONTHLY_TICKET_DAILY) + return result + } + } + return null +} + +/** + * 结算首次购买月卡的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeMonthlyTicketReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (activityData.type !== ACTIVITY_TYPE.MONTHLY_TICKET_1 && activityData.type !== ACTIVITY_TYPE.MONTHLY_TICKET_2) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + + if(!await checkMonthlyTicket(roleId, serverId, activityData)) return STATUS.ORDER_CANNOT_BUY; + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new MonthlyTicketData(activityData, createTime, serverTime); + + let endTime = playerData.isForever? moment(playerData.endTime).toDate(): moment(new Date()).startOf('d').add(playerData.days, 'day').add(REFRESH_TIME, 'h').toDate(); + console.log('endTime', playerData.isForever, moment(new Date()).startOf('d'), endTime, playerData.days) + + await ActivityMonthlyTicketModel.buyMonthlyTicket(serverId, roleId, activityId, activityData.type, endTime, playerData.isForever) + if(activityData.type == ACTIVITY_TYPE.MONTHLY_TICKET_2) { + let role = await RoleModel.buyForeverTicket(roleId); + if(sid) await pinus.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, vipStartTime: role.vipStartTime }]); + } + let firstReward = playerData.firstReward; + let rewardParamArr: Array = stringToRewardParam(firstReward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.MONTHLY_TICKET_FIRST) + return { + code: 0, + data: Object.assign(result, { item: { isOpen: true, todayIndex: 1 }, activityId: activityData.activityId }) + } +} + +// 是否可以购买月卡 +export async function checkMonthlyTicket(roleId: string, serverId: number, activityData: ActivityModelType) { + if(!activityData) return false; + + let result = await ActivityMonthlyTicketModel.checkHasBought(serverId, roleId, activityData.activityId, activityData.type); + return !result; +} + +// 军团捐献消耗 +export function getVipDonateConsume(originConsume: RewardInter, vipStartTime: number) { + if(vipStartTime > 0) { + if(originConsume.id == getGoldId()) { + return [{ id: originConsume.id, count: Math.floor(originConsume.count * VIP.VIP_GUILD_DONATE_COST_GOLD_RATIO) }]; + } else { + return [originConsume]; + } + } else { + return [originConsume]; + } +} + +export function getVipHungupReward(startTime: number, endTime: number, baseReward: RewardInter[], notReceivedGoods: {gid: number, count: number}[], vipStartTime: number) { + let multi = Math.floor((endTime - startTime) / HANG_UP_CONSTS.UNIT_TIME); + if(vipStartTime > 0) { + if(vipStartTime > startTime) { // 开始挂机之后买的月卡 + let isNotVipNum = Math.floor((vipStartTime - startTime) / HANG_UP_CONSTS.UNIT_TIME); // 不是vip的时间段数 + let isVipNum = multi - isNotVipNum; // 是vip的时间段数 + multi = cal.add(isNotVipNum, cal.mul(isVipNum, VIP.VIP_TOWER_HUNG_UP_RATIO)); + } else { + multi = cal.mul(multi, VIP.VIP_TOWER_HUNG_UP_RATIO); + } + } + + let needReceiveGoods: {gid: number, count: number}[] = [];// 由于小数,未能领取的奖励 + let timeReward: {id: number, count: number}[] = []; // 本次奖励 + for (let { id, count } of baseReward) { + let newCount = cal.mul(count, multi); + let oldGoods = notReceivedGoods.find(cur => cur.gid == id); + if (oldGoods) newCount = cal.add(newCount, oldGoods.count); + let roundCount = Math.floor(newCount); + if (newCount > roundCount) { + needReceiveGoods.push({ gid: id, count: cal.sub(newCount, roundCount) }); + } + if (roundCount > 0) { + timeReward.push({ id, count: roundCount }) + } + } + return { needReceiveGoods, timeReward } +} + +export async function getVipPvpChallengeMaxCnt(roleId: string, vipStartTime?: number) { + if(vipStartTime == undefined) { + let role = await RoleModel.findByRoleId(roleId, 'vipStartTime'); + vipStartTime = role.vipStartTime; + } + let count = PVP.PVP_CHALLENGE_COUNTS; + if(vipStartTime > 0) { + count += VIP.VIP_PVP_CHALLENGE_COUNTS_ADD; + } + return count; +} + +export function getVipDailyCnt(timesPerDay: number, role: RoleType) { + let vipStartTime = role.vipStartTime; + if(vipStartTime > 0) { + timesPerDay += VIP.VIP_DAILY_TIMERS_PER_DAY_ADD; + } + return timesPerDay +} + +export function getVipDungeonCnt(vipStartTime: number) { + let count = DUNGEON_CONST.DUNGEON_CONST_FREE; + if(vipStartTime > 0) { + count += VIP.VIP_DUNGEON_CONST_FREE_ADD; + } + return count +} + +export function getVipRegretCnt(vipStartTime: number) { + let count = VIP.VIP_REGRET_CNT_WITHOUT_VIP; + if(vipStartTime > 0) { + count = VIP.VIP_REGRET_CNT_WITH_VIP; + } + return count; +} + +export function vipCanSkipTower(recommendCeSum: number, heroesCeSum: number, vipStartTime: number) { + let ratio = vipStartTime > 0? VIP.VIP_TOWER_SKIP_CE_RATIO_WITH_VIP: VIP.VIP_TOWER_SKIP_CE_RATIO_WITHOUT_VIP; + return heroesCeSum > recommendCeSum * ratio; +} + +export function vipCanSkipExpedition(recommendCe: number, topLineupCe: number, vipStartTime: number) { + return vipStartTime > 0 && topLineupCe > recommendCe * VIP.EXPENDITION_SKIP_CE_RATIO_WITH_VIP; +} diff --git a/game-server/app/services/activity/newHeroGKService.ts b/game-server/app/services/activity/newHeroGKService.ts index e1c484919..1fc15b52b 100644 --- a/game-server/app/services/activity/newHeroGKService.ts +++ b/game-server/app/services/activity/newHeroGKService.ts @@ -1,85 +1,85 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityNewHeroGKModel, ActivityNewHeroGKModelType } from '../../db/ActivityNewHeroGK'; -import { NewHeroGKData } from '../../domain/activityField/newHeroGKField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function newHeroGKActivity(serverId: number, roleId: string) { - let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_GK); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityData.activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NewHeroGKData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerNewHeroGKData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NewHeroGKData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - - return playerData; -} - -/** - * 挑战每日关卡成功 - * - * @param {number} activityId 活动id - * @param {number} gk 关卡id - * - */ -// export async function challengeNewHeroGK(serverId: number, roleId: string, activityId: number, pageIndex: number, gk: number) { -// let isFirst = false; -// let activityData: ActivityModelType = await getActivityById(activityId); -// let playerRecords = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); -// let records = playerRecords && playerRecords.records ? playerRecords.records : []; - -// let createTime = await getRoleCreateTime(roleId); -// let serverTime = await getServerCreateTime(serverId); -// let playerData = new NewHeroGKData(activityData, createTime, serverTime); -// let item = playerData.findItemByGK(pageIndex, gk); -// if (item) { -// let index = item.index; -// let recordIndex = records.findIndex(obj => { return obj.pageIndex == pageIndex && obj.index == index }); -// if (recordIndex == -1) { -// isFirst = true; -// await ActivityNewHeroGKModel.addRecord(serverId, activityId, roleId, pageIndex, index); -// } -// } else { -// console.log('challengeNewHeroGK没有找到对应关卡活动数据', activityId, gk) -// } -// return isFirst; -// } - - - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityNewHeroGKModel, ActivityNewHeroGKModelType } from '@db/ActivityNewHeroGK'; +import { NewHeroGKData } from '@domain/activityField/newHeroGKField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function newHeroGKActivity(serverId: number, roleId: string) { + let activityDataArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.DAILY_GK); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityData.activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NewHeroGKData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerNewHeroGKData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NewHeroGKData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + + return playerData; +} + +/** + * 挑战每日关卡成功 + * + * @param {number} activityId 活动id + * @param {number} gk 关卡id + * + */ +// export async function challengeNewHeroGK(serverId: number, roleId: string, activityId: number, pageIndex: number, gk: number) { +// let isFirst = false; +// let activityData: ActivityModelType = await getActivityById(activityId); +// let playerRecords = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); +// let records = playerRecords && playerRecords.records ? playerRecords.records : []; + +// let createTime = await getRoleCreateTime(roleId); +// let serverTime = await getServerCreateTime(serverId); +// let playerData = new NewHeroGKData(activityData, createTime, serverTime); +// let item = playerData.findItemByGK(pageIndex, gk); +// if (item) { +// let index = item.index; +// let recordIndex = records.findIndex(obj => { return obj.pageIndex == pageIndex && obj.index == index }); +// if (recordIndex == -1) { +// isFirst = true; +// await ActivityNewHeroGKModel.addRecord(serverId, activityId, roleId, pageIndex, index); +// } +// } else { +// console.log('challengeNewHeroGK没有找到对应关卡活动数据', activityId, gk) +// } +// return isFirst; +// } + + + + diff --git a/game-server/app/services/activity/newHeroService.ts b/game-server/app/services/activity/newHeroService.ts index 290eb0ca0..937623879 100644 --- a/game-server/app/services/activity/newHeroService.ts +++ b/game-server/app/services/activity/newHeroService.ts @@ -1,120 +1,120 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityNewHeroGiftModel, ActivityNewHeroGiftModelType } from '../../db/ActivityNewHeroGift'; -import { ActivityNewHeroGKModel, ActivityNewHeroGKModelType } from '../../db/ActivityNewHeroGK'; -import { UserGachaModel, UserGachaType } from '../../db/UserGacha'; -import { NewHeroGachaData } from '../../domain/activityField/newHeroGachaField'; -import { NewHeroGiftData } from '../../domain/activityField/newHeroGiftField'; -import { NewHeroGKData } from '../../domain/activityField/newHeroGKField'; -import { gameData } from '../../pubUtils/data'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById, pushActivityInter } from './activityService'; -import { refreshGacha } from './gachaService'; - - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPlayerNewHeroGachaData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NewHeroGachaData(activityData, createTime, serverTime); - let userGacha: UserGachaType = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); - let dicGacha = gameData.gacha.get(playerData.gachaId); - userGacha = await refreshGacha(dicGacha, userGacha); - if(!userGacha.pickHero) { - userGacha = await UserGachaModel.updateInfo(roleId, playerData.gachaId, activityId, { pickHero: playerData.getDefaultHero() }) - } - playerData.setPlayerRecords(userGacha, dicGacha); - - return playerData; -} - - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPlayerNewHeroGKData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NewHeroGKData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - - return playerData; -} - -/** - * 挑战每日关卡成功 - * - * @param {number} activityId 活动id - * @param {number} warId 关卡id - * - */ -export async function challengeNewHeroGK(serverId: number, roleId: string, activityId: number, warId: number) { - let data = await ActivityNewHeroGKModel.addRecord(serverId, activityId, roleId, warId); - let isFirst = data.records.filter(cur => cur.warId == warId).length <= 1; - return isFirst; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPlayerNewHeroGiftsData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NewHeroGiftData(activityData, createTime, serverTime); - let playerRecord: ActivityNewHeroGiftModelType = await ActivityNewHeroGiftModel.findData(serverId, activityId, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 任务活动完成后会获得点数 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function newHeroGiftPoint(serverId: number, roleId: string, addPoint: number) { - try { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.NEW_HERO_GIFTS); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let playerData = new NewHeroGiftData(activityData, createTime, serverTime); - if(playerData.canRecordTaskPoint()) { - let result = await ActivityNewHeroGiftModel.addPoint(serverId, activityData.activityId, roleId, addPoint); - if(result) pushResult.push({ activityId: activityData.activityId, activityType: activityData.type, param: { totalPoint: result.totalPoint } }); - } - } - - return pushResult - } catch(e) { - console.error(e); - return [] - } -} +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityNewHeroGiftModel, ActivityNewHeroGiftModelType } from '@db/ActivityNewHeroGift'; +import { ActivityNewHeroGKModel, ActivityNewHeroGKModelType } from '@db/ActivityNewHeroGK'; +import { UserGachaModel, UserGachaType } from '@db/UserGacha'; +import { NewHeroGachaData } from '@domain/activityField/newHeroGachaField'; +import { NewHeroGiftData } from '@domain/activityField/newHeroGiftField'; +import { NewHeroGKData } from '@domain/activityField/newHeroGKField'; +import { gameData } from '@pubUtils/data'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById, pushActivityInter } from './activityService'; +import { refreshGacha } from './gachaService'; + + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPlayerNewHeroGachaData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NewHeroGachaData(activityData, createTime, serverTime); + let userGacha: UserGachaType = await UserGachaModel.findByRole(roleId, playerData.gachaId, activityId); + let dicGacha = gameData.gacha.get(playerData.gachaId); + userGacha = await refreshGacha(dicGacha, userGacha); + if(!userGacha.pickHero) { + userGacha = await UserGachaModel.updateInfo(roleId, playerData.gachaId, activityId, { pickHero: playerData.getDefaultHero() }) + } + playerData.setPlayerRecords(userGacha, dicGacha); + + return playerData; +} + + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPlayerNewHeroGKData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord: ActivityNewHeroGKModelType = await ActivityNewHeroGKModel.findData(serverId, activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NewHeroGKData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + + return playerData; +} + +/** + * 挑战每日关卡成功 + * + * @param {number} activityId 活动id + * @param {number} warId 关卡id + * + */ +export async function challengeNewHeroGK(serverId: number, roleId: string, activityId: number, warId: number) { + let data = await ActivityNewHeroGKModel.addRecord(serverId, activityId, roleId, warId); + let isFirst = data.records.filter(cur => cur.warId == warId).length <= 1; + return isFirst; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPlayerNewHeroGiftsData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NewHeroGiftData(activityData, createTime, serverTime); + let playerRecord: ActivityNewHeroGiftModelType = await ActivityNewHeroGiftModel.findData(serverId, activityId, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 任务活动完成后会获得点数 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function newHeroGiftPoint(serverId: number, roleId: string, addPoint: number) { + try { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.NEW_HERO_GIFTS); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let playerData = new NewHeroGiftData(activityData, createTime, serverTime); + if(playerData.canRecordTaskPoint()) { + let result = await ActivityNewHeroGiftModel.addPoint(serverId, activityData.activityId, roleId, addPoint); + if(result) pushResult.push({ activityId: activityData.activityId, activityType: activityData.type, param: { totalPoint: result.totalPoint } }); + } + } + + return pushResult + } catch(e) { + console.error(e); + return [] + } +} diff --git a/game-server/app/services/activity/novemberServices.ts b/game-server/app/services/activity/novemberServices.ts index 31ac3b0c8..0bdd638aa 100644 --- a/game-server/app/services/activity/novemberServices.ts +++ b/game-server/app/services/activity/novemberServices.ts @@ -1,23 +1,23 @@ -import { ActivityNovemberRecModel } from "../../db/ActivityNovemberRec"; -import { NovemberData } from "../../domain/activityField/novemberField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -export async function getPlayerNovemberData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new NovemberData(activityData, createTime, serverTime); - let playerRecord = await ActivityNovemberRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -export async function getPlayerNovemberDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerNovemberData(activityId, serverId, roleId); - if (playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityNovemberRecModel } from "@db/ActivityNovemberRec"; +import { NovemberData } from "@domain/activityField/novemberField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +export async function getPlayerNovemberData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new NovemberData(activityData, createTime, serverTime); + let playerRecord = await ActivityNovemberRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +export async function getPlayerNovemberDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerNovemberData(activityId, serverId, roleId); + if (playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/popNoticeService.ts b/game-server/app/services/activity/popNoticeService.ts index f0303566c..d9b2c3b1b 100644 --- a/game-server/app/services/activity/popNoticeService.ts +++ b/game-server/app/services/activity/popNoticeService.ts @@ -1,36 +1,36 @@ -import { ActivityData } from "../../domain/activityField/activityField"; -import { PopNoticeData } from "../../domain/activityField/popNotice"; -import { ShopData } from "../../domain/roleField/shop"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getPopNoticeData(serverId: number, activityId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - - let playerData = new PopNoticeData(activityData, createTime, serverTime); - if(playerData.needActivityTime()) { - let { activityId } = playerData.param; - let curActivity = await getActivityById(activityId); - let data = new ActivityData(curActivity, createTime, serverTime); - playerData.setActivityTime(Math.floor(data.beginTime/1000), Math.floor(data.nextRefreshTime/1000)); - } - if(playerData.needShopTime()) { - let { activityId, shopItemId } = playerData.param; - let curActivity = await getActivityById(activityId); - let data = new ShopData(curActivity, createTime, serverTime); - let item = data.findByItemId(shopItemId); - if(item) playerData.setActivityTime(item.beginTime, item.endTime) - } - delete playerData.param; - return playerData; -} \ No newline at end of file +import { ActivityData } from "@domain/activityField/activityField"; +import { PopNoticeData } from "@domain/activityField/popNotice"; +import { ShopData } from "@domain/roleField/shop"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getPopNoticeData(serverId: number, activityId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + + let playerData = new PopNoticeData(activityData, createTime, serverTime); + if(playerData.needActivityTime()) { + let { activityId } = playerData.param; + let curActivity = await getActivityById(activityId); + let data = new ActivityData(curActivity, createTime, serverTime); + playerData.setActivityTime(Math.floor(data.beginTime/1000), Math.floor(data.nextRefreshTime/1000)); + } + if(playerData.needShopTime()) { + let { activityId, shopItemId } = playerData.param; + let curActivity = await getActivityById(activityId); + let data = new ShopData(curActivity, createTime, serverTime); + let item = data.findByItemId(shopItemId); + if(item) playerData.setActivityTime(item.beginTime, item.endTime) + } + delete playerData.param; + return playerData; +} diff --git a/game-server/app/services/activity/popUpShopService.ts b/game-server/app/services/activity/popUpShopService.ts index 68e1e1acc..7a931e035 100644 --- a/game-server/app/services/activity/popUpShopService.ts +++ b/game-server/app/services/activity/popUpShopService.ts @@ -1,203 +1,203 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, PUSH_BATCH, PUSH_INTERVAL, STATUS } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { PopShopItem, PopUpConditionParamInter, PopUpShopData, PopUpShopPackage, PopUpShopItemShow, } from '../../domain/activityField/popUpShopField'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { addReward, stringToRewardParam } from './giftPackageService'; -import { ActivityPopUpShopModel, ActivityPopUpShopModelType, PopUpShopItem } from '../../db/ActivityPopUpShop'; -import { ServerlistModel } from '../../db/Serverlist'; -import moment = require('moment'); -import { getActivitiesByType, getActivityById, pushActivities, pushActivityInter, pushSingleActivity } from './activityService'; -import { RoleModel, RoleType } from '../../db/Role'; -import { HeroType } from '../../db/Hero'; -import { pinus } from 'pinus'; -import { getRandEelm, getRandSingleEelm } from '../../pubUtils/util'; -import { getAllOnlineRoles } from '../redisService'; -import { GachaResultIndb } from '../../domain/activityField/gachaField'; -import { gameData } from '../../pubUtils/data'; -import { ActivityPopUpShopRecModel } from '../../db/ActivityPopUpShopRec'; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPopUpShopData(activityId: number, serverId: number, roleId: string, role?: RoleType) { - if(!role) role = await RoleModel.findByRoleId(roleId, 'roleId totalPay lv'); - - let activityData = await getActivityById(activityId); - let playerRecords = await ActivityPopUpShopModel.findAllEffectData(serverId, activityId, roleId); - let latestRecords = await ActivityPopUpShopModel.findAllLastData(serverId, activityId, roleId); - - let playerData = new PopUpShopData(activityData); - playerData.setPlayerRecords(playerRecords, latestRecords, role.totalPay, role.lv); - - return playerData; -} - -export async function getPopUpShopDataShow(activityId: number, serverId: number, roleId: string, role?: RoleType) { - let playerData = await getPopUpShopData(activityId, serverId, roleId, role); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -export async function checkPopUpConditionInCreateHero(serverId: number, roleId: string, result: GachaResultIndb[]) { - let conditions = result.map(gachaResult => { - let dicHero = gameData.hero.get(gachaResult?.hid); - return { conditionType: POP_UP_SHOP_CONDITION_TYPE.GET_HERO_BY_QUALITY, param: { quality: dicHero?.quality } }; - }); - return await checkPopUpConditions(serverId, roleId, conditions); -} - -export async function checkPopUpCondition(serverId: number, roleId: string, conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter, sid?: string) { - return await checkPopUpConditions(serverId, roleId, [{ conditionType, param }], sid); -} - -export async function checkPopUpConditionInEntry(serverId: number, roleId: string, sid: string) { - let guilds = pinus.app.getServersByType('guild'); - let guild = getRandSingleEelm(guilds); - let isAuctionPopUpShow = await pinus.app.rpc.guild.guildActivityRemote.getAuctionPopUpShow.toServer(guild.id); - if(isAuctionPopUpShow) { - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid); - } -} - -export async function checkPopUpConditionWhenGuildActivityEnd() { - let allOnlineUsers = await getAllOnlineRoles(); - let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批 - - let i = -1; - let interval = setInterval(async () => { - if (++i < n) { - // console.log('****', i) - let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); - // console.log('****', users) - for(let { serverId, roleId, sid } of users) { - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid); - } - } else { - clearInterval(interval); - } - }, PUSH_INTERVAL); -} - -// 弹出礼包任务 -export async function checkPopUpConditions(serverId: number, roleId: string, conditions: { conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter }[], sid?: string) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.POP_UP_SHOP); - let pushData: pushActivityInter[] = []; - for(let { activityId, type: activityType } of activities) { - - let playerData = await getPopUpShopData(activityId, serverId, roleId); - let pushItems: PopUpShopItemShow[] = []; - for(let { conditionType, param } of conditions) { - for(let pkg of playerData.packages) { - // console.log('##### 3', pkg.id, pkg.checkPackageCanPush(conditionType)) - if( !pkg.checkPackageCanPush(conditionType)) { // 筛选推送 - continue; - } - let effectTimes = await pkg.getEffectTime(); - if(conditionType == POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR) { - let result = await ActivityPopUpShopRecModel.addRecord(serverId, activityId, roleId, pkg.id, effectTimes.effectBeginTime, effectTimes.effectEndTime, conditionType, param.equipStar); - param.equipStarSum = result.num; - } - - let items = pkg.getItemsByCondition(param); - if(items.length > 0) { - - let map = new Map(); - for(let item of items) { - if(!map.has(item.param)) { - map.set(item.param, []); - } - map.get(item.param).push(item); - } - for(let [_, items] of map) { - let popUpShopRec = await ActivityPopUpShopModel.createRecord({ - serverId, activityId, roleId, id: pkg.id, - ...effectTimes, - items: items.map(item => new PopUpShopItem(item)) - }); - let result = pkg.pushPackage(popUpShopRec); - pushItems.push(...result); - } - } - } - } - // console.log('##### 5', pushItems.length) - if(pushItems.length > 0) { - pushData.push({ activityId, activityType, param: { popUpShopItems: pushItems } }); - } - } - // console.log('##### 6', pushData.length) - return await pushActivities(pushData, roleId, sid); - -} - - -/** - * 结算购买礼包的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makePopUpShopReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string, paramStr: string, roleInfo: RoleType) { - if (!paramStr) { - return STATUS.ORDER_PARAM_ERROR; - } - let paramObj = JSON.parse(paramStr); - let code = paramObj.code; - - let playerData = await getPopUpShopData(activityId, serverId, roleId, roleInfo); - if (!playerData) { - return STATUS.ACTIVITY_MISSING; - } - if (playerData.type !== ACTIVITY_TYPE.POP_UP_SHOP) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - - let playerRecord: ActivityPopUpShopModelType = await ActivityPopUpShopModel.addRecord(serverId, activityId, roleId, code, productID); - if (!playerRecord) { - return STATUS.APPLY_ORDER_ERROR; - } - let item = playerData.updateRecord(playerRecord, productID); - if(!item) return STATUS.NO_PRODUCT_ID - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT) - - return { - code: 0, - data: Object.assign(result, { item: item, activityId }) - } -} - -export async function checkPopUpShopCanBuy(roleId: string, serverId: number, activityId: number, productID: string, paramStr: string) { - if (!paramStr) { - return false; - } - let paramObj = JSON.parse(paramStr); - let code = paramObj.code; - - let playerData = await getPopUpShopData(activityId, serverId, roleId); - if (!playerData) { - return false; - } - - let playerRecord: ActivityPopUpShopModelType = await ActivityPopUpShopModel.findByCode(serverId, activityId, roleId, code); - if (!playerRecord) { - return false; - } - - let item = playerData.checkItem(playerRecord, productID); - if(!item) return false; - - return true -} \ No newline at end of file +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, PUSH_BATCH, PUSH_INTERVAL, STATUS } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { PopShopItem, PopUpConditionParamInter, PopUpShopData, PopUpShopPackage, PopUpShopItemShow, } from '@domain/activityField/popUpShopField'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { addReward, stringToRewardParam } from './giftPackageService'; +import { ActivityPopUpShopModel, ActivityPopUpShopModelType, PopUpShopItem } from '@db/ActivityPopUpShop'; +import { ServerlistModel } from '@db/Serverlist'; +import moment = require('moment'); +import { getActivitiesByType, getActivityById, pushActivities, pushActivityInter, pushSingleActivity } from './activityService'; +import { RoleModel, RoleType } from '@db/Role'; +import { HeroType } from '@db/Hero'; +import { pinus } from 'pinus'; +import { getRandEelm, getRandSingleEelm } from '@pubUtils/util'; +import { getAllOnlineRoles } from '../redisService'; +import { GachaResultIndb } from '@domain/activityField/gachaField'; +import { gameData } from '@pubUtils/data'; +import { ActivityPopUpShopRecModel } from '@db/ActivityPopUpShopRec'; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPopUpShopData(activityId: number, serverId: number, roleId: string, role?: RoleType) { + if(!role) role = await RoleModel.findByRoleId(roleId, 'roleId totalPay lv'); + + let activityData = await getActivityById(activityId); + let playerRecords = await ActivityPopUpShopModel.findAllEffectData(serverId, activityId, roleId); + let latestRecords = await ActivityPopUpShopModel.findAllLastData(serverId, activityId, roleId); + + let playerData = new PopUpShopData(activityData); + playerData.setPlayerRecords(playerRecords, latestRecords, role.totalPay, role.lv); + + return playerData; +} + +export async function getPopUpShopDataShow(activityId: number, serverId: number, roleId: string, role?: RoleType) { + let playerData = await getPopUpShopData(activityId, serverId, roleId, role); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +export async function checkPopUpConditionInCreateHero(serverId: number, roleId: string, result: GachaResultIndb[]) { + let conditions = result.map(gachaResult => { + let dicHero = gameData.hero.get(gachaResult?.hid); + return { conditionType: POP_UP_SHOP_CONDITION_TYPE.GET_HERO_BY_QUALITY, param: { quality: dicHero?.quality } }; + }); + return await checkPopUpConditions(serverId, roleId, conditions); +} + +export async function checkPopUpCondition(serverId: number, roleId: string, conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter, sid?: string) { + return await checkPopUpConditions(serverId, roleId, [{ conditionType, param }], sid); +} + +export async function checkPopUpConditionInEntry(serverId: number, roleId: string, sid: string) { + let guilds = pinus.app.getServersByType('guild'); + let guild = getRandSingleEelm(guilds); + let isAuctionPopUpShow = await pinus.app.rpc.guild.guildActivityRemote.getAuctionPopUpShow.toServer(guild.id); + if(isAuctionPopUpShow) { + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid); + } +} + +export async function checkPopUpConditionWhenGuildActivityEnd() { + let allOnlineUsers = await getAllOnlineRoles(); + let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批 + + let i = -1; + let interval = setInterval(async () => { + if (++i < n) { + // console.log('****', i) + let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); + // console.log('****', users) + for(let { serverId, roleId, sid } of users) { + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.AUCTION, {}, sid); + } + } else { + clearInterval(interval); + } + }, PUSH_INTERVAL); +} + +// 弹出礼包任务 +export async function checkPopUpConditions(serverId: number, roleId: string, conditions: { conditionType: POP_UP_SHOP_CONDITION_TYPE, param: PopUpConditionParamInter }[], sid?: string) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.POP_UP_SHOP); + let pushData: pushActivityInter[] = []; + for(let { activityId, type: activityType } of activities) { + + let playerData = await getPopUpShopData(activityId, serverId, roleId); + let pushItems: PopUpShopItemShow[] = []; + for(let { conditionType, param } of conditions) { + for(let pkg of playerData.packages) { + // console.log('##### 3', pkg.id, pkg.checkPackageCanPush(conditionType)) + if( !pkg.checkPackageCanPush(conditionType)) { // 筛选推送 + continue; + } + let effectTimes = await pkg.getEffectTime(); + if(conditionType == POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR) { + let result = await ActivityPopUpShopRecModel.addRecord(serverId, activityId, roleId, pkg.id, effectTimes.effectBeginTime, effectTimes.effectEndTime, conditionType, param.equipStar); + param.equipStarSum = result.num; + } + + let items = pkg.getItemsByCondition(param); + if(items.length > 0) { + + let map = new Map(); + for(let item of items) { + if(!map.has(item.param)) { + map.set(item.param, []); + } + map.get(item.param).push(item); + } + for(let [_, items] of map) { + let popUpShopRec = await ActivityPopUpShopModel.createRecord({ + serverId, activityId, roleId, id: pkg.id, + ...effectTimes, + items: items.map(item => new PopUpShopItem(item)) + }); + let result = pkg.pushPackage(popUpShopRec); + pushItems.push(...result); + } + } + } + } + // console.log('##### 5', pushItems.length) + if(pushItems.length > 0) { + pushData.push({ activityId, activityType, param: { popUpShopItems: pushItems } }); + } + } + // console.log('##### 6', pushData.length) + return await pushActivities(pushData, roleId, sid); + +} + + +/** + * 结算购买礼包的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makePopUpShopReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string, paramStr: string, roleInfo: RoleType) { + if (!paramStr) { + return STATUS.ORDER_PARAM_ERROR; + } + let paramObj = JSON.parse(paramStr); + let code = paramObj.code; + + let playerData = await getPopUpShopData(activityId, serverId, roleId, roleInfo); + if (!playerData) { + return STATUS.ACTIVITY_MISSING; + } + if (playerData.type !== ACTIVITY_TYPE.POP_UP_SHOP) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + + let playerRecord: ActivityPopUpShopModelType = await ActivityPopUpShopModel.addRecord(serverId, activityId, roleId, code, productID); + if (!playerRecord) { + return STATUS.APPLY_ORDER_ERROR; + } + let item = playerData.updateRecord(playerRecord, productID); + if(!item) return STATUS.NO_PRODUCT_ID + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.POP_UP_BUY_GIFT) + + return { + code: 0, + data: Object.assign(result, { item: item, activityId }) + } +} + +export async function checkPopUpShopCanBuy(roleId: string, serverId: number, activityId: number, productID: string, paramStr: string) { + if (!paramStr) { + return false; + } + let paramObj = JSON.parse(paramStr); + let code = paramObj.code; + + let playerData = await getPopUpShopData(activityId, serverId, roleId); + if (!playerData) { + return false; + } + + let playerRecord: ActivityPopUpShopModelType = await ActivityPopUpShopModel.findByCode(serverId, activityId, roleId, code); + if (!playerRecord) { + return false; + } + + let item = playerData.checkItem(playerRecord, productID); + if(!item) return false; + + return true +} diff --git a/game-server/app/services/activity/qixiService.ts b/game-server/app/services/activity/qixiService.ts index 5519235a3..d41757cb0 100644 --- a/game-server/app/services/activity/qixiService.ts +++ b/game-server/app/services/activity/qixiService.ts @@ -1,38 +1,38 @@ -import { ActivityQixiRecModel } from "../../db/ActivityQixiRec"; -import { QixiData } from "../../domain/activityField/qixiField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerQixiData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new QixiData(activityData, createTime, serverTime); - let playerRecord = await ActivityQixiRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerQixiDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerQixiData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { ActivityQixiRecModel } from "@db/ActivityQixiRec"; +import { QixiData } from "@domain/activityField/qixiField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerQixiData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new QixiData(activityData, createTime, serverTime); + let playerRecord = await ActivityQixiRecModel.findData(serverId, activityId, playerData.roundIndex, roleId); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerQixiDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerQixiData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/rebateService.ts b/game-server/app/services/activity/rebateService.ts index 05b78c456..1eb88f297 100644 --- a/game-server/app/services/activity/rebateService.ts +++ b/game-server/app/services/activity/rebateService.ts @@ -1,42 +1,42 @@ -import { HistoryOrderModel } from "../../db/HistoryOrder"; -import { UserModel } from "../../db/User"; -import { RebateData } from "../../domain/activityField/rebateField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRebateData(activityId: number, serverId: number, roleId: string, uid: number) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RebateData(activityData, createTime, serverTime); - let user = await UserModel.findUserByUid(uid); - if(user.channelId) { - let playerRecords = await HistoryOrderModel.findByChannelId(user.channelId); - playerData.setPlayerRecords(playerRecords, user); - } - return playerData; -} - -/** - * 玩家活动数据显示 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRebateDataShow(activityId: number, serverId: number, roleId: string, uid: number) { - let playerData = await getPlayerRebateData(activityId, serverId, roleId, uid); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { HistoryOrderModel } from "@db/HistoryOrder"; +import { UserModel } from "@db/User"; +import { RebateData } from "@domain/activityField/rebateField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRebateData(activityId: number, serverId: number, roleId: string, uid: number) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RebateData(activityData, createTime, serverTime); + let user = await UserModel.findUserByUid(uid); + if(user.channelId) { + let playerRecords = await HistoryOrderModel.findByChannelId(user.channelId); + playerData.setPlayerRecords(playerRecords, user); + } + return playerData; +} + +/** + * 玩家活动数据显示 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRebateDataShow(activityId: number, serverId: number, roleId: string, uid: number) { + let playerData = await getPlayerRebateData(activityId, serverId, roleId, uid); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/rechargeMoneyService.ts b/game-server/app/services/activity/rechargeMoneyService.ts index 05c2cf8e4..6ed4ea24e 100644 --- a/game-server/app/services/activity/rechargeMoneyService.ts +++ b/game-server/app/services/activity/rechargeMoneyService.ts @@ -1,63 +1,63 @@ -import { ActivityRechargeMoneyModel, ActivityRechargeMoneyModelType } from '../../db/ActivityRechargeMoney'; -import { RechargeMoneyData } from '../../domain/activityField/rechargeMoneyField'; -import { getActivitiesByType, getActivityById, pushActivities, pushActivityInter } from './activityService'; -import { ACTIVITY_TYPE } from '../../consts'; -import { getRoleCreateTime, getRoleOnlineInfo, getServerCreateTime } from '../redisService'; -import { getZeroPointD, getZeroPointOfTime } from '../../pubUtils/timeUtil'; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRechargeMoneyData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RechargeMoneyData(activityData, createTime, serverTime); - let beginTime = new Date(getZeroPointOfTime(playerData.beginTime)); - let endTime = new Date(getZeroPointD().getTime() + 24 * 60 * 60 * 1000); - let playerRecord: ActivityRechargeMoneyModelType[] = await ActivityRechargeMoneyModel.findDataByTime(serverId, roleId, beginTime, endTime); - - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -export async function getPlayerRechargeMoneyDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -/** - * 统计充值金额 - * - * @param {number} serverId 区Id - * @param {string} roleId 角色Id - * @param {string} RMB 金额 - * - */ -export async function addRechargeMoney(roleId: string, serverId: number, RMB: number) { - let beginTime = getZeroPointD(); - let endTime = new Date(getZeroPointD().getTime() + 24 * 60 * 60 * 1000); - let result = await ActivityRechargeMoneyModel.addRMB(serverId, roleId, RMB, beginTime, endTime); - if(result.RMB == RMB) { // 获得木签的时候推送给在线玩家 - let onlineUser = await getRoleOnlineInfo(roleId); - if(!!onlineUser.sid) { - let result: pushActivityInter[] = []; - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.RECHARGE_MONEY); - for(let { activityId, type: activityType } of activities) { - let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); - result.push({ activityId, activityType, param: { ticketCnt: playerData.ticketCnt } }); - } - - await pushActivities(result, roleId, onlineUser.sid); - } - } -} - +import { ActivityRechargeMoneyModel, ActivityRechargeMoneyModelType } from '@db/ActivityRechargeMoney'; +import { RechargeMoneyData } from '@domain/activityField/rechargeMoneyField'; +import { getActivitiesByType, getActivityById, pushActivities, pushActivityInter } from './activityService'; +import { ACTIVITY_TYPE } from '@consts'; +import { getRoleCreateTime, getRoleOnlineInfo, getServerCreateTime } from '../redisService'; +import { getZeroPointD, getZeroPointOfTime } from '@pubUtils/timeUtil'; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRechargeMoneyData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RechargeMoneyData(activityData, createTime, serverTime); + let beginTime = new Date(getZeroPointOfTime(playerData.beginTime)); + let endTime = new Date(getZeroPointD().getTime() + 24 * 60 * 60 * 1000); + let playerRecord: ActivityRechargeMoneyModelType[] = await ActivityRechargeMoneyModel.findDataByTime(serverId, roleId, beginTime, endTime); + + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +export async function getPlayerRechargeMoneyDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +/** + * 统计充值金额 + * + * @param {number} serverId 区Id + * @param {string} roleId 角色Id + * @param {string} RMB 金额 + * + */ +export async function addRechargeMoney(roleId: string, serverId: number, RMB: number) { + let beginTime = getZeroPointD(); + let endTime = new Date(getZeroPointD().getTime() + 24 * 60 * 60 * 1000); + let result = await ActivityRechargeMoneyModel.addRMB(serverId, roleId, RMB, beginTime, endTime); + if(result.RMB == RMB) { // 获得木签的时候推送给在线玩家 + let onlineUser = await getRoleOnlineInfo(roleId); + if(!!onlineUser.sid) { + let result: pushActivityInter[] = []; + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.RECHARGE_MONEY); + for(let { activityId, type: activityType } of activities) { + let playerData = await getPlayerRechargeMoneyData(activityId, serverId, roleId); + result.push({ activityId, activityType, param: { ticketCnt: playerData.ticketCnt } }); + } + + await pushActivities(result, roleId, onlineUser.sid); + } + } +} + diff --git a/game-server/app/services/activity/refreshShopService.ts b/game-server/app/services/activity/refreshShopService.ts index 0af92baa0..e3bf5744c 100644 --- a/game-server/app/services/activity/refreshShopService.ts +++ b/game-server/app/services/activity/refreshShopService.ts @@ -1,174 +1,174 @@ -import moment = require('moment'); -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityRefreshShopModel, ActivityRefreshShopModelType } from '../../db/ActivityRefreshShop'; -import { RoleModel } from '../../db/Role'; -import { ServerlistModel } from '../../db/Serverlist'; -import { RefreshShopData } from '../../domain/activityField/refreshShopField'; -import { deltaDays } from '../../pubUtils/util'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { addReward, stringToRewardParam } from './giftPackageService'; - -/** - * - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function getRefreshShopActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.REFRESH_SHOP); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); - if (!playerRecord) {//生成商店可购买商品的数据 - let { lv } = await RoleModel.findByRoleId(roleId); - let randomGoods = playerData.randomGoodsItems(lv); - playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); - } - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家商店数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRefreshShopData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let role = await RoleModel.findByRoleId(roleId, 'lv createTime'); - let createTime = await getRoleCreateTime(roleId, role); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshShopData(activityData, createTime, serverTime); - - let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityId, roleId, playerData.roundIndex); - if (!playerRecord) {//生成商店可购买商品的数据 - let randomGoods = playerData.randomGoodsItems(role.lv); - playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); - } - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家商店数据(指定回合数,大富翁商店每回合刷新) - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRefreshShopDataByRoundIndex(activityId: number, serverId: number, roleId: string, roundIndex: number) { - let activityData: ActivityModelType = await getActivityById(activityId); - let role = await RoleModel.findByRoleId(roleId, 'lv createTime'); - let createTime = await getRoleCreateTime(roleId, role); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshShopData(activityData, createTime, serverTime); - playerData.roundIndex = roundIndex; - let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityId, roleId, playerData.roundIndex); - if (!playerRecord) {//生成商店可购买商品的数据 - let randomGoods = playerData.randomGoodsItems(role.lv); - playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); - } - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动第几天 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function newPlayerActivityDays(roleId: string) { - let { createTime } = await RoleModel.findByRoleId(roleId); - let createDate = moment(createTime * 1000).toDate(); - let todayIndex = deltaDays(createDate, new Date, true) + 1; - return todayIndex; -} - - - - -/** - * 结算购买的奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * @param {number} roundIndex 大富翁重置回合数 - * - */ -export async function makeRefreshShopReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string, roundIndex: number) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.REFRESH_SHOP) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshShopData(activityData, createTime, serverTime); - if (roundIndex) { - playerData.roundIndex = roundIndex; - } - - let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecord); - - let item = playerData.findItemByProductID(productID); - if (!item) { - return STATUS.ACTIVITY_NO_PRODUCT; - } - if (item.countMax > 0 && item.buyCount >= item.countMax) { - return STATUS.ACTIVITY_MAX_COUNT; - } - - let rewardArray = stringToRewardParam(item.reward) - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); - - await ActivityRefreshShopModel.addRecord(activityId, roleId, playerData.roundIndex, item.pageIndex, item.id, 1); - - item.buyCount += 1; - return { - code: 0, - data: Object.assign(result, { item: item, activityId: activityId }) - } -} - -export async function checkRefreshShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, roundIndex: number) { - if (!activityData) return false; - if (activityData.type !== ACTIVITY_TYPE.REFRESH_SHOP) return false; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshShopData(activityData, createTime, serverTime); - - if(!roundIndex) { - roundIndex = playerData.roundIndex; - } - let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, roundIndex); - playerData.setPlayerRecords(playerRecord); - - let item = playerData.findItemByProductID(productID); - if (!item) return false; - if (item.countMax > 0 && item.buyCount >= item.countMax) return false; - return true; -} \ No newline at end of file +import moment = require('moment'); +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityRefreshShopModel, ActivityRefreshShopModelType } from '@db/ActivityRefreshShop'; +import { RoleModel } from '@db/Role'; +import { ServerlistModel } from '@db/Serverlist'; +import { RefreshShopData } from '@domain/activityField/refreshShopField'; +import { deltaDays } from '@pubUtils/util'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { addReward, stringToRewardParam } from './giftPackageService'; + +/** + * + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function getRefreshShopActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.REFRESH_SHOP); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); + if (!playerRecord) {//生成商店可购买商品的数据 + let { lv } = await RoleModel.findByRoleId(roleId); + let randomGoods = playerData.randomGoodsItems(lv); + playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); + } + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家商店数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRefreshShopData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let role = await RoleModel.findByRoleId(roleId, 'lv createTime'); + let createTime = await getRoleCreateTime(roleId, role); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshShopData(activityData, createTime, serverTime); + + let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityId, roleId, playerData.roundIndex); + if (!playerRecord) {//生成商店可购买商品的数据 + let randomGoods = playerData.randomGoodsItems(role.lv); + playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); + } + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家商店数据(指定回合数,大富翁商店每回合刷新) + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRefreshShopDataByRoundIndex(activityId: number, serverId: number, roleId: string, roundIndex: number) { + let activityData: ActivityModelType = await getActivityById(activityId); + let role = await RoleModel.findByRoleId(roleId, 'lv createTime'); + let createTime = await getRoleCreateTime(roleId, role); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshShopData(activityData, createTime, serverTime); + playerData.roundIndex = roundIndex; + let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityId, roleId, playerData.roundIndex); + if (!playerRecord) {//生成商店可购买商品的数据 + let randomGoods = playerData.randomGoodsItems(role.lv); + playerRecord = await ActivityRefreshShopModel.createShop(activityData.activityId, roleId, playerData.roundIndex, randomGoods); + } + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动第几天 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function newPlayerActivityDays(roleId: string) { + let { createTime } = await RoleModel.findByRoleId(roleId); + let createDate = moment(createTime * 1000).toDate(); + let todayIndex = deltaDays(createDate, new Date, true) + 1; + return todayIndex; +} + + + + +/** + * 结算购买的奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * @param {number} roundIndex 大富翁重置回合数 + * + */ +export async function makeRefreshShopReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string, roundIndex: number) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.REFRESH_SHOP) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshShopData(activityData, createTime, serverTime); + if (roundIndex) { + playerData.roundIndex = roundIndex; + } + + let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecord); + + let item = playerData.findItemByProductID(productID); + if (!item) { + return STATUS.ACTIVITY_NO_PRODUCT; + } + if (item.countMax > 0 && item.buyCount >= item.countMax) { + return STATUS.ACTIVITY_MAX_COUNT; + } + + let rewardArray = stringToRewardParam(item.reward) + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.BUY_REFRESH_SHOP); + + await ActivityRefreshShopModel.addRecord(activityId, roleId, playerData.roundIndex, item.pageIndex, item.id, 1); + + item.buyCount += 1; + return { + code: 0, + data: Object.assign(result, { item: item, activityId: activityId }) + } +} + +export async function checkRefreshShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, roundIndex: number) { + if (!activityData) return false; + if (activityData.type !== ACTIVITY_TYPE.REFRESH_SHOP) return false; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshShopData(activityData, createTime, serverTime); + + if(!roundIndex) { + roundIndex = playerData.roundIndex; + } + let playerRecord: ActivityRefreshShopModelType = await ActivityRefreshShopModel.findData(activityData.activityId, roleId, roundIndex); + playerData.setPlayerRecords(playerRecord); + + let item = playerData.findItemByProductID(productID); + if (!item) return false; + if (item.countMax > 0 && item.buyCount >= item.countMax) return false; + return true; +} diff --git a/game-server/app/services/activity/refreshTaskService.ts b/game-server/app/services/activity/refreshTaskService.ts index 1bd5e6dc2..174a36820 100644 --- a/game-server/app/services/activity/refreshTaskService.ts +++ b/game-server/app/services/activity/refreshTaskService.ts @@ -1,28 +1,28 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityRefreshTaskModel, ActivityRefreshTaskModelType } from '../../db/ActivityRefreshTask'; -import { ActivityRefreshTaskPointModel, ActivityRefreshTaskPointModelType } from '../../db/ActivityRefreshTaskPoint'; -import { RefreshTaskData } from '../../domain/activityField/refreshTaskField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; - -/** - * 玩家玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerRefreshTaskData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new RefreshTaskData(activityData, createTime, serverTime); - let playerRecords: ActivityRefreshTaskModelType[] = await ActivityRefreshTaskModel.findData(serverId, activityId, roleId, playerData.roundIndex); - let pointRecordData: ActivityRefreshTaskPointModelType = await ActivityRefreshTaskPointModel.findData(serverId, activityId, roleId); - playerData.setPlayerRecords(playerRecords, pointRecordData); - return playerData; -} - - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityRefreshTaskModel, ActivityRefreshTaskModelType } from '@db/ActivityRefreshTask'; +import { ActivityRefreshTaskPointModel, ActivityRefreshTaskPointModelType } from '@db/ActivityRefreshTaskPoint'; +import { RefreshTaskData } from '@domain/activityField/refreshTaskField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; + +/** + * 玩家玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerRefreshTaskData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new RefreshTaskData(activityData, createTime, serverTime); + let playerRecords: ActivityRefreshTaskModelType[] = await ActivityRefreshTaskModel.findData(serverId, activityId, roleId, playerData.roundIndex); + let pointRecordData: ActivityRefreshTaskPointModelType = await ActivityRefreshTaskPointModel.findData(serverId, activityId, roleId); + playerData.setPlayerRecords(playerRecords, pointRecordData); + return playerData; +} + + diff --git a/game-server/app/services/activity/selfServiceShopActivityService.ts b/game-server/app/services/activity/selfServiceShopActivityService.ts index df7b5ba90..77b33e430 100644 --- a/game-server/app/services/activity/selfServiceShopActivityService.ts +++ b/game-server/app/services/activity/selfServiceShopActivityService.ts @@ -1,161 +1,161 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, REFRESH_TIME, STATUS } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivitySelfServiceGoodsModel, ActivitySelfServiceGoodsModelType } from '../../db/ActivitySelfServiceGoods'; -import { ActivitySelfServiceShopModel, ActivitySelfServiceShopModelType } from '../../db/ActivitySelfServiceShop'; -import { ActivitySelfServiceModel } from '../../db/ActivitySelfService'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { SelfServiceShopData, SelfServiceShopItem } from '../../domain/activityField/selfServiceShopField'; -import { addReward, stringToRewardParam } from './giftPackageService'; -import moment = require('moment'); -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getSelfServiceShopActivityData(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SELF_SERVICE_SHOP); - activityArray = activityArray.sort((a, b) => { - return b.activityId - a.activityId - }); - if (activityArray.length > 0) { - let activityData = activityArray[0]; - let playerData = await getPlayerActivityData(activityData.activityId, serverId, roleId); - return playerData; - } - return null; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerActivityData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SelfServiceShopData(activityData, createTime, serverTime); - - let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByPriceType(serverId, activityId, roleId, playerData.roundIndex); - - playerData.setPlayerRecords(playerRecords); - let playerSelfServerData = await ActivitySelfServiceModel.findData(serverId, activityId, roleId, playerData.roundIndex); - let buyCount = (playerSelfServerData && playerSelfServerData.unitBuyCount) ? playerSelfServerData.unitBuyCount : 0; - playerData.unitBuyCount = buyCount; - let challengeBeginTime = null; - let challengeEndTime = null; - let curDate = moment(new Date()); - if (curDate.hour() < REFRESH_TIME) { - challengeBeginTime = moment(new Date()).startOf('d').add(-1, 'd').add(REFRESH_TIME, 'h').toDate(); - challengeEndTime = moment(challengeBeginTime).add(1, 'd').toDate() - } else { - challengeBeginTime = moment(new Date()).startOf('d').add(REFRESH_TIME, 'h').toDate(); - challengeEndTime = moment(challengeBeginTime).add(1, 'd').toDate() - } - let records = (playerSelfServerData && playerSelfServerData.challengeRecords) ? playerSelfServerData.challengeRecords : []; - for (let record of records) { - // console.log(challengeBeginTime, challengeEndTime, record.time) - if (record.time >= challengeBeginTime && record.time <= challengeEndTime) { - playerData.challengeCount++; - } - } - - return playerData; -} - -/** - * 结算礼包 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {number} roundIndex 周期数 - * @param {number} index 货架 - * @param {number} price 价格 - * @param {number} priceType 价格类型 - * - */ - -export async function addSelfServiceShopGiftReward(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, roundIndex: number, index: number, item: SelfServiceShopItem) { - let playerGoods: ActivitySelfServiceGoodsModelType[] = await ActivitySelfServiceGoodsModel.findDataByIndex(activityId, roleId, roundIndex, index); - - let rewardArray: Array = []; - for (let obj of playerGoods) { - let selectedIndex = obj.rewardIndex; - let cellIndex = obj.cellIndex; - let giftData = item.findCellIndex(cellIndex); - let rewards: Array = stringToRewardParam(giftData.gift); - rewardArray = rewardArray.concat(rewards[selectedIndex]) - } - let goodsStr = ''; - for (let obj of rewardArray) { - goodsStr += `${obj.type}&${obj.id}&${obj.count}|`; - } - let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_GIFT); - //购买记录 - console.log('dddddddd', rewardArray.length, serverId, activityId, roleId, roundIndex, index, goodsStr, JSON.stringify(item)) - await ActivitySelfServiceShopModel.addBuyRecord(serverId, activityId, roleId, roundIndex, index, goodsStr); - return result -} - - -/** - * 购买自选礼包 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeSelfServerShop(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SelfServiceShopData(activityData, createTime, serverTime); - let item: SelfServiceShopItem = playerData.getItemByProductID(productID); - if (!item) { - return STATUS.ACTIVITY_DATA_ERROR - } - if (item.countMax > 0) {//限制购买次数 - let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityId, roleId, playerData.roundIndex, item.index); - if (playerRecords.length >= item.countMax) { - return STATUS.ACTIVITY_MAX_COUNT - } - } - let result = await addSelfServiceShopGiftReward(roleId, roleName, sid, serverId, activityId, playerData.roundIndex, item.index, item); - item.buyCount += 1; - return { - code: 0, - data: Object.assign(result, { item }) - } -} - -export async function checkSelfServiceShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false; - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SelfServiceShopData(activityData, createTime, serverTime); - let item: SelfServiceShopItem = playerData.getItemByProductID(productID); - if (!item) return false - if (item.countMax > 0) {//限制购买次数 - let playerRecords = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityData.activityId, roleId, playerData.roundIndex, item.index); - if (playerRecords.length >= item.countMax) return false; - } - return true; -} +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, REFRESH_TIME, STATUS } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivitySelfServiceGoodsModel, ActivitySelfServiceGoodsModelType } from '@db/ActivitySelfServiceGoods'; +import { ActivitySelfServiceShopModel, ActivitySelfServiceShopModelType } from '@db/ActivitySelfServiceShop'; +import { ActivitySelfServiceModel } from '@db/ActivitySelfService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { SelfServiceShopData, SelfServiceShopItem } from '@domain/activityField/selfServiceShopField'; +import { addReward, stringToRewardParam } from './giftPackageService'; +import moment = require('moment'); +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getSelfServiceShopActivityData(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SELF_SERVICE_SHOP); + activityArray = activityArray.sort((a, b) => { + return b.activityId - a.activityId + }); + if (activityArray.length > 0) { + let activityData = activityArray[0]; + let playerData = await getPlayerActivityData(activityData.activityId, serverId, roleId); + return playerData; + } + return null; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerActivityData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SelfServiceShopData(activityData, createTime, serverTime); + + let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByPriceType(serverId, activityId, roleId, playerData.roundIndex); + + playerData.setPlayerRecords(playerRecords); + let playerSelfServerData = await ActivitySelfServiceModel.findData(serverId, activityId, roleId, playerData.roundIndex); + let buyCount = (playerSelfServerData && playerSelfServerData.unitBuyCount) ? playerSelfServerData.unitBuyCount : 0; + playerData.unitBuyCount = buyCount; + let challengeBeginTime = null; + let challengeEndTime = null; + let curDate = moment(new Date()); + if (curDate.hour() < REFRESH_TIME) { + challengeBeginTime = moment(new Date()).startOf('d').add(-1, 'd').add(REFRESH_TIME, 'h').toDate(); + challengeEndTime = moment(challengeBeginTime).add(1, 'd').toDate() + } else { + challengeBeginTime = moment(new Date()).startOf('d').add(REFRESH_TIME, 'h').toDate(); + challengeEndTime = moment(challengeBeginTime).add(1, 'd').toDate() + } + let records = (playerSelfServerData && playerSelfServerData.challengeRecords) ? playerSelfServerData.challengeRecords : []; + for (let record of records) { + // console.log(challengeBeginTime, challengeEndTime, record.time) + if (record.time >= challengeBeginTime && record.time <= challengeEndTime) { + playerData.challengeCount++; + } + } + + return playerData; +} + +/** + * 结算礼包 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {number} roundIndex 周期数 + * @param {number} index 货架 + * @param {number} price 价格 + * @param {number} priceType 价格类型 + * + */ + +export async function addSelfServiceShopGiftReward(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, roundIndex: number, index: number, item: SelfServiceShopItem) { + let playerGoods: ActivitySelfServiceGoodsModelType[] = await ActivitySelfServiceGoodsModel.findDataByIndex(activityId, roleId, roundIndex, index); + + let rewardArray: Array = []; + for (let obj of playerGoods) { + let selectedIndex = obj.rewardIndex; + let cellIndex = obj.cellIndex; + let giftData = item.findCellIndex(cellIndex); + let rewards: Array = stringToRewardParam(giftData.gift); + rewardArray = rewardArray.concat(rewards[selectedIndex]) + } + let goodsStr = ''; + for (let obj of rewardArray) { + goodsStr += `${obj.type}&${obj.id}&${obj.count}|`; + } + let result = await addReward(roleId, roleName, sid, serverId, rewardArray, ITEM_CHANGE_REASON.SELF_SERVICE_SHOP_BUY_GIFT); + //购买记录 + console.log('dddddddd', rewardArray.length, serverId, activityId, roleId, roundIndex, index, goodsStr, JSON.stringify(item)) + await ActivitySelfServiceShopModel.addBuyRecord(serverId, activityId, roleId, roundIndex, index, goodsStr); + return result +} + + +/** + * 购买自选礼包 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeSelfServerShop(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SelfServiceShopData(activityData, createTime, serverTime); + let item: SelfServiceShopItem = playerData.getItemByProductID(productID); + if (!item) { + return STATUS.ACTIVITY_DATA_ERROR + } + if (item.countMax > 0) {//限制购买次数 + let playerRecords: ActivitySelfServiceShopModelType[] = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityId, roleId, playerData.roundIndex, item.index); + if (playerRecords.length >= item.countMax) { + return STATUS.ACTIVITY_MAX_COUNT + } + } + let result = await addSelfServiceShopGiftReward(roleId, roleName, sid, serverId, activityId, playerData.roundIndex, item.index, item); + item.buyCount += 1; + return { + code: 0, + data: Object.assign(result, { item }) + } +} + +export async function checkSelfServiceShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false; + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SelfServiceShopData(activityData, createTime, serverTime); + let item: SelfServiceShopItem = playerData.getItemByProductID(productID); + if (!item) return false + if (item.countMax > 0) {//限制购买次数 + let playerRecords = await ActivitySelfServiceShopModel.findDataByIndex(serverId, activityData.activityId, roleId, playerData.roundIndex, item.index); + if (playerRecords.length >= item.countMax) return false; + } + return true; +} diff --git a/game-server/app/services/activity/sevenDaysService.ts b/game-server/app/services/activity/sevenDaysService.ts index da654eb1e..8b55b4fad 100644 --- a/game-server/app/services/activity/sevenDaysService.ts +++ b/game-server/app/services/activity/sevenDaysService.ts @@ -1,129 +1,129 @@ -import { ActivityModel, ActivityModelType } from '../../db/Activity'; -import { ActivityGrowthModel, ActivityGrowthModelType } from '../../db/ActivityGrowth'; -import { ActivityGrowthPointModel, ActivityGrowthPointModelType } from '../../db/ActivityGrowthPoint'; -import { SevenDaysData } from '../../domain/activityField/sevenDaysField'; -import { ActivityDailyChallengesModel, ActivityDailyChallengesModelType } from '../../db/ActivityDailyChallenges'; -import { ActivityDailyGiftsModel, ActivityDailyGiftsModelType } from '../../db/ActivityDailyGifts'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function sevenDaysActivity(serverId: number, roleId: string, type: number) { - let activityDataArray = await getActivitiesByType(serverId, type); - if (activityDataArray.length === 0) { - return null; - } - let activityData: ActivityModelType = activityDataArray[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SevenDaysData(activityData, createTime, serverTime); - //成长数据 - let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityData.activityId, roleId); - let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityData.activityId, roleId); - playerData.growth.setPlayerRecords(playerGrowthRecords); - playerData.growth.setPlayerPointRecord(playerPointRecord); - //今日挑战 - let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityData.activityId, roleId); - playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); - //每日特惠礼包 - let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityData.activityId, roleId); - playerData.dailyGift.setPlayerRecords(playerRecords); - - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerSevenDaysData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SevenDaysData(activityData, createTime, serverTime); - //成长数据 - let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); - let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); - playerData.growth.setPlayerRecords(playerGrowthRecords); - playerData.growth.setPlayerPointRecord(playerPointRecord); - //今日挑战 - let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); - playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); - //每日特惠礼包 - let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); - playerData.dailyGift.setPlayerRecords(playerRecords); - return playerData; -} - - -/** - * 玩家成长数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerSevenDaysGrowthData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SevenDaysData(activityData, createTime, serverTime); - //成长数据 - let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); - let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); - playerData.growth.setPlayerRecords(playerGrowthRecords); - playerData.growth.setPlayerPointRecord(playerPointRecord); - return playerData; -} - - -/** - * 玩家今日挑战数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerSevenDaysDailyChallengesData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SevenDaysData(activityData, createTime, serverTime); - //今日挑战 - let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); - playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); - return playerData; -} - -/** - * 玩家每日特惠礼包数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerSevenDaysDailyGiftsData(activityId: number, serverId: number, roleId: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SevenDaysData(activityData, createTime, serverTime); - //每日特惠礼包 - let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); - playerData.dailyGift.setPlayerRecords(playerRecords); - return playerData; -} \ No newline at end of file +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { ActivityGrowthModel, ActivityGrowthModelType } from '@db/ActivityGrowth'; +import { ActivityGrowthPointModel, ActivityGrowthPointModelType } from '@db/ActivityGrowthPoint'; +import { SevenDaysData } from '@domain/activityField/sevenDaysField'; +import { ActivityDailyChallengesModel, ActivityDailyChallengesModelType } from '@db/ActivityDailyChallenges'; +import { ActivityDailyGiftsModel, ActivityDailyGiftsModelType } from '@db/ActivityDailyGifts'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function sevenDaysActivity(serverId: number, roleId: string, type: number) { + let activityDataArray = await getActivitiesByType(serverId, type); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SevenDaysData(activityData, createTime, serverTime); + //成长数据 + let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityData.activityId, roleId); + let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityData.activityId, roleId); + playerData.growth.setPlayerRecords(playerGrowthRecords); + playerData.growth.setPlayerPointRecord(playerPointRecord); + //今日挑战 + let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityData.activityId, roleId); + playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); + //每日特惠礼包 + let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityData.activityId, roleId); + playerData.dailyGift.setPlayerRecords(playerRecords); + + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSevenDaysData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SevenDaysData(activityData, createTime, serverTime); + //成长数据 + let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); + let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); + playerData.growth.setPlayerRecords(playerGrowthRecords); + playerData.growth.setPlayerPointRecord(playerPointRecord); + //今日挑战 + let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); + playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); + //每日特惠礼包 + let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); + playerData.dailyGift.setPlayerRecords(playerRecords); + return playerData; +} + + +/** + * 玩家成长数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSevenDaysGrowthData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SevenDaysData(activityData, createTime, serverTime); + //成长数据 + let playerGrowthRecords: ActivityGrowthModelType[] = await ActivityGrowthModel.findData(serverId, activityId, roleId); + let playerPointRecord: ActivityGrowthPointModelType = await ActivityGrowthPointModel.findData(serverId, activityId, roleId); + playerData.growth.setPlayerRecords(playerGrowthRecords); + playerData.growth.setPlayerPointRecord(playerPointRecord); + return playerData; +} + + +/** + * 玩家今日挑战数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSevenDaysDailyChallengesData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SevenDaysData(activityData, createTime, serverTime); + //今日挑战 + let playerDailyChallengeRecords: ActivityDailyChallengesModelType[] = await ActivityDailyChallengesModel.findData(serverId, activityId, roleId); + playerData.dailyChallenge.setPlayerRecords(playerDailyChallengeRecords); + return playerData; +} + +/** + * 玩家每日特惠礼包数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSevenDaysDailyGiftsData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SevenDaysData(activityData, createTime, serverTime); + //每日特惠礼包 + let playerRecords: ActivityDailyGiftsModelType[] = await ActivityDailyGiftsModel.findData(serverId, activityId, roleId); + playerData.dailyGift.setPlayerRecords(playerRecords); + return playerData; +} diff --git a/game-server/app/services/activity/signInService.ts b/game-server/app/services/activity/signInService.ts index 4cb7bc3e7..6d3117d3e 100644 --- a/game-server/app/services/activity/signInService.ts +++ b/game-server/app/services/activity/signInService.ts @@ -1,164 +1,164 @@ -import moment = require('moment'); -import { ACTIVITY_TYPE, MAIL_TYPE, SERVER_OPEN_TIME, SIGNIN_VIP_OPEN_LIMIT, STATUS } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { ActivitySignInModel, ActivitySignInModelType } from '../../db/ActivitySignIn'; -import { SignInData } from '../../domain/activityField/signInField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { RewardInter } from '../../pubUtils/interface'; -import { stringToRewardInter } from './giftPackageService'; -import { sendMailByContent } from '../mailService'; - -/** - * 获取活动数据 - * - * @param {number} type 普通、高级 ACTIVITY_TYPE - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function signInActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SIGN_IN); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SignInData(activityData, createTime, serverTime); - let curDate = moment(new Date()).valueOf(); - if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 - return null; - } - let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - -/** - * 获取活动数据 - * - * @param {number} type 普通、高级 ACTIVITY_TYPE - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function signInVIPActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SIGN_IN_VIP); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new SignInData(activityData, createTime, serverTime); - - let curDate = moment(new Date()).valueOf(); - if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 - return null; - } - - let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityData.activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerSignInData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - if (activityData.type !== ACTIVITY_TYPE.SIGN_IN_VIP && activityData.type !== ACTIVITY_TYPE.SIGN_IN && activityData.type !== ACTIVITY_TYPE.NEW_PLAYER_SIGN_IN - && activityData.type !== ACTIVITY_TYPE.COMMON_SIGN_IN) { - return null; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - - let playerData = new SignInData(activityData, createTime, serverTime); - let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityId, roleId, playerData.roundIndex); - playerData.setPlayerRecords(playerRecords); - return playerData; -} - - -/** - * 购买vip签到 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeSignInVIP(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (activityData.type !== ACTIVITY_TYPE.SIGN_IN_VIP && activityData.type !== ACTIVITY_TYPE.COMMON_SIGN_IN) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let playerData = await getPlayerSignInData(activityId, serverId, roleId); - if (!playerData || playerData.isVip) { - return STATUS.ORDER_CANNOT_BUY; - } - await ActivitySignInModel.buyVIP(activityId, roleId, playerData.roundIndex); - - return { - code: 0, - data: Object.assign({}, { item: { isVip: true }, activityId: activityData.activityId }) - } -} - -//高级签到开启条件 -export async function canBuyVip(lv: number) { - //高级签到开启条件 - let openTime = SERVER_OPEN_TIME; - if (moment(openTime).valueOf() + 24 * 60 * 60 * 1000 * 8 > moment(new Date()).valueOf()) {//开服时间8天后才能开启vip签到 - return false; - } - if (lv < SIGNIN_VIP_OPEN_LIMIT) {//玩家等级大于等于15级才能开启vip签到 - return false - } - return true; -} - - -export async function checkSignInCanBuy(roleId: string, serverId: number, activityId: number, productID: string) { - - let playerData = await getPlayerSignInData(activityId, serverId, roleId); - if (!playerData || playerData.isVip) { - return false; - } - - return true -} - -// 补发签到邮件 -export async function repairSignInMail(playerData: SignInData) { - if(!playerData || playerData.productID == '&') return; - let playerRecords = await ActivitySignInModel.findByActivity(playerData.activityId, 1); - let hasRepaireRoleIds: string[] = [] - for(let playerRecord of playerRecords) { - if(playerRecord.hasRepair) continue; - let notSendGoods: RewardInter[] = []; - let records = playerRecord.records||[]; - for(let item of playerData.list) { - let curRec = records.find(rec => rec.dayIndex == item.dayIndex); - if(!curRec) { - notSendGoods.push(...stringToRewardInter(item.reward)); - } - } - if(notSendGoods.length > 0) { - await sendMailByContent(MAIL_TYPE.REPAIRE_SIGN_IN, playerRecord.roleId, { goods: notSendGoods }); - hasRepaireRoleIds.push(playerRecord.roleId); - } - } - await ActivitySignInModel.repairSignIn(playerData.activityId, hasRepaireRoleIds); -} \ No newline at end of file +import moment = require('moment'); +import { ACTIVITY_TYPE, MAIL_TYPE, SERVER_OPEN_TIME, SIGNIN_VIP_OPEN_LIMIT, STATUS } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { ActivitySignInModel, ActivitySignInModelType } from '@db/ActivitySignIn'; +import { SignInData } from '@domain/activityField/signInField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { RewardInter } from '@pubUtils/interface'; +import { stringToRewardInter } from './giftPackageService'; +import { sendMailByContent } from '../mailService'; + +/** + * 获取活动数据 + * + * @param {number} type 普通、高级 ACTIVITY_TYPE + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function signInActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SIGN_IN); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SignInData(activityData, createTime, serverTime); + let curDate = moment(new Date()).valueOf(); + if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 + return null; + } + let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + +/** + * 获取活动数据 + * + * @param {number} type 普通、高级 ACTIVITY_TYPE + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function signInVIPActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.SIGN_IN_VIP); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new SignInData(activityData, createTime, serverTime); + + let curDate = moment(new Date()).valueOf(); + if (curDate < playerData.beginTime || curDate > playerData.endTime) {//未开启 + return null; + } + + let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityData.activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSignInData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + if (activityData.type !== ACTIVITY_TYPE.SIGN_IN_VIP && activityData.type !== ACTIVITY_TYPE.SIGN_IN && activityData.type !== ACTIVITY_TYPE.NEW_PLAYER_SIGN_IN + && activityData.type !== ACTIVITY_TYPE.COMMON_SIGN_IN) { + return null; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + + let playerData = new SignInData(activityData, createTime, serverTime); + let playerRecords: ActivitySignInModelType = await ActivitySignInModel.findData(activityId, roleId, playerData.roundIndex); + playerData.setPlayerRecords(playerRecords); + return playerData; +} + + +/** + * 购买vip签到 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeSignInVIP(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (activityData.type !== ACTIVITY_TYPE.SIGN_IN_VIP && activityData.type !== ACTIVITY_TYPE.COMMON_SIGN_IN) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let playerData = await getPlayerSignInData(activityId, serverId, roleId); + if (!playerData || playerData.isVip) { + return STATUS.ORDER_CANNOT_BUY; + } + await ActivitySignInModel.buyVIP(activityId, roleId, playerData.roundIndex); + + return { + code: 0, + data: Object.assign({}, { item: { isVip: true }, activityId: activityData.activityId }) + } +} + +//高级签到开启条件 +export async function canBuyVip(lv: number) { + //高级签到开启条件 + let openTime = SERVER_OPEN_TIME; + if (moment(openTime).valueOf() + 24 * 60 * 60 * 1000 * 8 > moment(new Date()).valueOf()) {//开服时间8天后才能开启vip签到 + return false; + } + if (lv < SIGNIN_VIP_OPEN_LIMIT) {//玩家等级大于等于15级才能开启vip签到 + return false + } + return true; +} + + +export async function checkSignInCanBuy(roleId: string, serverId: number, activityId: number, productID: string) { + + let playerData = await getPlayerSignInData(activityId, serverId, roleId); + if (!playerData || playerData.isVip) { + return false; + } + + return true +} + +// 补发签到邮件 +export async function repairSignInMail(playerData: SignInData) { + if(!playerData || playerData.productID == '&') return; + let playerRecords = await ActivitySignInModel.findByActivity(playerData.activityId, 1); + let hasRepaireRoleIds: string[] = [] + for(let playerRecord of playerRecords) { + if(playerRecord.hasRepair) continue; + let notSendGoods: RewardInter[] = []; + let records = playerRecord.records||[]; + for(let item of playerData.list) { + let curRec = records.find(rec => rec.dayIndex == item.dayIndex); + if(!curRec) { + notSendGoods.push(...stringToRewardInter(item.reward)); + } + } + if(notSendGoods.length > 0) { + await sendMailByContent(MAIL_TYPE.REPAIRE_SIGN_IN, playerRecord.roleId, { goods: notSendGoods }); + hasRepaireRoleIds.push(playerRecord.roleId); + } + } + await ActivitySignInModel.repairSignIn(playerData.activityId, hasRepaireRoleIds); +} diff --git a/game-server/app/services/activity/taskPassService.ts b/game-server/app/services/activity/taskPassService.ts index 1f6ea4df8..a1136d1bb 100644 --- a/game-server/app/services/activity/taskPassService.ts +++ b/game-server/app/services/activity/taskPassService.ts @@ -1,100 +1,100 @@ -import { ACTIVITY_TYPE, STATUS } from "../../consts"; -import { ActivityModelType } from "../../db/Activity"; -import { ActivityTaskPassModel } from "../../db/ActivityTaskPass"; -import { TaskPassData } from "../../domain/activityField/taskPassField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivitiesByType, getActivityById, pushActivityInter } from "./activityService"; - -export async function getTaskPassData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TaskPassData(activityData, createTime, serverTime); - let record = await ActivityTaskPassModel.findData(serverId, activityId, roleId, playerData.roundIndex); - - playerData.setPlayerRecord(record); - - return playerData; -} - -export async function getTaskPassDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getTaskPassData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - - -/** - * 购买高级战令 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ - export async function makeTaskPass(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.TASK_PASS) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TaskPassData(activityData, createTime, serverTime); - let roundIndex = playerData.roundIndex; - let checkResult = await ActivityTaskPassModel.check(serverId, activityData.activityId, roleId, roundIndex, productID); - if(checkResult) return STATUS.ORDER_CANNOT_BUY; - - await ActivityTaskPassModel.buy(serverId, activityId, roleId, roundIndex, productID); - return { - code: 0, - data: Object.assign({}, { item: { roundIndex }, activityId: activityId }) - } -} - -export async function checkTaskPass(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TaskPassData(activityData, createTime, serverTime); - let roundIndex = playerData.roundIndex; - - let checkResult = await ActivityTaskPassModel.check(serverId, activityData.activityId, roleId, roundIndex, productID); - return !checkResult; -} - -/** - * 任务活动完成后会获得点数 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function addTaskPassPoint(serverId: number, roleId: string, addPoint: number) { - try { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_PASS); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - - let pushResult: pushActivityInter[] = []; - for(let activityData of activities) { - let playerData = new TaskPassData(activityData, createTime, serverTime); - if(playerData.canShow()) { - let result = await ActivityTaskPassModel.addPoint(serverId, activityData.activityId, roleId, playerData.roundIndex, addPoint); - if(result) pushResult.push({ activityId: activityData.activityId, activityType: activityData.type, param: { totalPoint: result.totalPoint } }); - } - } - - return pushResult - } catch(e) { - console.error(e); - return [] - } -} \ No newline at end of file +import { ACTIVITY_TYPE, STATUS } from "@consts"; +import { ActivityModelType } from "@db/Activity"; +import { ActivityTaskPassModel } from "@db/ActivityTaskPass"; +import { TaskPassData } from "@domain/activityField/taskPassField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivitiesByType, getActivityById, pushActivityInter } from "./activityService"; + +export async function getTaskPassData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TaskPassData(activityData, createTime, serverTime); + let record = await ActivityTaskPassModel.findData(serverId, activityId, roleId, playerData.roundIndex); + + playerData.setPlayerRecord(record); + + return playerData; +} + +export async function getTaskPassDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getTaskPassData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + + +/** + * 购买高级战令 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ + export async function makeTaskPass(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.TASK_PASS) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TaskPassData(activityData, createTime, serverTime); + let roundIndex = playerData.roundIndex; + let checkResult = await ActivityTaskPassModel.check(serverId, activityData.activityId, roleId, roundIndex, productID); + if(checkResult) return STATUS.ORDER_CANNOT_BUY; + + await ActivityTaskPassModel.buy(serverId, activityId, roleId, roundIndex, productID); + return { + code: 0, + data: Object.assign({}, { item: { roundIndex }, activityId: activityId }) + } +} + +export async function checkTaskPass(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TaskPassData(activityData, createTime, serverTime); + let roundIndex = playerData.roundIndex; + + let checkResult = await ActivityTaskPassModel.check(serverId, activityData.activityId, roleId, roundIndex, productID); + return !checkResult; +} + +/** + * 任务活动完成后会获得点数 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function addTaskPassPoint(serverId: number, roleId: string, addPoint: number) { + try { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TASK_PASS); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + + let pushResult: pushActivityInter[] = []; + for(let activityData of activities) { + let playerData = new TaskPassData(activityData, createTime, serverTime); + if(playerData.canShow()) { + let result = await ActivityTaskPassModel.addPoint(serverId, activityData.activityId, roleId, playerData.roundIndex, addPoint); + if(result) pushResult.push({ activityId: activityData.activityId, activityType: activityData.type, param: { totalPoint: result.totalPoint } }); + } + } + + return pushResult + } catch(e) { + console.error(e); + return [] + } +} diff --git a/game-server/app/services/activity/thirtyDaysService.ts b/game-server/app/services/activity/thirtyDaysService.ts index d0f321b08..a1a77a41b 100644 --- a/game-server/app/services/activity/thirtyDaysService.ts +++ b/game-server/app/services/activity/thirtyDaysService.ts @@ -1,72 +1,72 @@ -import { ActivityThirtyDaysModel, ActivityThirtyDaysModelType } from '../../db/ActivityThirtyDays'; -import { ThirtyDaysData } from '../../domain/activityField/thirtyDaysField'; -import { ActivityThirtyDaysPointRewardModel, ActivityThirtyDaysPointRewardModelType } from '../../db/ActivityThirtyDaysPointReward'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function thirtyDaysActivity(type: number, serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, type); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerData = await getPlayerThirtyDaysData(activityData.activityId, serverId, roleId); - - return playerData -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerThirtyDaysData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecords: ActivityThirtyDaysModelType[] = await ActivityThirtyDaysModel.findData(serverId, activityId, roleId); - let playerPointRecords: ActivityThirtyDaysPointRewardModelType[] = await ActivityThirtyDaysPointRewardModel.findData(activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new ThirtyDaysData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - playerData.setPlayerPointRecords(playerPointRecords); - - // let playerHeroes = await HeroModel.findByRole(roleId); - // let colorStarHeroes = playerHeroes.filter(obj => { return obj && obj.colorStar > 0 }) - // playerData.setColorStarCount(colorStarHeroes.length); - - return playerData; -} - -/** - * 活动任务添加统计次数 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function addPlayerThirtyDaysTask(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecords: ActivityThirtyDaysModelType[] = await ActivityThirtyDaysModel.findData(serverId, activityId, roleId); - let playerPointRecords: ActivityThirtyDaysPointRewardModelType[] = await ActivityThirtyDaysPointRewardModel.findData(activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new ThirtyDaysData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecords); - playerData.setPlayerPointRecords(playerPointRecords); - return playerData; -} \ No newline at end of file +import { ActivityThirtyDaysModel, ActivityThirtyDaysModelType } from '@db/ActivityThirtyDays'; +import { ThirtyDaysData } from '@domain/activityField/thirtyDaysField'; +import { ActivityThirtyDaysPointRewardModel, ActivityThirtyDaysPointRewardModelType } from '@db/ActivityThirtyDaysPointReward'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function thirtyDaysActivity(type: number, serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, type); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerData = await getPlayerThirtyDaysData(activityData.activityId, serverId, roleId); + + return playerData +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerThirtyDaysData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecords: ActivityThirtyDaysModelType[] = await ActivityThirtyDaysModel.findData(serverId, activityId, roleId); + let playerPointRecords: ActivityThirtyDaysPointRewardModelType[] = await ActivityThirtyDaysPointRewardModel.findData(activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new ThirtyDaysData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + playerData.setPlayerPointRecords(playerPointRecords); + + // let playerHeroes = await HeroModel.findByRole(roleId); + // let colorStarHeroes = playerHeroes.filter(obj => { return obj && obj.colorStar > 0 }) + // playerData.setColorStarCount(colorStarHeroes.length); + + return playerData; +} + +/** + * 活动任务添加统计次数 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function addPlayerThirtyDaysTask(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecords: ActivityThirtyDaysModelType[] = await ActivityThirtyDaysModel.findData(serverId, activityId, roleId); + let playerPointRecords: ActivityThirtyDaysPointRewardModelType[] = await ActivityThirtyDaysPointRewardModel.findData(activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new ThirtyDaysData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecords); + playerData.setPlayerPointRecords(playerPointRecords); + return playerData; +} diff --git a/game-server/app/services/activity/timeLimitRankService.ts b/game-server/app/services/activity/timeLimitRankService.ts index c57b3a191..b78bc6e86 100644 --- a/game-server/app/services/activity/timeLimitRankService.ts +++ b/game-server/app/services/activity/timeLimitRankService.ts @@ -1,138 +1,138 @@ -import { ACTIVITY_TYPE, getRedisKeyByRankType, MAIL_TYPE, RANK_TYPE, REDIS_KEY } from "../../consts"; -import { ActivityGroupModel } from "../../db/ActivityGroup"; -import { ActivityTimeLimitRankModel, ActivityTimeLimitRankModelTypeParam } from "../../db/ActivityTimeLimitRank"; -import { GuildModel, GuildType } from "../../db/Guild"; -import { RoleModel } from "../../db/Role"; -import { TimeLimitRankData } from "../../domain/activityField/timeLimitRankField"; -import { GuildRankInfo, RoleRankInfo } from "../../domain/rank"; -import { stringWithTypeToRewardInter } from "../../pubUtils/roleUtil"; -import { sendMailByContent, sendMailToGuildByContent, sendMailToManyPlayerByContent } from "../mailService"; -import { Rank } from "../rankService"; -import { getServerCreateTime } from "../redisService"; -import { getActivitiesByType, getActivityById } from "./activityService"; - - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ - export async function getTimeLimitRankData(activityId: number, serverId: number) { - let activityData = await getActivityById(activityId); - let serverTime = await getServerCreateTime(serverId); - - let playerData = new TimeLimitRankData(activityData, 0, serverTime); - return playerData; -} - -export async function getTimeLimitRankDataShow(activityId: number, serverId: number) { - let playerData = await getTimeLimitRankData(activityId, serverId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - - -/** - * @description 记录每次活动获得的资金排行榜 - * @param serverId - * @param code - * @param fund - */ -export async function recordGuildFund(serverId: number, guild: GuildType, fund: number) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TIME_LIMIT_RANK); - for(let activity of activities) { - let serverTime = await getServerCreateTime(serverId); - let playerData = new TimeLimitRankData(activity, 0, serverTime); - if(playerData.canRecord() && playerData.rankType == RANK_TYPE.GUILD_FUND) { - await ActivityTimeLimitRankModel.addGuildScore(serverId, playerData.activityId, playerData.rankType, guild.code, fund, guild._id); - - let redisKey = getRedisKeyByRankType(playerData.rankType); - // 加入排行 - let r = new Rank(redisKey, { serverId, activityId: playerData.activityId }); - await r.setRankWithGuildInfo(guild.code, fund, Date.now(), guild, true); - } - } -} - -/** - * 活动结束发送排行榜奖励 - * @param data {TimeLimitRankData} 活动数据 - * @returns - */ -export async function sendRankMail(data: TimeLimitRankData, serverId: number) { - let redisKey = getRedisKeyByRankType(data.rankType, true); - if (!redisKey) return null; - let r = new Rank(redisKey, { activityId: data.activityId, serverId }); - if(r.infoKey == REDIS_KEY.GUILD_INFO) { - let allRank = (await r.getRankByRange()); - - for(let { rank, code, name, leader } of allRank) { - let reward = data.getRewardByRank(rank); - if(reward) { - let guild = await GuildModel.findByCode(code, serverId, '+members'); - // console.log(guild.members) - for(let roleId of guild.members) { - await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, { - params: [data.tabName,`${rank}`], - goods: stringWithTypeToRewardInter(roleId == leader.roleId? reward.rewards: reward.guildRewards) - }); - } - } - } - } else { - let allRank = (await r.getRankByRange()); - let sentRoleIds: string[] = []; - for(let { rank, roleId } of allRank) { - let reward = data.getRewardByRank(rank); - if(reward) { - await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, { - params: [data.tabName, `${rank}`], - goods: stringWithTypeToRewardInter(reward.rewards) - }); - sentRoleIds.push(roleId); - } - } - let lastReward = data.getRewardByRank(9999); - let roles = await RoleModel.findAllRoleForTimeLimitRank(serverId, 16); - let roleIds: string[] = []; - for(let { roleId } of roles) { - if(sentRoleIds.indexOf(roleId) == -1) roleIds.push(roleId); - } - await sendMailToManyPlayerByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleIds, { - params: [data.tabName, '200+'], - goods: stringWithTypeToRewardInter(lastReward.rewards) - }); - } -} - -export async function takeSnapshot(data: TimeLimitRankData, serverId: number) { - let redisKey = getRedisKeyByRankType(data.rankType); - let targetRedisKey = getRedisKeyByRankType(data.rankType, true); - if (!redisKey || !targetRedisKey || redisKey == targetRedisKey) return null; - - - let insertInfos: ActivityTimeLimitRankModelTypeParam[] = []; - let r = new Rank(redisKey, { serverId, activityId: data.activityId }); - let allRank = await r.getRankDataByRankWithoutDetail(); - let targetR = new Rank(targetRedisKey, { serverId, activityId: data.activityId }); - for(let rank of allRank) { - await targetR.setRank(rank.myId, rank.scores); - - let insertBaseInfo = { - serverId, activityId: data.activityId, rankType: data.rankType, score: rank.scores[0]||0, time: rank.scores[1]||0 - } - if(rank.myId.roleId) { - let role = await RoleModel.findByRoleId(rank.myId.roleId, '_id roleId'); - if(role) insertInfos.push({ ...insertBaseInfo, roleId: role.roleId, role: role._id }); - } else if(rank.myId.guildCode) { - let guild = await GuildModel.findByCode(rank.myId.guildCode, serverId, '_id guildCode'); - if(guild) insertInfos.push({ ...insertBaseInfo, guildCode: guild.code, guild: guild._id }); - } - } - await ActivityTimeLimitRankModel.insertRanks(insertInfos); -} \ No newline at end of file +import { ACTIVITY_TYPE, getRedisKeyByRankType, MAIL_TYPE, RANK_TYPE, REDIS_KEY } from "@consts"; +import { ActivityGroupModel } from "@db/ActivityGroup"; +import { ActivityTimeLimitRankModel, ActivityTimeLimitRankModelTypeParam } from "@db/ActivityTimeLimitRank"; +import { GuildModel, GuildType } from "@db/Guild"; +import { RoleModel } from "@db/Role"; +import { TimeLimitRankData } from "@domain/activityField/timeLimitRankField"; +import { GuildRankInfo, RoleRankInfo } from "@domain/rank"; +import { stringWithTypeToRewardInter } from "@pubUtils/roleUtil"; +import { sendMailByContent, sendMailToGuildByContent, sendMailToManyPlayerByContent } from "../mailService"; +import { Rank } from "../rankService"; +import { getServerCreateTime } from "../redisService"; +import { getActivitiesByType, getActivityById } from "./activityService"; + + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ + export async function getTimeLimitRankData(activityId: number, serverId: number) { + let activityData = await getActivityById(activityId); + let serverTime = await getServerCreateTime(serverId); + + let playerData = new TimeLimitRankData(activityData, 0, serverTime); + return playerData; +} + +export async function getTimeLimitRankDataShow(activityId: number, serverId: number) { + let playerData = await getTimeLimitRankData(activityId, serverId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + + +/** + * @description 记录每次活动获得的资金排行榜 + * @param serverId + * @param code + * @param fund + */ +export async function recordGuildFund(serverId: number, guild: GuildType, fund: number) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TIME_LIMIT_RANK); + for(let activity of activities) { + let serverTime = await getServerCreateTime(serverId); + let playerData = new TimeLimitRankData(activity, 0, serverTime); + if(playerData.canRecord() && playerData.rankType == RANK_TYPE.GUILD_FUND) { + await ActivityTimeLimitRankModel.addGuildScore(serverId, playerData.activityId, playerData.rankType, guild.code, fund, guild._id); + + let redisKey = getRedisKeyByRankType(playerData.rankType); + // 加入排行 + let r = new Rank(redisKey, { serverId, activityId: playerData.activityId }); + await r.setRankWithGuildInfo(guild.code, fund, Date.now(), guild, true); + } + } +} + +/** + * 活动结束发送排行榜奖励 + * @param data {TimeLimitRankData} 活动数据 + * @returns + */ +export async function sendRankMail(data: TimeLimitRankData, serverId: number) { + let redisKey = getRedisKeyByRankType(data.rankType, true); + if (!redisKey) return null; + let r = new Rank(redisKey, { activityId: data.activityId, serverId }); + if(r.infoKey == REDIS_KEY.GUILD_INFO) { + let allRank = (await r.getRankByRange()); + + for(let { rank, code, name, leader } of allRank) { + let reward = data.getRewardByRank(rank); + if(reward) { + let guild = await GuildModel.findByCode(code, serverId, '+members'); + // console.log(guild.members) + for(let roleId of guild.members) { + await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, { + params: [data.tabName,`${rank}`], + goods: stringWithTypeToRewardInter(roleId == leader.roleId? reward.rewards: reward.guildRewards) + }); + } + } + } + } else { + let allRank = (await r.getRankByRange()); + let sentRoleIds: string[] = []; + for(let { rank, roleId } of allRank) { + let reward = data.getRewardByRank(rank); + if(reward) { + await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, { + params: [data.tabName, `${rank}`], + goods: stringWithTypeToRewardInter(reward.rewards) + }); + sentRoleIds.push(roleId); + } + } + let lastReward = data.getRewardByRank(9999); + let roles = await RoleModel.findAllRoleForTimeLimitRank(serverId, 16); + let roleIds: string[] = []; + for(let { roleId } of roles) { + if(sentRoleIds.indexOf(roleId) == -1) roleIds.push(roleId); + } + await sendMailToManyPlayerByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleIds, { + params: [data.tabName, '200+'], + goods: stringWithTypeToRewardInter(lastReward.rewards) + }); + } +} + +export async function takeSnapshot(data: TimeLimitRankData, serverId: number) { + let redisKey = getRedisKeyByRankType(data.rankType); + let targetRedisKey = getRedisKeyByRankType(data.rankType, true); + if (!redisKey || !targetRedisKey || redisKey == targetRedisKey) return null; + + + let insertInfos: ActivityTimeLimitRankModelTypeParam[] = []; + let r = new Rank(redisKey, { serverId, activityId: data.activityId }); + let allRank = await r.getRankDataByRankWithoutDetail(); + let targetR = new Rank(targetRedisKey, { serverId, activityId: data.activityId }); + for(let rank of allRank) { + await targetR.setRank(rank.myId, rank.scores); + + let insertBaseInfo = { + serverId, activityId: data.activityId, rankType: data.rankType, score: rank.scores[0]||0, time: rank.scores[1]||0 + } + if(rank.myId.roleId) { + let role = await RoleModel.findByRoleId(rank.myId.roleId, '_id roleId'); + if(role) insertInfos.push({ ...insertBaseInfo, roleId: role.roleId, role: role._id }); + } else if(rank.myId.guildCode) { + let guild = await GuildModel.findByCode(rank.myId.guildCode, serverId, '_id guildCode'); + if(guild) insertInfos.push({ ...insertBaseInfo, guildCode: guild.code, guild: guild._id }); + } + } + await ActivityTimeLimitRankModel.insertRanks(insertInfos); +} diff --git a/game-server/app/services/activity/treasureHuntService.ts b/game-server/app/services/activity/treasureHuntService.ts index 9d5a51a34..3c246fd76 100644 --- a/game-server/app/services/activity/treasureHuntService.ts +++ b/game-server/app/services/activity/treasureHuntService.ts @@ -1,160 +1,160 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS, TREASURE_HUNT_DATA_TYPE } from '../../consts'; -import { ActivityTreasureHuntShopModel } from '../../db/ActivityTreasureHuntShop'; -import { ActivityTreasureHuntTaskModel } from '../../db/ActivityTreasureHuntTask'; -import { ActivityTreasureHuntTreasureShopModel } from '../../db/ActivityTreasureHuntTreasureShop'; -import { ActivityTreasureHuntFirstPageModel } from '../../db/ActivityTreasureHuntFirstPage'; -import { TreasureHuntData } from '../../domain/activityField/treasureHuntField'; -import { addReward, stringToConsumeParam, stringToRewardParam } from './giftPackageService'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { getActivitiesByType, getActivityById, getActivityByServerId } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { handleCost } from '../role/rewardService'; -import { ActivityTreasureHuntChallengeModel } from '../../db/ActivityTreasureHuntChallenge'; -import { ActivityModelType } from '../../db/Activity'; - -export async function getPlayerTreasureHuntDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getPlayerTreasureHuntData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerTreasureHuntData(activityId: number, serverId: number, roleId: string, dataType: TREASURE_HUNT_DATA_TYPE = TREASURE_HUNT_DATA_TYPE.ALL) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TreasureHuntData(activityData, createTime, serverTime); - if(dataType == TREASURE_HUNT_DATA_TYPE.FIRST_PAGE || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { - let playerTreasureFirstPageRecord = await ActivityTreasureHuntFirstPageModel.findData(serverId, activityId, roleId, playerData.roundIndex); - playerData.firstPage.setPlayerFirstPageRecord(playerTreasureFirstPageRecord); - } - if (dataType == TREASURE_HUNT_DATA_TYPE.SHOP || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { - let playerShopRecord = await ActivityTreasureHuntShopModel.findTreasureData(activityId, roleId, playerData.roundIndex, playerData.todayIndex); - playerData.shop.setPlayerShopRecords(playerShopRecord); - } - if (dataType == TREASURE_HUNT_DATA_TYPE.TASK || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { - let playerTaskRecord = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityId, roleId, playerData.roundIndex); - playerData.tasks.setPlayerTaskRecords(playerTaskRecord); - } - if(dataType == TREASURE_HUNT_DATA_TYPE.TREASURE_SHOP || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { - let playerTreasureShopRecord = await ActivityTreasureHuntTreasureShopModel.findData(activityId, roleId, playerData.roundIndex); - playerData.treasureShop.setPlayerTreasureShopRecords(playerTreasureShopRecord); - } - if(dataType == TREASURE_HUNT_DATA_TYPE.CHALLENGE || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { - let playerRecord = await ActivityTreasureHuntChallengeModel.findData(serverId, activityId, roleId, playerData.roundIndex); - playerData.challenge.setChallengeRecord(playerRecord) - } - - return playerData; -} - -export async function getPlayerTreasureHuntFirstPageData(activityId: number, serverId: number, roleId: string) { - return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.FIRST_PAGE); -} - -export async function getPlayerTreasureHuntShopData(activityId: number, serverId: number, roleId: string) { - return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.SHOP); -} - -export async function getPlayerTreasureHuntTaskData(activityId: number, serverId: number, roleId: string) { - return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.TASK); -} - -export async function getPlayerTreasureHuntChallengeData(activityId: number, serverId: number, roleId: string) { - return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.CHALLENGE); -} - -export async function getPlayerTreasureHuntTreasureShopData(activityId: number, serverId: number, roleId: string) { - return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.TREASURE_SHOP); -} - -/** - * 购买每日物资 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeShop(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - // let activityData: ActivityModelType = await ActivityModel.findActivity(activityId); - let playerData = await getPlayerTreasureHuntShopData(activityId, serverId, roleId,); - if (!playerData) { - return { - code: STATUS.ACTIVITY_MISSING, - } - } - - let item = playerData.shop.findProductID(productID) - - if (!item) { - return { - code: STATUS.ACTIVITY_MISSING, - } - } - if (item.buyCount >= item.countMax) { - return { - code: STATUS.ACTIVITY_MAX_COUNT, - } - } - let cellIndex = item.cellIndex; - - //添加购买记录 - await ActivityTreasureHuntShopModel.buyShopRecord(activityId, roleId, playerData.roundIndex, playerData.todayIndex, cellIndex, 1); - - let rewardParamArr: Array = stringToRewardParam(item.reward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY) - - item.buyCount += 1; - return { - code: 0, - data: Object.assign(result, { item }) - } -} - -export async function checkTreasureHuntShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { - if(!activityData) return false; - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new TreasureHuntData(activityData, createTime, serverTime); - - let playerShopRecord = await ActivityTreasureHuntShopModel.findTreasureData(activityData.activityId, roleId, playerData.roundIndex, playerData.todayIndex); - playerData.shop.setPlayerShopRecords(playerShopRecord); - - let item = playerData.shop.findProductID(productID) - - if (!item) return false; - if (item.buyCount >= item.countMax) return false; - return true; -} - -export async function treasureHuntChallengeConsume(serverId: number, roleId: string, sid: string) { - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TREASURE_HUNT); - for(let { activityId } of activities) { - let playerData = await getPlayerTreasureHuntChallengeData(activityId, serverId, roleId,); - if (!playerData) return false; - - if(playerData.canShow()) { - let challengeData = playerData.challenge; - //消耗资源 - let consumeStr = challengeData.consume; - let consume = stringToConsumeParam(consumeStr) - let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_CHALLENGE); - if (!resourceResult) return false; - - let warId = playerData.challenge.randomGK(); - await ActivityTreasureHuntChallengeModel.setWarId(serverId, activityId, roleId, playerData.roundIndex, warId); - } - } - return true -} \ No newline at end of file +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS, TREASURE_HUNT_DATA_TYPE } from '@consts'; +import { ActivityTreasureHuntShopModel } from '@db/ActivityTreasureHuntShop'; +import { ActivityTreasureHuntTaskModel } from '@db/ActivityTreasureHuntTask'; +import { ActivityTreasureHuntTreasureShopModel } from '@db/ActivityTreasureHuntTreasureShop'; +import { ActivityTreasureHuntFirstPageModel } from '@db/ActivityTreasureHuntFirstPage'; +import { TreasureHuntData } from '@domain/activityField/treasureHuntField'; +import { addReward, stringToConsumeParam, stringToRewardParam } from './giftPackageService'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { getActivitiesByType, getActivityById, getActivityByServerId } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { handleCost } from '../role/rewardService'; +import { ActivityTreasureHuntChallengeModel } from '@db/ActivityTreasureHuntChallenge'; +import { ActivityModelType } from '@db/Activity'; + +export async function getPlayerTreasureHuntDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getPlayerTreasureHuntData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerTreasureHuntData(activityId: number, serverId: number, roleId: string, dataType: TREASURE_HUNT_DATA_TYPE = TREASURE_HUNT_DATA_TYPE.ALL) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TreasureHuntData(activityData, createTime, serverTime); + if(dataType == TREASURE_HUNT_DATA_TYPE.FIRST_PAGE || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { + let playerTreasureFirstPageRecord = await ActivityTreasureHuntFirstPageModel.findData(serverId, activityId, roleId, playerData.roundIndex); + playerData.firstPage.setPlayerFirstPageRecord(playerTreasureFirstPageRecord); + } + if (dataType == TREASURE_HUNT_DATA_TYPE.SHOP || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { + let playerShopRecord = await ActivityTreasureHuntShopModel.findTreasureData(activityId, roleId, playerData.roundIndex, playerData.todayIndex); + playerData.shop.setPlayerShopRecords(playerShopRecord); + } + if (dataType == TREASURE_HUNT_DATA_TYPE.TASK || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { + let playerTaskRecord = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityId, roleId, playerData.roundIndex); + playerData.tasks.setPlayerTaskRecords(playerTaskRecord); + } + if(dataType == TREASURE_HUNT_DATA_TYPE.TREASURE_SHOP || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { + let playerTreasureShopRecord = await ActivityTreasureHuntTreasureShopModel.findData(activityId, roleId, playerData.roundIndex); + playerData.treasureShop.setPlayerTreasureShopRecords(playerTreasureShopRecord); + } + if(dataType == TREASURE_HUNT_DATA_TYPE.CHALLENGE || dataType == TREASURE_HUNT_DATA_TYPE.ALL) { + let playerRecord = await ActivityTreasureHuntChallengeModel.findData(serverId, activityId, roleId, playerData.roundIndex); + playerData.challenge.setChallengeRecord(playerRecord) + } + + return playerData; +} + +export async function getPlayerTreasureHuntFirstPageData(activityId: number, serverId: number, roleId: string) { + return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.FIRST_PAGE); +} + +export async function getPlayerTreasureHuntShopData(activityId: number, serverId: number, roleId: string) { + return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.SHOP); +} + +export async function getPlayerTreasureHuntTaskData(activityId: number, serverId: number, roleId: string) { + return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.TASK); +} + +export async function getPlayerTreasureHuntChallengeData(activityId: number, serverId: number, roleId: string) { + return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.CHALLENGE); +} + +export async function getPlayerTreasureHuntTreasureShopData(activityId: number, serverId: number, roleId: string) { + return await getPlayerTreasureHuntData(activityId, serverId, roleId, TREASURE_HUNT_DATA_TYPE.TREASURE_SHOP); +} + +/** + * 购买每日物资 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeShop(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + // let activityData: ActivityModelType = await ActivityModel.findActivity(activityId); + let playerData = await getPlayerTreasureHuntShopData(activityId, serverId, roleId,); + if (!playerData) { + return { + code: STATUS.ACTIVITY_MISSING, + } + } + + let item = playerData.shop.findProductID(productID) + + if (!item) { + return { + code: STATUS.ACTIVITY_MISSING, + } + } + if (item.buyCount >= item.countMax) { + return { + code: STATUS.ACTIVITY_MAX_COUNT, + } + } + let cellIndex = item.cellIndex; + + //添加购买记录 + await ActivityTreasureHuntShopModel.buyShopRecord(activityId, roleId, playerData.roundIndex, playerData.todayIndex, cellIndex, 1); + + let rewardParamArr: Array = stringToRewardParam(item.reward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.TREASURE_HUNT_SHOP_BUY) + + item.buyCount += 1; + return { + code: 0, + data: Object.assign(result, { item }) + } +} + +export async function checkTreasureHuntShop(roleId: string, serverId: number, activityData: ActivityModelType, productID: string) { + if(!activityData) return false; + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new TreasureHuntData(activityData, createTime, serverTime); + + let playerShopRecord = await ActivityTreasureHuntShopModel.findTreasureData(activityData.activityId, roleId, playerData.roundIndex, playerData.todayIndex); + playerData.shop.setPlayerShopRecords(playerShopRecord); + + let item = playerData.shop.findProductID(productID) + + if (!item) return false; + if (item.buyCount >= item.countMax) return false; + return true; +} + +export async function treasureHuntChallengeConsume(serverId: number, roleId: string, sid: string) { + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TREASURE_HUNT); + for(let { activityId } of activities) { + let playerData = await getPlayerTreasureHuntChallengeData(activityId, serverId, roleId,); + if (!playerData) return false; + + if(playerData.canShow()) { + let challengeData = playerData.challenge; + //消耗资源 + let consumeStr = challengeData.consume; + let consume = stringToConsumeParam(consumeStr) + let resourceResult = await handleCost(roleId, sid, consume, ITEM_CHANGE_REASON.TREASURE_HUNT_CHALLENGE); + if (!resourceResult) return false; + + let warId = playerData.challenge.randomGK(); + await ActivityTreasureHuntChallengeModel.setWarId(serverId, activityId, roleId, playerData.roundIndex, warId); + } + } + return true +} diff --git a/game-server/app/services/activity/vipRechargeMoneyService.ts b/game-server/app/services/activity/vipRechargeMoneyService.ts index b8ec30d35..eac6851f4 100644 --- a/game-server/app/services/activity/vipRechargeMoneyService.ts +++ b/game-server/app/services/activity/vipRechargeMoneyService.ts @@ -1,71 +1,71 @@ -import { ACTIVITY_TYPE } from '../../consts'; -import { ActivityVipRechargeMoneyModel, ActivityVipRechargeMoneyModelType } from '../../db/ActivityVipRechargeMoney'; -import { VipRechargeMoneyData } from '../../domain/activityField/vipRechargeMoneyField'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function vipRechargeMoneyActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.VIP_RECHARGE_MONEY); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerRecord: ActivityVipRechargeMoneyModelType = await ActivityVipRechargeMoneyModel.findData(serverId, roleId, activityData.activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new VipRechargeMoneyData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerVipRechargeMoneyData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - if (!activityData) { - return null; - } - let playerRecord: ActivityVipRechargeMoneyModelType = await ActivityVipRechargeMoneyModel.findData(serverId, roleId, activityId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new VipRechargeMoneyData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - - -/** - * 统计充值金额 - * - * @param {number} serverId 区Id - * @param {string} roleId 角色Id - * @param {string} RMB 金额 - * - */ -export async function addVipRechargeMoney(roleId: string, serverId: number, RMB: number) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.VIP_RECHARGE_MONEY); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - await ActivityVipRechargeMoneyModel.addRMB(serverId, roleId, activityData.activityId, RMB); -} - +import { ACTIVITY_TYPE } from '@consts'; +import { ActivityVipRechargeMoneyModel, ActivityVipRechargeMoneyModelType } from '@db/ActivityVipRechargeMoney'; +import { VipRechargeMoneyData } from '@domain/activityField/vipRechargeMoneyField'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function vipRechargeMoneyActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.VIP_RECHARGE_MONEY); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerRecord: ActivityVipRechargeMoneyModelType = await ActivityVipRechargeMoneyModel.findData(serverId, roleId, activityData.activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new VipRechargeMoneyData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerVipRechargeMoneyData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + if (!activityData) { + return null; + } + let playerRecord: ActivityVipRechargeMoneyModelType = await ActivityVipRechargeMoneyModel.findData(serverId, roleId, activityId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new VipRechargeMoneyData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + + +/** + * 统计充值金额 + * + * @param {number} serverId 区Id + * @param {string} roleId 角色Id + * @param {string} RMB 金额 + * + */ +export async function addVipRechargeMoney(roleId: string, serverId: number, RMB: number) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.VIP_RECHARGE_MONEY); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + await ActivityVipRechargeMoneyModel.addRMB(serverId, roleId, activityData.activityId, RMB); +} + diff --git a/game-server/app/services/activity/webviewService.ts b/game-server/app/services/activity/webviewService.ts index 38e92329d..87b1e3a31 100644 --- a/game-server/app/services/activity/webviewService.ts +++ b/game-server/app/services/activity/webviewService.ts @@ -1,29 +1,29 @@ -import { WebViewData } from "../../domain/activityField/webviewField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getWebviewData(activityId: number, serverId: number, roleId: string) { - - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - - let playerData = new WebViewData(activityData, createTime, serverTime); - return playerData; -} - -export async function getWebviewDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getWebviewData(activityId, serverId, roleId); - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} \ No newline at end of file +import { WebViewData } from "@domain/activityField/webviewField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getWebviewData(activityId: number, serverId: number, roleId: string) { + + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + + let playerData = new WebViewData(activityData, createTime, serverTime); + return playerData; +} + +export async function getWebviewDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getWebviewData(activityId, serverId, roleId); + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} diff --git a/game-server/app/services/activity/weeklyFundService.ts b/game-server/app/services/activity/weeklyFundService.ts index 621f4c7b0..690360623 100644 --- a/game-server/app/services/activity/weeklyFundService.ts +++ b/game-server/app/services/activity/weeklyFundService.ts @@ -1,93 +1,93 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "../../consts"; -import { ActivityModelType } from "../../db/Activity"; -import { ActivityWeeklyFundModel } from "../../db/ActivityWeeklyFund"; -import { WeeklyFundData } from "../../domain/activityField/weeklyFundField"; -import { getRoleCreateTime, getServerCreateTime } from "../redisService"; -import { getActivityById } from "./activityService"; -import { stringToRewardParam, addReward } from "./giftPackageService"; - -/** - * 周基金玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getWeeklyFundData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new WeeklyFundData(activityData, createTime, serverTime); - let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityId, roleId); - playerData.setPlayerRecord(playerRecord); - return playerData; -} - -/** - * 周基金 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getWeeklyFundDataShow(activityId: number, serverId: number, roleId: string) { - let playerData = await getWeeklyFundData(activityId, serverId, roleId); - // console.log('##### weeklyFund', playerData) - if(playerData && playerData.canShow && playerData.canShow()) { - return playerData.getShowResult(); - } - return null -} - -/** - * 周基金 是否可以购买 - * @param roleId 玩家id - * @param serverId 服 - * @param activityData 活动数据 - * @returns - */ -export async function checkWeeklyFund(roleId: string, serverId: number, activityData: ActivityModelType) { - if(!activityData || activityData.type !== ACTIVITY_TYPE.WEEKLY_FUND) return false; - - let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityData.activityId, roleId); - return !playerRecord; -} - -/** - * 周基金购买 - * @param roleId 玩家id - * @param roleName 玩家名 - * @param sid - * @param serverId 服 - * @param activityId 活动 - * @param productID 商品id - * @returns - */ -export async function makeWeeklyFund(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.WEEKLY_FUND) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new WeeklyFundData(activityData, createTime, serverTime); - let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityData.activityId, roleId); - if(playerRecord) { - return STATUS.ORDER_CANNOT_BUY; - } - - await ActivityWeeklyFundModel.buy(serverId, activityId, roleId, productID); - - let rewardParamArr = stringToRewardParam(playerData.onceReward); - let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_BUY); - - return { - code: 0, - data: Object.assign(result, { activityId: activityId }) - } -} \ No newline at end of file +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "@consts"; +import { ActivityModelType } from "@db/Activity"; +import { ActivityWeeklyFundModel } from "@db/ActivityWeeklyFund"; +import { WeeklyFundData } from "@domain/activityField/weeklyFundField"; +import { getRoleCreateTime, getServerCreateTime } from "../redisService"; +import { getActivityById } from "./activityService"; +import { stringToRewardParam, addReward } from "./giftPackageService"; + +/** + * 周基金玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getWeeklyFundData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new WeeklyFundData(activityData, createTime, serverTime); + let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityId, roleId); + playerData.setPlayerRecord(playerRecord); + return playerData; +} + +/** + * 周基金 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getWeeklyFundDataShow(activityId: number, serverId: number, roleId: string) { + let playerData = await getWeeklyFundData(activityId, serverId, roleId); + // console.log('##### weeklyFund', playerData) + if(playerData && playerData.canShow && playerData.canShow()) { + return playerData.getShowResult(); + } + return null +} + +/** + * 周基金 是否可以购买 + * @param roleId 玩家id + * @param serverId 服 + * @param activityData 活动数据 + * @returns + */ +export async function checkWeeklyFund(roleId: string, serverId: number, activityData: ActivityModelType) { + if(!activityData || activityData.type !== ACTIVITY_TYPE.WEEKLY_FUND) return false; + + let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityData.activityId, roleId); + return !playerRecord; +} + +/** + * 周基金购买 + * @param roleId 玩家id + * @param roleName 玩家名 + * @param sid + * @param serverId 服 + * @param activityId 活动 + * @param productID 商品id + * @returns + */ +export async function makeWeeklyFund(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.WEEKLY_FUND) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new WeeklyFundData(activityData, createTime, serverTime); + let playerRecord = await ActivityWeeklyFundModel.findData(serverId, activityData.activityId, roleId); + if(playerRecord) { + return STATUS.ORDER_CANNOT_BUY; + } + + await ActivityWeeklyFundModel.buy(serverId, activityId, roleId, productID); + + let rewardParamArr = stringToRewardParam(playerData.onceReward); + let result = await addReward(roleId, roleName, sid, serverId, rewardParamArr, ITEM_CHANGE_REASON.ACT_WEEKLY_FUND_BUY); + + return { + code: 0, + data: Object.assign(result, { activityId: activityId }) + } +} diff --git a/game-server/app/services/activity/yuanbaoService.ts b/game-server/app/services/activity/yuanbaoService.ts index 729e45292..cce8f984f 100644 --- a/game-server/app/services/activity/yuanbaoService.ts +++ b/game-server/app/services/activity/yuanbaoService.ts @@ -1,99 +1,99 @@ -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts'; -import { ActivityModelType } from '../../db/Activity'; -import { UserOrderModel, UserOrderModelType } from '../../db/UserOrder'; -import { RewardParam } from '../../domain/activityField/rewardField'; -import { YuanBaoShopData } from '../../domain/activityField/yuanBaoShopField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; -import { getActivitiesByType, getActivityById } from './activityService'; -import { addReward, stringToRewardParam } from './giftPackageService'; - -/** - * 获取活动数据 - * - * @param {number} serverId 区Id - * @param {number} type 活动类型 ACTIVITY_TYPE - * @param {string} roleId 角色Id - * - */ - -export async function yuanbaoActivity(serverId: number, roleId: string) { - let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.YUAN_BAO_SHOP); - if (activityArray.length == 0) { - return null; - } - let activityData = activityArray[0]; - let playerRecord: UserOrderModelType[] = await UserOrderModel.findOrderByActivityID(activityData.activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new YuanBaoShopData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - -/** - * 玩家活动数据 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * - */ -export async function getPlayerYuanbaoShopData(activityId: number, serverId: number, roleId: string) { - let activityData = await getActivityById(activityId); - let playerRecord: UserOrderModelType[] = await UserOrderModel.findOrderByActivityID(activityId, roleId); - - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new YuanBaoShopData(activityData, createTime, serverTime); - playerData.setPlayerRecords(playerRecord); - return playerData; -} - - -/** - * 结算奖励 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ -export async function makeYuanbaoShopReward(roleId: string, roleName: string, sid: string, serverId: number, - activityId: number, productID: string) { - let records = await UserOrderModel.findSuccessOrderByProductID(productID, roleId, activityId); - let activityData: ActivityModelType = await getActivityById(activityId); - if (activityData.type !== ACTIVITY_TYPE.YUAN_BAO_SHOP) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let playerData = new YuanBaoShopData(activityData, createTime, serverTime); - let item = playerData.findItem(productID); - - let rewardParamArr: Array = []; - if (records.length == 0) {//首充 - rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.baseReward)); - rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.firstReward)); - } else { - rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.baseReward)); - rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.extraReward)); - } - let arr: Array = []; - for (let obj of rewardParamArr) { - let index = arr.findIndex(reward => { return reward.type == obj.type && reward.id == obj.id }); - if (index != -1) { - arr[index].count += obj.count; - } else { - arr.push(obj); - } - } - - let result = await addReward(roleId, roleName, sid, serverId, arr, ITEM_CHANGE_REASON.YUANBAO_SHOP_BUY) - item.buyCount += 1; - return { - code: 0, - data: Object.assign(result, { item, activityId: activityData.activityId }) - } -} +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from '@consts'; +import { ActivityModelType } from '@db/Activity'; +import { UserOrderModel, UserOrderModelType } from '@db/UserOrder'; +import { RewardParam } from '@domain/activityField/rewardField'; +import { YuanBaoShopData } from '@domain/activityField/yuanBaoShopField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; +import { getActivitiesByType, getActivityById } from './activityService'; +import { addReward, stringToRewardParam } from './giftPackageService'; + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} type 活动类型 ACTIVITY_TYPE + * @param {string} roleId 角色Id + * + */ + +export async function yuanbaoActivity(serverId: number, roleId: string) { + let activityArray = await getActivitiesByType(serverId, ACTIVITY_TYPE.YUAN_BAO_SHOP); + if (activityArray.length == 0) { + return null; + } + let activityData = activityArray[0]; + let playerRecord: UserOrderModelType[] = await UserOrderModel.findOrderByActivityID(activityData.activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new YuanBaoShopData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerYuanbaoShopData(activityId: number, serverId: number, roleId: string) { + let activityData = await getActivityById(activityId); + let playerRecord: UserOrderModelType[] = await UserOrderModel.findOrderByActivityID(activityId, roleId); + + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new YuanBaoShopData(activityData, createTime, serverTime); + playerData.setPlayerRecords(playerRecord); + return playerData; +} + + +/** + * 结算奖励 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ +export async function makeYuanbaoShopReward(roleId: string, roleName: string, sid: string, serverId: number, + activityId: number, productID: string) { + let records = await UserOrderModel.findSuccessOrderByProductID(productID, roleId, activityId); + let activityData: ActivityModelType = await getActivityById(activityId); + if (activityData.type !== ACTIVITY_TYPE.YUAN_BAO_SHOP) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let playerData = new YuanBaoShopData(activityData, createTime, serverTime); + let item = playerData.findItem(productID); + + let rewardParamArr: Array = []; + if (records.length == 0) {//首充 + rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.baseReward)); + rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.firstReward)); + } else { + rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.baseReward)); + rewardParamArr = rewardParamArr.concat(stringToRewardParam(item.extraReward)); + } + let arr: Array = []; + for (let obj of rewardParamArr) { + let index = arr.findIndex(reward => { return reward.type == obj.type && reward.id == obj.id }); + if (index != -1) { + arr[index].count += obj.count; + } else { + arr.push(obj); + } + } + + let result = await addReward(roleId, roleName, sid, serverId, arr, ITEM_CHANGE_REASON.YUANBAO_SHOP_BUY) + item.buyCount += 1; + return { + code: 0, + data: Object.assign(result, { item, activityId: activityData.activityId }) + } +} diff --git a/game-server/app/services/auctionService.ts b/game-server/app/services/auctionService.ts index fb8eef8e4..41a8f092e 100644 --- a/game-server/app/services/auctionService.ts +++ b/game-server/app/services/auctionService.ts @@ -1,642 +1,642 @@ -import { DividendModel } from './../db/Dividend'; -import { LOT_CODE_LEN, AUCTION_STAGE, AUCTION_TIME, DIVIDEND_CODE_LEN, DIVIDEND_STATUS, LOT_STATUS, MAIL_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_RECEIVE_STATUS, AUCTION_BID_STATUS, DEBUG_MAGIC_WORD, AUCTION_SOURCE, TA_EVENT, getAuctionSourceTypeName, PUSH_ROUTE, GUILD_JOB, AUCTION_BID_TIME, AUCTION_BID_EXTEND_TIME } from './../consts'; -import { DividendRec, } from "../domain/dbGeneral"; -import { genCode, getRandEelmWithWeight, getRandSingleEelm } from '../pubUtils/util'; -import Lot, { LotModel, LotParam, LotType } from '../db/Lot'; -import { getCurDay, getSeconds, getTimeFunD, getTimeFunM, nowSeconds } from '../pubUtils/timeUtil'; -import { gameData, getGoodById } from '../pubUtils/data'; -import { DividendParam, DividendType } from '../db/Dividend'; -import { sendMailByContent } from './mailService'; -import { FrontendOrBackendSession, pinus } from 'pinus'; -import { participants } from './guildActivity/guildActivityService'; -import * as dicParam from '../pubUtils/dicParam'; -import { RewardInter } from '../pubUtils/interface'; -import { reportTAEvent } from './sdkService'; -import { getAllServers } from './redisService'; -import { sendMessageToGuildWithSuc, sendMessageToServer, sendMessageToServerWithSuc } from './pushService'; -import { isDebugTime } from '../pubUtils/sdkUtil'; -import { pick } from 'underscore'; -import { AuctionRewardInter } from '../domain/battleField/auction'; -import { CounterLotsModel } from '../db/CounterAuction'; -import { isGoodsHidden } from './dataService'; -import { scheduleJob } from 'node-schedule'; -import { clearLotTimer, setLotTimer } from './memoryCache/auctionData'; - -// ! 获取底价,假数据 -export function getBasePrice(gid: number, count: number) { - const good = getGoodById(gid); - return (good ? good.quality * 100 : 100) * count; -} - -// ! 获取一口价,假数据 -export function getMaxPrice(gid: number, count: number) { - const good = getGoodById(gid); - return (good ? good.quality * 200 : 200) * count; -} - -export async function auctionStage() { - const curTime = await getCurrentTimeWithSetDay(); - if (curTime < (await todayGuildBegin()).getTime()) return AUCTION_STAGE.DEFAULT; - if (curTime < (await todayWorldBegin()).getTime() && curTime > (await todayGuildBegin()).getTime()) return AUCTION_STAGE.GUILD; - if (curTime > (await todayWorldBegin()).getTime() && curTime < (await todayWorldEnd()).getTime()) return AUCTION_STAGE.WORLD; - if (curTime > (await todayWorldEnd()).getTime()) return AUCTION_STAGE.END; -} - -export async function debugAuctionLots(session: FrontendOrBackendSession, begin: Date) { - const serverId = session.get('serverId'); - const lots = await LotModel.findWorldLotsByBegin(serverId, begin); - return lots; -} - -export async function officialAuctionLots(session: FrontendOrBackendSession, begin: Date) { - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - let guildLots = await LotModel.findGuildLotsByBegin(guildCode, begin); - let serverLots = await LotModel.findWorldLotsByBegin(serverId, begin); - return processLotsFormat([...guildLots, ...serverLots]); -} - -// 拍卖行开始时间 今天20:20 -export async function auctionBegin() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 军团拍卖行结束时间 20:30 -export async function guildAuctionEnd() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_CLOSE); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 拍卖行结束时间 22:00 -export async function auctionEnd() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 今天军团拍卖行开始时间 20:20 -export async function todayGuildBegin() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -async function getCurrentTime() { - let now = Date.now(); - if(isDebugTime()) { - let guilds = pinus.app.getServersByType('guild'); - let guild = getRandSingleEelm(guilds); - now = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); - } - return now -} - -async function getCurrentTimeWithSetDay() { - let now = new Date(); - if(isDebugTime()) { - let guilds = pinus.app.getServersByType('guild'); - let guild = getRandSingleEelm(guilds); - let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); - now.setDate(new Date(currentTime).getDate()); - } - return now.getTime(); -} - -// 明天军团拍卖行开始时间 20:20 -export async function tomorrowGuildBegin() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); - // console.log(hour, minute) - return getTimeFunD(now).getAfterDayAndSetHour(1, hour, minute); -} - -// 明天军团拍卖行开始时间 20:20 -export async function tomorrowGuildEnd() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_CLOSE); - // console.log(hour, minute) - return getTimeFunD(now).getAfterDayAndSetHour(1, hour, minute); -} - -// 昨天军团拍卖行开始时间 20:20 -export async function yestodayGuildBegin() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); - return getTimeFunD(now).getAfterDayAndSetHour(-1, hour, minute); -} - -// 今天世界拍卖行开始时间 20:40 -export async function todayWorldBegin() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 今天世界拍卖行结束时间 22:00 -export async function todayWorldEnd() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 拍卖行预览时间 20:00 -export async function guildAuctionPreview() { - let now = await getCurrentTime(); - let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_PREVIEW); - return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); -} - -// 演武台。8点以前是今天的,8点以后是明天的 -export async function getBossAuctionBegin() { - if((await getCurrentTimeWithSetDay()) < (await guildAuctionPreview()).getTime()) { - return await todayGuildBegin(); - } else { - return await tomorrowGuildBegin(); - } -} - -// 演武台。8点以前是今天的,8点以后是明天的 -export async function getBossAuctionEnd() { - if((await getCurrentTimeWithSetDay()) < (await guildAuctionPreview()).getTime()) { - return await guildAuctionEnd(); - } else { - return await tomorrowGuildEnd(); - } -} - -/** - * @description 生成拍卖数据 - * @export - * @param {string} guildCode - * @param {number} sourceType - * @param {string} sourceCode - * @param {number} serverId - * @param {ItemReward[]} rewards - */ -export async function genAuction(guildCode: string, sourceType: number, sourceCode: string, serverId: number, rewards: Map) { - let begin = await auctionBegin(); - let end = await auctionEnd(); - if(sourceType == AUCTION_SOURCE.BOSS) { // 军团boss本 - begin = await getBossAuctionBegin(); - end = await getBossAuctionEnd(); - } - const guildEnd = await guildAuctionEnd(); - const lotsData: LotParam[] = []; - for(let [id, items] of rewards) { - let seq = await CounterLotsModel.getNewCounter(id * 100000 + serverId, begin, items.length); - for(let i = 0; i < items.length; i++) { - let { goods: {id, count}, maxPrice, basePrice, sort } = items[i]; - let code = genCode(LOT_CODE_LEN); - lotsData.push({ - seq: seq - i, - auctionStage: AUCTION_STAGE.DEFAULT, sourceType, - sourceCode, serverId, guildCode, code, gid: id, count, begin, end, status: LOT_STATUS.DEFAULT, - maxPrice, curPrice: basePrice, prePrice: 0, sort, bidRoles: [], watchingRoles: [] - }) - } - } - const lots = await LotModel.createRecs(lotsData); - const dividendCode = genCode(DIVIDEND_CODE_LEN); - const participantsData = await participants(guildCode, sourceType, sourceCode); - const dividends: DividendRec[] = participantsData.map(data => { - const { roleId, baseNum } = data; - return { - roleId, - posNum: 0, // 职位分红 - baseNum, - hasJoin: true, - weekendNum: 0, // 额外分红,周末 - total: baseNum, // 总分红 - status: 0, // 0:未领取,1:已领取 - }; - }); - const dividendData: DividendParam = { - guildCode, sourceType, sourceCode, serverId, code: dividendCode, dividends, totalPrice: 0, begin, lots: lots.map(lot => { - const { code, gid } = lot; - return { code, gid, price: 0, time: guildEnd, max: false, count: lot.count } - }), - }; - const dividend = await DividendModel.createDividend(dividendData); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.AUCTION_ADD, { lots: processLotsFormat(lots) }); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_ADD, { dividends: processDividendFormat([dividend]) }); - return { lots, dividend }; -} - -export function getRewardToDbFromMap(map: Map) { - let rewards: { id: number, count: number }[] = []; - for(let [_, arr] of map) { - for(let { goods } of arr) { - rewards.push(goods) - } - } - return rewards -} - -function posDividend(totalPrice: number, roleRatio: number, totalRatio: number) { - const dividend = Math.floor(totalPrice * roleRatio / totalRatio); - const maxDividend = Math.floor(totalPrice * dicParam.GUILD_AUCTION.DIVIDEND_MAXRATIO); - return dividend <= maxDividend ? dividend : Math.floor(maxDividend * roleRatio / getMaxPosRatio()); -} - -function getMaxPosRatio() { - return gameData.guildPosition.get(GUILD_JOB.DAJIANGJUN).sellRatio; -} - -function weekendDividend(posNum: number, date: Date) { - const day = date.getDay(); - return (day === 0 || day === 6) ? Math.floor(posNum * dicParam.GUILD_AUCTION.DIVIDEND_WEEKEND_RATE) : 0; -} - -function dividendRate(data: { roleId: string, job: number }) { - return gameData.guildPosition.get(data.job).sellRatio; -} - -function totalDividendRatio(participantsData: { roleId: string, job: number }[]) { - const result = participantsData.reduce((sum, data) => { - return sum + dividendRate(data); - }, 0); - return result; -} - -export async function calculateDividend(dividend: DividendType) { - if (!dividend) return null; - const { code, guildCode, sourceType, sourceCode, lots, totalPrice, status, begin } = dividend; - if (status === DIVIDEND_STATUS.SENT) return dividend; - const calcuTotalPrice = lots.reduce((acc, lot) => { return acc + lot.price }, 0) * dicParam.GUILD_AUCTION.DIVIDEND_RATE; - if (calcuTotalPrice !== totalPrice) { - await DividendModel.updateDividend(code, { totalPrice: calcuTotalPrice }); - // 更新 totalPrice - } - const participantsData = await participants(guildCode, sourceType, sourceCode); - const totalRatio = totalDividendRatio(participantsData); - const dividends: DividendRec[] = participantsData.map(data => { - const { roleId, baseNum } = data; - const posNum = posDividend(calcuTotalPrice, dividendRate(data), totalRatio); - const weekendNum = weekendDividend(posNum, begin); - return { - roleId, - posNum, // 职位分红 - baseNum, - hasJoin: true, - weekendNum, // 额外分红,周末 - total: posNum + baseNum + weekendNum, // 总分红 - status: 0, // 0:未领取,1:已领取 - }; - }); - return await DividendModel.updateDividend(code, { dividends }); -} - -export async function startGuildAuction() { - - try { - console.log('schedule startGuildAuction called:', new Date()); - const begin = await todayGuildBegin(); - let lots = await LotModel.updateLotsStageByBegin(begin, AUCTION_STAGE.GUILD); - let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.ING); - - if(isDebugTime()) { - let day = getCurDay(); - let time = getTimeFunM().getTimeWithWeek(day, 20, 20, 0); - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); - await pushCurrentTime(time); - } - - await pushAuctionUpdate(lots, dividends); - return true; - } catch (e) { - console.error('startGuildAuction err: ', e); - return false; - } -} - -export async function sendLotsRewardToMlail(lots: LotType[]) { - let lotByRole = new Map(); - for(let lot of lots) { - if(!lotByRole.has(lot.curBuyer)) { - lotByRole.set(lot.curBuyer, []); - } - lotByRole.get(lot.curBuyer).push({ id: lot.gid, count: lot.count, price: lot.curPrice }); - } - for(let [roleId, goods ] of lotByRole) { - await sendMailByContent(MAIL_TYPE.AUTION_REWARD, roleId, { goods }); - for(let { id, count, price } of goods) { - let dicGoods = gameData.goods.get(id); - reportTAEvent(roleId, TA_EVENT.AUCTION_ITEM_GET, { item_name: dicGoods?.name, item_count: count, deel_price: price }); - } - } -} - -export async function startWorldAuction() { - try { - console.log('schedule startWorldAuction called:', new Date()); - const begin = await todayGuildBegin(); - let lots = await LotModel.setLotSoldByBegin(begin, AUCTION_STAGE.GUILD); // 正在竞拍的拍品 - await sendLotsRewardToMlail(lots); - lots = await LotModel.keepUnSoldLotsToWorld(begin); - - if(isDebugTime()) { - let day = getCurDay(); - let time = getTimeFunM().getTimeWithWeek(day, 20, 30, 0); - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); - await pushCurrentTime(time); - } - await pushAuctionUpdate(lots, []); - return true; - } catch (e) { - console.error('startWorldAuction err: ', e); - return false; - } -} - -export async function startDividend() { - console.log('schedule startDividend called:', new Date()); - const begin = await todayGuildBegin(); - console.log('begin', begin) - let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.END); - await pushAuctionUpdate([], dividends); -} - -export async function stopAuction() { - try { - console.log('schedule stopAuction called:', new Date()); - const begin = await todayGuildBegin(); - let lots = await LotModel.setLotSoldByBegin(begin, AUCTION_STAGE.WORLD); // 正在竞拍的拍品 - await sendLotsRewardToMlail(lots); - lots = await LotModel.updateLotsStageByBegin(begin, AUCTION_STAGE.END); - - if(isDebugTime()) { - let day = getCurDay(); - let time = getTimeFunM().getTimeWithWeek(day, 22, 0, 0); - pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); - await pushCurrentTime(time); - } - await pushAuctionUpdate(lots, []); - return true; - } catch (e) { - console.error('stopAuction err: ', e); - return false; - } -} - -// debug函数,修改客户端当前时间 -export async function pushCurrentTime(time: number) { - let serverlists = await getAllServers() - for(let serverId of serverlists) { - await sendMessageToServer(serverId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time }); - } -} - -async function debugDividends() { - const begin = await yestodayGuildBegin(); - const dividends = await DividendModel.findDividendsByBegin(begin); - const todayBegin = await todayGuildBegin(); - const todayDividends = await DividendModel.findDividendsByBegin(todayBegin); - return [...dividends, ...todayDividends]; -} - -async function officialDividends() { - const begin = await yestodayGuildBegin(); - const dividends = await DividendModel.findDividendsByBegin(begin); - return dividends; -} - -async function updateDebugDividendsStatus(status: number) { - const begin = await yestodayGuildBegin(); - await DividendModel.updateDividendsStatus(begin, status); - const todayBegin = await todayGuildBegin(); - await DividendModel.updateDividendsStatus(todayBegin,status); -} - -async function updateOfficialDividendsStatus(status: number) { - const begin = await yestodayGuildBegin(); - await DividendModel.updateDividendsStatus(begin, status); -} - -export async function sendUngotDividendJob() { - try { - return await sendUngotDividend(); - } catch (e) { - console.error('sendUngotDividend err: ', e); - return false; - } -} - -export function auctionBidStatus(roleId: string, lot: LotParam) { - const { curBuyer, status } = lot; - return curBuyer !== roleId ? AUCTION_BID_STATUS.RETURN : status === LOT_STATUS.SOLD || status === LOT_STATUS.MAX ? AUCTION_BID_STATUS.SUC : AUCTION_BID_STATUS.LEAD; -} - -export function guildBidStatus(lot: { max: boolean, gid: number, count: number, price: number, dividendStatus: number }) { - const { max, gid, count, price: lotPrice, dividendStatus } = lot; - return max || ((dividendStatus == DIVIDEND_STATUS.END || dividendStatus == DIVIDEND_STATUS.SENT) && lotPrice !== 0) -} - -export async function sendUngotDividend(debug = false) { - try { - console.log('schedule sendUngotDividend called:', new Date()); - const dividends = debug === true ? await debugDividends() : await officialDividends(); - const rewards = new Map(); - for (let dividend of dividends) { - if (!dividend.dividends || dividend.status === DIVIDEND_STATUS.SENT) continue; - for (let dividendRec of dividend.dividends) { - if (dividendRec.status === ROLE_RECEIVE_STATUS.YES) continue; - const sum = rewards.get(dividendRec.roleId) || 0; - rewards.set(dividendRec.roleId, sum + dividendRec.total); - reportTAEvent(dividendRec.roleId, TA_EVENT.AUCTION_DIVIDEND, { type: getAuctionSourceTypeName(dividend.sourceType), count: dividendRec.total }) - } - } - - for (let [roleId, count] of rewards) { - if(count > 0) { - await sendMailByContent(MAIL_TYPE.GUILD_DIVIDEND, roleId, { - params: [JSON.stringify(count)], - goods: [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count }] - }); - } - } - - debug === true ? await updateDebugDividendsStatus(DIVIDEND_STATUS.SENT) : await updateOfficialDividendsStatus(DIVIDEND_STATUS.SENT); - return true; - } catch (e) { - console.error('sendUngotDividend err: ', e); - return false; - } -} - -/** - * 获取拍卖行数据 - * @param guildCode - * @param session - * @param magicWord - */ -export async function getAuction(guildCode: string, session: FrontendOrBackendSession, magicWord?: string) { - const begin = await todayGuildBegin(); - const tomorrowBegin = await tomorrowGuildBegin(); - let lots = magicWord === DEBUG_MAGIC_WORD ? await debugAuctionLots(session, begin) : await officialAuctionLots(session, begin); - - let dividends: DividendType[] = []; - if(guildCode) { - dividends = await DividendModel.findGuildDividendsByBegin(guildCode, [begin, tomorrowBegin]); - } - return { lots, dividends: processDividendFormat(dividends) }; -} - -export async function pushAuctionOver(lot: LotType) { - if(lot.auctionStage == AUCTION_STAGE.GUILD) { - await sendMessageToGuildWithSuc(lot.guildCode, PUSH_ROUTE.AUCTION_OVER, { lot: processSingleLotFormat(lot) }); - } else if (lot.auctionStage == AUCTION_STAGE.WORLD) { - await sendMessageToServerWithSuc(lot.serverId, PUSH_ROUTE.AUCTION_OVER, { lot: processSingleLotFormat(lot) }); - } -} - -export async function pushAuctionUpdate(lots: LotType[], dividends: DividendType[]) { - let serverIds: number[] = []; - for(let lot of lots) { - if(serverIds.indexOf(lot.serverId) == -1) serverIds.push(lot.serverId); - } - - for(let serverId of serverIds) { - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.AUCTION_UPDATE, { }); - } - - let dividendsResult = new Map(); - for(let dividend of dividends) { - if(!dividendsResult.has(dividend.guildCode)) { - dividendsResult.set(dividend.guildCode, []); - } - dividendsResult.get(dividend.guildCode).push(dividend); - } - for(let [guildCode, dividends] of dividendsResult) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_UPDATE, { dividends: processDividendFormat(dividends) }) - } - - -} - -export async function checkAuctionStage(auctionStage: number, magicWord: string) { - if(magicWord == DEBUG_MAGIC_WORD) return true - - const curTime = await getCurrentTimeWithSetDay(); - if(auctionStage != AUCTION_STAGE.GUILD && auctionStage != AUCTION_STAGE.WORLD) return false; - if(auctionStage == AUCTION_STAGE.GUILD) { - if(curTime < (await todayGuildBegin()).getTime()) return false; - if(curTime > (await todayWorldBegin()).getTime()) return false - } - if(auctionStage == AUCTION_STAGE.WORLD) { - if(curTime < (await todayWorldBegin()).getTime()) return false; - if(curTime > (await todayWorldEnd()).getTime()) return false - } - return true -} - -export async function isAuctionBidding() { - const curTime = await getCurrentTimeWithSetDay(); - const guildAuctionBeginTime = (await todayWorldBegin()).getTime(); - return guildAuctionBeginTime - curTime <= AUCTION_BID_TIME * 1000; -} - -/** - * - * @param max 玩家是否直接选择一口价 - * @param maxFlag 竞拍是否达到一口价的价格了 - * @param isBidding 是否在竞价时间重 - */ -export async function getLotStatus(auctionStage: number, max: boolean, maxFlag: boolean) { - if(max) return LOT_STATUS.MAX; - if(maxFlag) return LOT_STATUS.SOLD; - - if(auctionStage == AUCTION_STAGE.GUILD && await isAuctionBidding()) return LOT_STATUS.BIDDING; - return LOT_STATUS.ING -} - -export async function extendLotTime(lot: LotType) { - clearLotTimer(lot.code); - if(lot.status == LOT_STATUS.BIDDING) { - let timer = setTimeout(async () => { - await sendSingleLot(lot.code); - }, lot.end.getTime() - Date.now()); - setLotTimer(lot.code, timer); - } -} - -export async function sendSingleLot(code: string) { - console.log('schedule sendSingleLot called:', new Date()); - let lot = await LotModel.setLotSold(code, AUCTION_STAGE.GUILD); // 正在竞拍的拍品 - if(!lot) return; - await sendLotsRewardToMlail([lot]); - await pushAuctionOver(lot); - return true; -} - -export function processSingleDividendFormat(dividend: DividendType) { - if(!dividend) return null; - let newDividend = { ...dividend, begin: getSeconds(dividend.begin)} - return pick(newDividend, ['serverId', 'guildCode', 'sourceType', 'sourceCode', 'code', 'totalPrice', 'dividends', 'status', 'begin']) -} - -export function processDividendFormat(dividends: DividendType[]) { - return dividends.map(processSingleDividendFormat); -} - -export function processSingleLotFormat(lot: LotType) { - if(!lot) return null; - let newLot = { ...lot, begin: getSeconds(lot.begin), end: getSeconds(lot.end)} - return pick(newLot, ['auctionStage', 'sourceType', 'sourceCode', 'serverId', 'guildCode', 'code', 'gid', 'count', 'prePrice', 'curPrice', 'curBuyer', 'maxPrice', 'bidRoles', 'watchingRoles', 'begin', 'end', 'status', 'sort']) -} - -export function processLotsFormat(lots: LotType[]) { - return lots.map(processSingleLotFormat); -} - -/** - * 根据军团活动排名获得奖励 - * @param aid 活动id - * @param rank 排名 - */ - function getGuildAuction(aid: number, rank: number, struLv: number, cityId: number = 0) { - let ranksReward = gameData.guildAuction.get(`${aid}_${struLv}_${cityId}`) || []; - return ranksReward.find(cur => { - return rank >= cur.min && (rank <= cur.max || cur.max == 0); - }); -} - -export function getGuildAuctionBasicNum(aid: number, rank: number, struLv: number, cityId: number = 0) { - let dic = getGuildAuction(aid, rank, struLv, cityId); - return dic?.basicDividend||0; -} - -export function getGuildAuctionRewards(aid: number, rank: number, struLv: number, cityId: number = 0) { - let dic = getGuildAuction(aid, rank, struLv, cityId); - if(dic) { - return getAuctionRewardByPoolId(dic.rewards); - } else { - return new Map(); - } -} - -export function getAuctionRewardByPoolId(poolId: number) { - let pools = gameData.auctionPool.get(poolId); - let rewards: Map = new Map(); - for(let { count, basicPool } of pools) { - let { rewardBasicPool, basePrice, maxPrice, sort } = basicPool - for(let i = 0; i < count; i++) { - let result = getRandEelmWithWeight(rewardBasicPool); - if(result && result.dic) { - let { id, count } = result.dic; - if(isGoodsHidden(id)) continue; - if(!rewards.has(id)) { - rewards.set(id, []); - } - rewards.get(id).push({ goods: {id, count}, basePrice, maxPrice, sort }); - } - } - } - return rewards; -} - -export function biddingLotTimeout() { - scheduleJob('', () => {}) -} \ No newline at end of file +import { DividendModel } from '@db/Dividend'; +import { LOT_CODE_LEN, AUCTION_STAGE, AUCTION_TIME, DIVIDEND_CODE_LEN, DIVIDEND_STATUS, LOT_STATUS, MAIL_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_RECEIVE_STATUS, AUCTION_BID_STATUS, DEBUG_MAGIC_WORD, AUCTION_SOURCE, TA_EVENT, getAuctionSourceTypeName, PUSH_ROUTE, GUILD_JOB, AUCTION_BID_TIME, AUCTION_BID_EXTEND_TIME } from '@consts'; +import { DividendRec, } from "@domain/dbGeneral"; +import { genCode, getRandEelmWithWeight, getRandSingleEelm } from '@pubUtils/util'; +import Lot, { LotModel, LotParam, LotType } from '@db/Lot'; +import { getCurDay, getSeconds, getTimeFunD, getTimeFunM, nowSeconds } from '@pubUtils/timeUtil'; +import { gameData, getGoodById } from '@pubUtils/data'; +import { DividendParam, DividendType } from '@db/Dividend'; +import { sendMailByContent } from './mailService'; +import { FrontendOrBackendSession, pinus } from 'pinus'; +import { participants } from './guildActivity/guildActivityService'; +import * as dicParam from '@pubUtils/dicParam'; +import { RewardInter } from '@pubUtils/interface'; +import { reportTAEvent } from './sdkService'; +import { getAllServers } from './redisService'; +import { sendMessageToGuildWithSuc, sendMessageToServer, sendMessageToServerWithSuc } from './pushService'; +import { isDebugTime } from '@pubUtils/sdkUtil'; +import { pick } from 'underscore'; +import { AuctionRewardInter } from '@domain/battleField/auction'; +import { CounterLotsModel } from '@db/CounterAuction'; +import { isGoodsHidden } from './dataService'; +import { scheduleJob } from 'node-schedule'; +import { clearLotTimer, setLotTimer } from './memoryCache/auctionData'; + +// ! 获取底价,假数据 +export function getBasePrice(gid: number, count: number) { + const good = getGoodById(gid); + return (good ? good.quality * 100 : 100) * count; +} + +// ! 获取一口价,假数据 +export function getMaxPrice(gid: number, count: number) { + const good = getGoodById(gid); + return (good ? good.quality * 200 : 200) * count; +} + +export async function auctionStage() { + const curTime = await getCurrentTimeWithSetDay(); + if (curTime < (await todayGuildBegin()).getTime()) return AUCTION_STAGE.DEFAULT; + if (curTime < (await todayWorldBegin()).getTime() && curTime > (await todayGuildBegin()).getTime()) return AUCTION_STAGE.GUILD; + if (curTime > (await todayWorldBegin()).getTime() && curTime < (await todayWorldEnd()).getTime()) return AUCTION_STAGE.WORLD; + if (curTime > (await todayWorldEnd()).getTime()) return AUCTION_STAGE.END; +} + +export async function debugAuctionLots(session: FrontendOrBackendSession, begin: Date) { + const serverId = session.get('serverId'); + const lots = await LotModel.findWorldLotsByBegin(serverId, begin); + return lots; +} + +export async function officialAuctionLots(session: FrontendOrBackendSession, begin: Date) { + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + let guildLots = await LotModel.findGuildLotsByBegin(guildCode, begin); + let serverLots = await LotModel.findWorldLotsByBegin(serverId, begin); + return processLotsFormat([...guildLots, ...serverLots]); +} + +// 拍卖行开始时间 今天20:20 +export async function auctionBegin() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 军团拍卖行结束时间 20:30 +export async function guildAuctionEnd() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_CLOSE); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 拍卖行结束时间 22:00 +export async function auctionEnd() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 今天军团拍卖行开始时间 20:20 +export async function todayGuildBegin() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +async function getCurrentTime() { + let now = Date.now(); + if(isDebugTime()) { + let guilds = pinus.app.getServersByType('guild'); + let guild = getRandSingleEelm(guilds); + now = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); + } + return now +} + +async function getCurrentTimeWithSetDay() { + let now = new Date(); + if(isDebugTime()) { + let guilds = pinus.app.getServersByType('guild'); + let guild = getRandSingleEelm(guilds); + let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); + now.setDate(new Date(currentTime).getDate()); + } + return now.getTime(); +} + +// 明天军团拍卖行开始时间 20:20 +export async function tomorrowGuildBegin() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); + // console.log(hour, minute) + return getTimeFunD(now).getAfterDayAndSetHour(1, hour, minute); +} + +// 明天军团拍卖行开始时间 20:20 +export async function tomorrowGuildEnd() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_CLOSE); + // console.log(hour, minute) + return getTimeFunD(now).getAfterDayAndSetHour(1, hour, minute); +} + +// 昨天军团拍卖行开始时间 20:20 +export async function yestodayGuildBegin() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); + return getTimeFunD(now).getAfterDayAndSetHour(-1, hour, minute); +} + +// 今天世界拍卖行开始时间 20:40 +export async function todayWorldBegin() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 今天世界拍卖行结束时间 22:00 +export async function todayWorldEnd() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 拍卖行预览时间 20:00 +export async function guildAuctionPreview() { + let now = await getCurrentTime(); + let { hour, minute } = gameData.auctionTime.get(AUCTION_TIME.GUILD_PREVIEW); + return getTimeFunD(now).getAfterDayAndSetHour(0, hour, minute); +} + +// 演武台。8点以前是今天的,8点以后是明天的 +export async function getBossAuctionBegin() { + if((await getCurrentTimeWithSetDay()) < (await guildAuctionPreview()).getTime()) { + return await todayGuildBegin(); + } else { + return await tomorrowGuildBegin(); + } +} + +// 演武台。8点以前是今天的,8点以后是明天的 +export async function getBossAuctionEnd() { + if((await getCurrentTimeWithSetDay()) < (await guildAuctionPreview()).getTime()) { + return await guildAuctionEnd(); + } else { + return await tomorrowGuildEnd(); + } +} + +/** + * @description 生成拍卖数据 + * @export + * @param {string} guildCode + * @param {number} sourceType + * @param {string} sourceCode + * @param {number} serverId + * @param {ItemReward[]} rewards + */ +export async function genAuction(guildCode: string, sourceType: number, sourceCode: string, serverId: number, rewards: Map) { + let begin = await auctionBegin(); + let end = await auctionEnd(); + if(sourceType == AUCTION_SOURCE.BOSS) { // 军团boss本 + begin = await getBossAuctionBegin(); + end = await getBossAuctionEnd(); + } + const guildEnd = await guildAuctionEnd(); + const lotsData: LotParam[] = []; + for(let [id, items] of rewards) { + let seq = await CounterLotsModel.getNewCounter(id * 100000 + serverId, begin, items.length); + for(let i = 0; i < items.length; i++) { + let { goods: {id, count}, maxPrice, basePrice, sort } = items[i]; + let code = genCode(LOT_CODE_LEN); + lotsData.push({ + seq: seq - i, + auctionStage: AUCTION_STAGE.DEFAULT, sourceType, + sourceCode, serverId, guildCode, code, gid: id, count, begin, end, status: LOT_STATUS.DEFAULT, + maxPrice, curPrice: basePrice, prePrice: 0, sort, bidRoles: [], watchingRoles: [] + }) + } + } + const lots = await LotModel.createRecs(lotsData); + const dividendCode = genCode(DIVIDEND_CODE_LEN); + const participantsData = await participants(guildCode, sourceType, sourceCode); + const dividends: DividendRec[] = participantsData.map(data => { + const { roleId, baseNum } = data; + return { + roleId, + posNum: 0, // 职位分红 + baseNum, + hasJoin: true, + weekendNum: 0, // 额外分红,周末 + total: baseNum, // 总分红 + status: 0, // 0:未领取,1:已领取 + }; + }); + const dividendData: DividendParam = { + guildCode, sourceType, sourceCode, serverId, code: dividendCode, dividends, totalPrice: 0, begin, lots: lots.map(lot => { + const { code, gid } = lot; + return { code, gid, price: 0, time: guildEnd, max: false, count: lot.count } + }), + }; + const dividend = await DividendModel.createDividend(dividendData); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.AUCTION_ADD, { lots: processLotsFormat(lots) }); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_ADD, { dividends: processDividendFormat([dividend]) }); + return { lots, dividend }; +} + +export function getRewardToDbFromMap(map: Map) { + let rewards: { id: number, count: number }[] = []; + for(let [_, arr] of map) { + for(let { goods } of arr) { + rewards.push(goods) + } + } + return rewards +} + +function posDividend(totalPrice: number, roleRatio: number, totalRatio: number) { + const dividend = Math.floor(totalPrice * roleRatio / totalRatio); + const maxDividend = Math.floor(totalPrice * dicParam.GUILD_AUCTION.DIVIDEND_MAXRATIO); + return dividend <= maxDividend ? dividend : Math.floor(maxDividend * roleRatio / getMaxPosRatio()); +} + +function getMaxPosRatio() { + return gameData.guildPosition.get(GUILD_JOB.DAJIANGJUN).sellRatio; +} + +function weekendDividend(posNum: number, date: Date) { + const day = date.getDay(); + return (day === 0 || day === 6) ? Math.floor(posNum * dicParam.GUILD_AUCTION.DIVIDEND_WEEKEND_RATE) : 0; +} + +function dividendRate(data: { roleId: string, job: number }) { + return gameData.guildPosition.get(data.job).sellRatio; +} + +function totalDividendRatio(participantsData: { roleId: string, job: number }[]) { + const result = participantsData.reduce((sum, data) => { + return sum + dividendRate(data); + }, 0); + return result; +} + +export async function calculateDividend(dividend: DividendType) { + if (!dividend) return null; + const { code, guildCode, sourceType, sourceCode, lots, totalPrice, status, begin } = dividend; + if (status === DIVIDEND_STATUS.SENT) return dividend; + const calcuTotalPrice = lots.reduce((acc, lot) => { return acc + lot.price }, 0) * dicParam.GUILD_AUCTION.DIVIDEND_RATE; + if (calcuTotalPrice !== totalPrice) { + await DividendModel.updateDividend(code, { totalPrice: calcuTotalPrice }); + // 更新 totalPrice + } + const participantsData = await participants(guildCode, sourceType, sourceCode); + const totalRatio = totalDividendRatio(participantsData); + const dividends: DividendRec[] = participantsData.map(data => { + const { roleId, baseNum } = data; + const posNum = posDividend(calcuTotalPrice, dividendRate(data), totalRatio); + const weekendNum = weekendDividend(posNum, begin); + return { + roleId, + posNum, // 职位分红 + baseNum, + hasJoin: true, + weekendNum, // 额外分红,周末 + total: posNum + baseNum + weekendNum, // 总分红 + status: 0, // 0:未领取,1:已领取 + }; + }); + return await DividendModel.updateDividend(code, { dividends }); +} + +export async function startGuildAuction() { + + try { + console.log('schedule startGuildAuction called:', new Date()); + const begin = await todayGuildBegin(); + let lots = await LotModel.updateLotsStageByBegin(begin, AUCTION_STAGE.GUILD); + let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.ING); + + if(isDebugTime()) { + let day = getCurDay(); + let time = getTimeFunM().getTimeWithWeek(day, 20, 20, 0); + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); + await pushCurrentTime(time); + } + + await pushAuctionUpdate(lots, dividends); + return true; + } catch (e) { + console.error('startGuildAuction err: ', e); + return false; + } +} + +export async function sendLotsRewardToMlail(lots: LotType[]) { + let lotByRole = new Map(); + for(let lot of lots) { + if(!lotByRole.has(lot.curBuyer)) { + lotByRole.set(lot.curBuyer, []); + } + lotByRole.get(lot.curBuyer).push({ id: lot.gid, count: lot.count, price: lot.curPrice }); + } + for(let [roleId, goods ] of lotByRole) { + await sendMailByContent(MAIL_TYPE.AUTION_REWARD, roleId, { goods }); + for(let { id, count, price } of goods) { + let dicGoods = gameData.goods.get(id); + reportTAEvent(roleId, TA_EVENT.AUCTION_ITEM_GET, { item_name: dicGoods?.name, item_count: count, deel_price: price }); + } + } +} + +export async function startWorldAuction() { + try { + console.log('schedule startWorldAuction called:', new Date()); + const begin = await todayGuildBegin(); + let lots = await LotModel.setLotSoldByBegin(begin, AUCTION_STAGE.GUILD); // 正在竞拍的拍品 + await sendLotsRewardToMlail(lots); + lots = await LotModel.keepUnSoldLotsToWorld(begin); + + if(isDebugTime()) { + let day = getCurDay(); + let time = getTimeFunM().getTimeWithWeek(day, 20, 30, 0); + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); + await pushCurrentTime(time); + } + await pushAuctionUpdate(lots, []); + return true; + } catch (e) { + console.error('startWorldAuction err: ', e); + return false; + } +} + +export async function startDividend() { + console.log('schedule startDividend called:', new Date()); + const begin = await todayGuildBegin(); + console.log('begin', begin) + let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.END); + await pushAuctionUpdate([], dividends); +} + +export async function stopAuction() { + try { + console.log('schedule stopAuction called:', new Date()); + const begin = await todayGuildBegin(); + let lots = await LotModel.setLotSoldByBegin(begin, AUCTION_STAGE.WORLD); // 正在竞拍的拍品 + await sendLotsRewardToMlail(lots); + lots = await LotModel.updateLotsStageByBegin(begin, AUCTION_STAGE.END); + + if(isDebugTime()) { + let day = getCurDay(); + let time = getTimeFunM().getTimeWithWeek(day, 22, 0, 0); + pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time); + await pushCurrentTime(time); + } + await pushAuctionUpdate(lots, []); + return true; + } catch (e) { + console.error('stopAuction err: ', e); + return false; + } +} + +// debug函数,修改客户端当前时间 +export async function pushCurrentTime(time: number) { + let serverlists = await getAllServers() + for(let serverId of serverlists) { + await sendMessageToServer(serverId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time }); + } +} + +async function debugDividends() { + const begin = await yestodayGuildBegin(); + const dividends = await DividendModel.findDividendsByBegin(begin); + const todayBegin = await todayGuildBegin(); + const todayDividends = await DividendModel.findDividendsByBegin(todayBegin); + return [...dividends, ...todayDividends]; +} + +async function officialDividends() { + const begin = await yestodayGuildBegin(); + const dividends = await DividendModel.findDividendsByBegin(begin); + return dividends; +} + +async function updateDebugDividendsStatus(status: number) { + const begin = await yestodayGuildBegin(); + await DividendModel.updateDividendsStatus(begin, status); + const todayBegin = await todayGuildBegin(); + await DividendModel.updateDividendsStatus(todayBegin,status); +} + +async function updateOfficialDividendsStatus(status: number) { + const begin = await yestodayGuildBegin(); + await DividendModel.updateDividendsStatus(begin, status); +} + +export async function sendUngotDividendJob() { + try { + return await sendUngotDividend(); + } catch (e) { + console.error('sendUngotDividend err: ', e); + return false; + } +} + +export function auctionBidStatus(roleId: string, lot: LotParam) { + const { curBuyer, status } = lot; + return curBuyer !== roleId ? AUCTION_BID_STATUS.RETURN : status === LOT_STATUS.SOLD || status === LOT_STATUS.MAX ? AUCTION_BID_STATUS.SUC : AUCTION_BID_STATUS.LEAD; +} + +export function guildBidStatus(lot: { max: boolean, gid: number, count: number, price: number, dividendStatus: number }) { + const { max, gid, count, price: lotPrice, dividendStatus } = lot; + return max || ((dividendStatus == DIVIDEND_STATUS.END || dividendStatus == DIVIDEND_STATUS.SENT) && lotPrice !== 0) +} + +export async function sendUngotDividend(debug = false) { + try { + console.log('schedule sendUngotDividend called:', new Date()); + const dividends = debug === true ? await debugDividends() : await officialDividends(); + const rewards = new Map(); + for (let dividend of dividends) { + if (!dividend.dividends || dividend.status === DIVIDEND_STATUS.SENT) continue; + for (let dividendRec of dividend.dividends) { + if (dividendRec.status === ROLE_RECEIVE_STATUS.YES) continue; + const sum = rewards.get(dividendRec.roleId) || 0; + rewards.set(dividendRec.roleId, sum + dividendRec.total); + reportTAEvent(dividendRec.roleId, TA_EVENT.AUCTION_DIVIDEND, { type: getAuctionSourceTypeName(dividend.sourceType), count: dividendRec.total }) + } + } + + for (let [roleId, count] of rewards) { + if(count > 0) { + await sendMailByContent(MAIL_TYPE.GUILD_DIVIDEND, roleId, { + params: [JSON.stringify(count)], + goods: [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count }] + }); + } + } + + debug === true ? await updateDebugDividendsStatus(DIVIDEND_STATUS.SENT) : await updateOfficialDividendsStatus(DIVIDEND_STATUS.SENT); + return true; + } catch (e) { + console.error('sendUngotDividend err: ', e); + return false; + } +} + +/** + * 获取拍卖行数据 + * @param guildCode + * @param session + * @param magicWord + */ +export async function getAuction(guildCode: string, session: FrontendOrBackendSession, magicWord?: string) { + const begin = await todayGuildBegin(); + const tomorrowBegin = await tomorrowGuildBegin(); + let lots = magicWord === DEBUG_MAGIC_WORD ? await debugAuctionLots(session, begin) : await officialAuctionLots(session, begin); + + let dividends: DividendType[] = []; + if(guildCode) { + dividends = await DividendModel.findGuildDividendsByBegin(guildCode, [begin, tomorrowBegin]); + } + return { lots, dividends: processDividendFormat(dividends) }; +} + +export async function pushAuctionOver(lot: LotType) { + if(lot.auctionStage == AUCTION_STAGE.GUILD) { + await sendMessageToGuildWithSuc(lot.guildCode, PUSH_ROUTE.AUCTION_OVER, { lot: processSingleLotFormat(lot) }); + } else if (lot.auctionStage == AUCTION_STAGE.WORLD) { + await sendMessageToServerWithSuc(lot.serverId, PUSH_ROUTE.AUCTION_OVER, { lot: processSingleLotFormat(lot) }); + } +} + +export async function pushAuctionUpdate(lots: LotType[], dividends: DividendType[]) { + let serverIds: number[] = []; + for(let lot of lots) { + if(serverIds.indexOf(lot.serverId) == -1) serverIds.push(lot.serverId); + } + + for(let serverId of serverIds) { + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.AUCTION_UPDATE, { }); + } + + let dividendsResult = new Map(); + for(let dividend of dividends) { + if(!dividendsResult.has(dividend.guildCode)) { + dividendsResult.set(dividend.guildCode, []); + } + dividendsResult.get(dividend.guildCode).push(dividend); + } + for(let [guildCode, dividends] of dividendsResult) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DIVIDEND_UPDATE, { dividends: processDividendFormat(dividends) }) + } + + +} + +export async function checkAuctionStage(auctionStage: number, magicWord: string) { + if(magicWord == DEBUG_MAGIC_WORD) return true + + const curTime = await getCurrentTimeWithSetDay(); + if(auctionStage != AUCTION_STAGE.GUILD && auctionStage != AUCTION_STAGE.WORLD) return false; + if(auctionStage == AUCTION_STAGE.GUILD) { + if(curTime < (await todayGuildBegin()).getTime()) return false; + if(curTime > (await todayWorldBegin()).getTime()) return false + } + if(auctionStage == AUCTION_STAGE.WORLD) { + if(curTime < (await todayWorldBegin()).getTime()) return false; + if(curTime > (await todayWorldEnd()).getTime()) return false + } + return true +} + +export async function isAuctionBidding() { + const curTime = await getCurrentTimeWithSetDay(); + const guildAuctionBeginTime = (await todayWorldBegin()).getTime(); + return guildAuctionBeginTime - curTime <= AUCTION_BID_TIME * 1000; +} + +/** + * + * @param max 玩家是否直接选择一口价 + * @param maxFlag 竞拍是否达到一口价的价格了 + * @param isBidding 是否在竞价时间重 + */ +export async function getLotStatus(auctionStage: number, max: boolean, maxFlag: boolean) { + if(max) return LOT_STATUS.MAX; + if(maxFlag) return LOT_STATUS.SOLD; + + if(auctionStage == AUCTION_STAGE.GUILD && await isAuctionBidding()) return LOT_STATUS.BIDDING; + return LOT_STATUS.ING +} + +export async function extendLotTime(lot: LotType) { + clearLotTimer(lot.code); + if(lot.status == LOT_STATUS.BIDDING) { + let timer = setTimeout(async () => { + await sendSingleLot(lot.code); + }, lot.end.getTime() - Date.now()); + setLotTimer(lot.code, timer); + } +} + +export async function sendSingleLot(code: string) { + console.log('schedule sendSingleLot called:', new Date()); + let lot = await LotModel.setLotSold(code, AUCTION_STAGE.GUILD); // 正在竞拍的拍品 + if(!lot) return; + await sendLotsRewardToMlail([lot]); + await pushAuctionOver(lot); + return true; +} + +export function processSingleDividendFormat(dividend: DividendType) { + if(!dividend) return null; + let newDividend = { ...dividend, begin: getSeconds(dividend.begin)} + return pick(newDividend, ['serverId', 'guildCode', 'sourceType', 'sourceCode', 'code', 'totalPrice', 'dividends', 'status', 'begin']) +} + +export function processDividendFormat(dividends: DividendType[]) { + return dividends.map(processSingleDividendFormat); +} + +export function processSingleLotFormat(lot: LotType) { + if(!lot) return null; + let newLot = { ...lot, begin: getSeconds(lot.begin), end: getSeconds(lot.end)} + return pick(newLot, ['auctionStage', 'sourceType', 'sourceCode', 'serverId', 'guildCode', 'code', 'gid', 'count', 'prePrice', 'curPrice', 'curBuyer', 'maxPrice', 'bidRoles', 'watchingRoles', 'begin', 'end', 'status', 'sort']) +} + +export function processLotsFormat(lots: LotType[]) { + return lots.map(processSingleLotFormat); +} + +/** + * 根据军团活动排名获得奖励 + * @param aid 活动id + * @param rank 排名 + */ + function getGuildAuction(aid: number, rank: number, struLv: number, cityId: number = 0) { + let ranksReward = gameData.guildAuction.get(`${aid}_${struLv}_${cityId}`) || []; + return ranksReward.find(cur => { + return rank >= cur.min && (rank <= cur.max || cur.max == 0); + }); +} + +export function getGuildAuctionBasicNum(aid: number, rank: number, struLv: number, cityId: number = 0) { + let dic = getGuildAuction(aid, rank, struLv, cityId); + return dic?.basicDividend||0; +} + +export function getGuildAuctionRewards(aid: number, rank: number, struLv: number, cityId: number = 0) { + let dic = getGuildAuction(aid, rank, struLv, cityId); + if(dic) { + return getAuctionRewardByPoolId(dic.rewards); + } else { + return new Map(); + } +} + +export function getAuctionRewardByPoolId(poolId: number) { + let pools = gameData.auctionPool.get(poolId); + let rewards: Map = new Map(); + for(let { count, basicPool } of pools) { + let { rewardBasicPool, basePrice, maxPrice, sort } = basicPool + for(let i = 0; i < count; i++) { + let result = getRandEelmWithWeight(rewardBasicPool); + if(result && result.dic) { + let { id, count } = result.dic; + if(isGoodsHidden(id)) continue; + if(!rewards.has(id)) { + rewards.set(id, []); + } + rewards.get(id).push({ goods: {id, count}, basePrice, maxPrice, sort }); + } + } + } + return rewards; +} + +export function biddingLotTimeout() { + scheduleJob('', () => {}) +} diff --git a/game-server/app/services/authenticateService.ts b/game-server/app/services/authenticateService.ts index 5ccdc517f..a6e0a3e75 100644 --- a/game-server/app/services/authenticateService.ts +++ b/game-server/app/services/authenticateService.ts @@ -1,61 +1,61 @@ -import moment = require("moment"); -import { pinus } from "pinus"; -import { ADDICTION_PREVENTION_CODE, ADULT_AGE, GUEST_MAX_TIME, PUSH_ROUTE, STATUS } from "../consts"; -import { UserModel, UserType } from "../db/User"; -import { getAge } from "../pubUtils/timeUtil"; -import { resResult } from "../pubUtils/util"; -import { incOnlineTime, setOnlineTime } from "./redisService"; -import { checkTeeanAgerTime } from '../pubUtils/authenticateUtil'; -import { sendMessageToUserWithSuc } from "./pushService"; - -export async function reportOneOnline(roleId: string, userCode: string, sid: string, isLogin: boolean = false, user?: UserType) { - if (!user) user = await UserModel.findUserByUserCode(userCode); - if (!user) return false; - - let sumTime = await incOnlineTime(userCode, false, 5 * 60); // 返回单位为分 - let todaySumTime = await incOnlineTime(userCode, true, 5 * 60); - - let { isGuest, hasAuthenticated, birthday } = user; - let age = getAge(birthday); - let isAdult = age >= ADULT_AGE; - - if (isGuest || !hasAuthenticated) { - if (sumTime > GUEST_MAX_TIME) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest, - guestTime: sumTime, // 游客已体验时间 - hasAuthenticated, // 是否进行过实名认证 - isAdult, // 是否已成年 - todayPlayTime: todaySumTime, // 今天已游戏时长 - type: ADDICTION_PREVENTION_CODE.GUEST, - }, sid); - } - } else { - let code = checkTeeanAgerTime(isAdult, todaySumTime); - if(code != ADDICTION_PREVENTION_CODE.SUCCESS) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { - isGuest, - guestTime: 0, // 游客已体验时间 - hasAuthenticated, // 是否进行过实名认证 - isAdult, // 是否已成年 - todayPlayTime: todaySumTime, // 今天已游戏时长 - type: code - }, sid); - } - } -} - -export async function savePlayTime(userCode: string, user?: UserType) { - if (!user) user = await UserModel.findUserByUserCode(userCode); - if (!user) return false; - - let time = Date.now() - user.lastLoginTime.getTime(); - let setsumTime = (user.playTime||0) + Math.floor(time/1000); - let settodaySumTime = (user.todayPlayTime||0) + Math.floor(time/1000); - - let sumTime = await setOnlineTime(userCode, false, setsumTime); // 返回单位为分 - let todaySumTime = await setOnlineTime(userCode, true, settodaySumTime); - - let { isGuest, hasAuthenticated } = user; - await UserModel.updatePlayTime(userCode, isGuest || !hasAuthenticated, settodaySumTime, setsumTime); -} \ No newline at end of file +import moment = require("moment"); +import { pinus } from "pinus"; +import { ADDICTION_PREVENTION_CODE, ADULT_AGE, GUEST_MAX_TIME, PUSH_ROUTE, STATUS } from "@consts"; +import { UserModel, UserType } from "@db/User"; +import { getAge } from "@pubUtils/timeUtil"; +import { resResult } from "@pubUtils/util"; +import { incOnlineTime, setOnlineTime } from "./redisService"; +import { checkTeeanAgerTime } from '@pubUtils/authenticateUtil'; +import { sendMessageToUserWithSuc } from "./pushService"; + +export async function reportOneOnline(roleId: string, userCode: string, sid: string, isLogin: boolean = false, user?: UserType) { + if (!user) user = await UserModel.findUserByUserCode(userCode); + if (!user) return false; + + let sumTime = await incOnlineTime(userCode, false, 5 * 60); // 返回单位为分 + let todaySumTime = await incOnlineTime(userCode, true, 5 * 60); + + let { isGuest, hasAuthenticated, birthday } = user; + let age = getAge(birthday); + let isAdult = age >= ADULT_AGE; + + if (isGuest || !hasAuthenticated) { + if (sumTime > GUEST_MAX_TIME) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest, + guestTime: sumTime, // 游客已体验时间 + hasAuthenticated, // 是否进行过实名认证 + isAdult, // 是否已成年 + todayPlayTime: todaySumTime, // 今天已游戏时长 + type: ADDICTION_PREVENTION_CODE.GUEST, + }, sid); + } + } else { + let code = checkTeeanAgerTime(isAdult, todaySumTime); + if(code != ADDICTION_PREVENTION_CODE.SUCCESS) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAY_TIME, { + isGuest, + guestTime: 0, // 游客已体验时间 + hasAuthenticated, // 是否进行过实名认证 + isAdult, // 是否已成年 + todayPlayTime: todaySumTime, // 今天已游戏时长 + type: code + }, sid); + } + } +} + +export async function savePlayTime(userCode: string, user?: UserType) { + if (!user) user = await UserModel.findUserByUserCode(userCode); + if (!user) return false; + + let time = Date.now() - user.lastLoginTime.getTime(); + let setsumTime = (user.playTime||0) + Math.floor(time/1000); + let settodaySumTime = (user.todayPlayTime||0) + Math.floor(time/1000); + + let sumTime = await setOnlineTime(userCode, false, setsumTime); // 返回单位为分 + let todaySumTime = await setOnlineTime(userCode, true, settodaySumTime); + + let { isGuest, hasAuthenticated } = user; + await UserModel.updatePlayTime(userCode, isGuest || !hasAuthenticated, settodaySumTime, setsumTime); +} diff --git a/game-server/app/services/battle/comBattleService.ts b/game-server/app/services/battle/comBattleService.ts index ab78e264e..888005b74 100644 --- a/game-server/app/services/battle/comBattleService.ts +++ b/game-server/app/services/battle/comBattleService.ts @@ -1,712 +1,711 @@ -import { MemComBtlTeam } from '../../domain/battleField/ComBattleTeamField'; -import { ItemModel } from '../../db/Item'; -import { BATTLE_REWARD_TYPE, ITEM_CHANGE_REASON, IT_TYPE, PUSH_ROUTE } from '../../consts'; -import { FriendRelationModel } from '../../db/FriendRelation'; -import { RoleModel, RoleType } from '../../db/Role'; -import { STATUS } from '../../consts/statusCode'; -import { COM_TEAM_STATUS, FRIEND_DROP_TYPE, COM_BTL_CONST, FRIEND_DROP_MAX } from '../../consts'; -import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, ComBattleReward } from '../../db/ComBattleTeam'; -import { getRandEelm, getRandValue, resResult, ratioReward, getRandValueByMinMax, getRandEelmWithWeight, getRobotInfo, getRandSingleEelm } from "../../pubUtils/util"; -import { getRandRobot } from "../battleService"; -import { Channel, ChannelService, pinus } from 'pinus'; -import { TREASURE, EXTERIOR, FRIEND } from '../../pubUtils/dicParam'; -import { getFriendLvAdd } from '../friendService'; -import { getRoleIds } from '../../pubUtils/friendUtil'; -import { getComTeamSidByCode, getCreatedTeamByLv, getTeamSearchByLv, redisClient, rmCreatedTeamFromRedis, rmRoleFromQueue, setCreatedTeamToRedis } from '../redisService'; -import { getRewardByBlueprtId, gameData, getBossHpByBlueprtId, getDicBlueprtById } from '../../pubUtils/data'; -import { getZeroPointD, nowSeconds } from '../../pubUtils/timeUtil'; -import { addItems, getFriendPointObject, handleCost } from '../role/rewardService'; -import { addUserToTeamChannel, delTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../pushService'; -import { checkTaskInComBattleEnd } from '../task/taskService'; -import { RewardInter } from '../../pubUtils/interface'; -import { FriendPointModel } from '../../db/FriendPoint'; -import { isComBattleTimeLimit } from '../../pubUtils/battleUtils'; -import { clearComBtlTimer, deleteComBattle, getComTeamByCode, getComTeamTimerByCode, getRobotHurtTimer, setComTeamTimer, setRobotHurtTimerIfNotExist } from '../memoryCache/comBattleData'; -import { clearComBattleRoute } from '../../pubUtils/dispatcher'; - -/** - * 在给定的品质列表中随机返回一定数量的藏宝图Id - * @param lv 品质数组,在所有给定品质的藏宝图中筛选1 - * @param cnt 返回藏宝图数量 - */ -export function getRandBlueprtId(lvs: number[], cnt = 1) { - if (!lvs || !lvs.length) return null; - - let blueprtIdArr: number[] = []; - for (let lv of lvs) { - blueprtIdArr = blueprtIdArr.concat(gameData.blueprtByLv.get(lv)); - } - if (blueprtIdArr.length === 0) return null; - - const res = getRandEelm(blueprtIdArr, cnt); - // console.log('******** getRandBlueprtId', blueprtIdArr, cnt, res) - return res; -} - -export function getRandComBtlRobots(topLineupCe: number, ceLimit: number, lv: number, cnt: number) { - let robotHeroes = getRandRobot(cnt); // 随机几个阵容 - let robotInfos: { robotRoleName: string, robotRoleId: string }[] = []; // 随机几个机器人信息 - for (let i = 0; i < cnt; i++) { - robotInfos.push(getRobotInfo()); - } - // 创建并添加机器人 - let robotStArr: RoleStatus[] = [], robotIdArr: string[] = []; - if (robotHeroes && robotInfos && robotHeroes.length && robotInfos.length && robotInfos.length === robotHeroes.length) { - robotHeroes.forEach((robot, idx) => { - let robotCe = 0; - if (ceLimit && ceLimit > 0) { - robotCe = getRandValueByMinMax(ceLimit, (topLineupCe || 0) * (1 + COM_BTL_CONST.ROBOT_CE_RATIO), 0); - } else { - robotCe = getRandValue(topLineupCe || 0, COM_BTL_CONST.ROBOT_CE_RATIO, 0); - } - let robotLv = getRandValue(lv, COM_BTL_CONST.ROBOT_CE_RATIO, 0); - if(robotLv > gameData.maxPlayerLv.max) robotLv = gameData.maxPlayerLv.max; - // const imgHid = robot[Math.floor(Math.random() * robot.length)]; - const { robotRoleId, robotRoleName } = robotInfos[idx]; - let robotStatus = new RoleStatus({ - roleId: robotRoleId, - roleName: robotRoleName, - topLineupCe: robotCe, - lv: robotLv - }, '', false, false, robot, true); - robotStArr.push(robotStatus); - robotIdArr.push(robotRoleId); - }); - } - return { - robotStArr, robotIdArr - } -} - -export function checkComBattleResult(teamStatus) { - if (teamStatus.bossCurHp === 0) { - return COM_TEAM_STATUS.WIN; - } else { - let allPlayerKilled = true; - let robotRestHurt = 0; - // 看看是否还有活人 - teamStatus.roleStatus.forEach(st => { - // 设置了阵容,且阵容人数和阵亡人数一样,说明玩家战败 - if (!st.isRobot && st.battleStatus != 2 && st.heroes && ((st.heroes.length > 0 && st.killed.length < st.heroes.length) || st.heroes.length === 0 )) { - allPlayerKilled = false - } - }); - // 没有活人的话看看还有没有机器人没打完伤害 - if (allPlayerKilled && teamStatus.curRnd < COM_BTL_CONST.ROBOT_RND_LMT) { - teamStatus.roleStatus.forEach(st => { - if (st.isRobot) { - const deltaRnd = COM_BTL_CONST.ROBOT_RND_LMT - teamStatus.curRnd; - let hurtHp = getRandValue(teamStatus.bossHp / COM_BTL_CONST.ROBOT_RND_LMT * COM_BTL_CONST.ROBOT_HURT_RATIO, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害 - robotRestHurt += hurtHp; - } - }) - } - if (allPlayerKilled) { - // 没有活人且机器人剩余伤害打不死 boss,战败 - if (teamStatus.bossCurHp > robotRestHurt) { - return COM_TEAM_STATUS.LOOSE; - } else { - return COM_TEAM_STATUS.WIN; - } - } - } - return COM_TEAM_STATUS.FIGHTING; -} - -// /** -// * ! deprecated -// * @description 计算寻宝结算 -// * @export -// * @param {string} roleId -// * @param {string} battleCode -// * @returns -// */ -// export async function checkComBattleDrop(roleId: string, battleCode: string) { -// let team = await ComBattleTeamModel.getTeamByRoleAndBattleCode(roleId, battleCode); -// if (team.status !== COM_TEAM_STATUS.WIN) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; -// let roleSt = null; -// team.roleStatus.forEach(st => { -// if (st.roleId === roleId) { -// roleSt = st; -// } -// }); -// if (!roleSt || roleSt.gotReward) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; -// let { fixReward, teammateReward } = getRewardByBlueprtId(team.blueprtId); -// if (!roleSt.isCap) { -// if (roleSt.isFrd) { -// fixReward = []; -// } else { -// fixReward = teammateReward; -// } -// } -// await ComBattleTeamModel.updateRewardSt(team.teamCode, roleId, true); -// return { status: 0, fixReward }; -// } - -export async function getRealReward(blueprtId: number, roleSts: RoleStatus[], roleSt: RoleStatus, hasTimeExtraReward: boolean): Promise { - let dicReward = getRewardByBlueprtId(blueprtId); - if(!dicReward) return []; - - let fixRewards: RewardInter[] = [], extraRewards: RewardInter[] = [], hasExtraReward = true; - if (roleSt.isCap) { - fixRewards.push(...dicReward.captainReward); - if(roleSt.isFrd && !roleSt.isRobot) { - hasExtraReward = false; - } - } else { - if (roleSt.isFrd && !roleSt.isRobot) { - // 情谊值有上限,送到上限为止 - let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleSt.roleId, FRIEND_DROP_TYPE.COM_BATTLE); - let { comBattleCnt = 0 } = frdPointRec || {}; - if(comBattleCnt < FRIEND.FRIEND_FRIENDPOINT_MAX) { - let count = FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt > TREASURE.REWARD_FRIENDPOINT? TREASURE.REWARD_FRIENDPOINT: FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt; - fixRewards.push(getFriendPointObject(count)); - await FriendPointModel.updateComBattleCntToday(roleSt.roleId, roleSt.roleName, count, FRIEND.FRIEND_FRIENDPOINT_MAX, FRIEND_DROP_TYPE.COM_BATTLE); - } - hasExtraReward = false; - } else { - fixRewards.push(...dicReward.teammateReward) - } - } - if(hasTimeExtraReward && hasExtraReward) { - let sameGuildCnt = roleSts.filter(cur => !!roleSt.guildCode && cur.guildCode == roleSt.guildCode && cur.roleId != roleSt.roleId).length; - if(sameGuildCnt > 0) { - let dicGuildReward = roleSt.isCap? dicReward.captainTimeGuildReward: dicReward.teammateTimeGuildReward; - let guildRewards = dicGuildReward.get(sameGuildCnt)||[] - extraRewards.push(...guildRewards); - } else { - let guildRewards = roleSt.isCap? dicReward.captainTimeReward: dicReward.teammateTimeReward; - extraRewards.push(...guildRewards); - } - } - return [ - ...fixRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.FIX_REWARD, ...reward })), - ...extraRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.EXTRA_REWARD, ...reward })) - ] -} - -export async function getAllAssistCnt(roleId: string) { - let teams = await ComBattleTeamModel.getAssistTeamsByTime(roleId, getZeroPointD(), true); - if (teams.length > 0) { - // 过滤掉情谊助战次数 - teams = teams.filter(team => { - let roleSt = team.roleStatus.find(st => st.roleId === roleId); - return !roleSt.isFrd; - }); - } - return teams.length; -} - -export async function getCapExtraCnt(roleId: string) { - let teams = await ComBattleTeamModel.getCapExtraRewardCnt(roleId, getZeroPointD()); - return teams.length; -} - -export async function getFrd(roleId: string) { - let isFrd = false; - let cnt = await getAllAssistCnt(roleId); - if (cnt >= TREASURE.TREASURE_ASSIST_TIME) isFrd = true; - return isFrd; -} - -export async function getCapFrd(roleId: string) { - let isFrd = false; - let cnt = await getCapExtraCnt(roleId); - if (cnt >= TREASURE.TREASURE_CAP_EXTRA_TIME) isFrd = true; - return isFrd; -} - -/** - * @description 更新队伍状态 - * @export - * @param {number} preStatus 更新前状态,作为筛选条件 - * @param {number} newStatus 要设置的新状态 - */ -export async function updateTeamStatus(preStatus: number, newStatus: number) { - if (preStatus === newStatus) return; - await ComBattleTeamModel.updateStatusByStatus(preStatus, newStatus); -} - -/** - * @description 计算机器人每次对 boss 造成的伤害 - * @param {number} bossHp boss 总血量 - */ -function robotEachHurt(bossHp: number, bossCnt: number) { - const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; - const robotAverageHurt = robotTotalHurt / COM_BTL_CONST.ROBOT_ACT_LMT / bossCnt; - return getRandValue(robotAverageHurt, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) -} - -/** - * @description 更新机器人阵亡情况 - * @param {number} bossHp - * @param {RoleStatus} roleSt - */ -function updateRobotKilled(bossHp: number, roleSt: RoleStatus) { - const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; - // 让阵亡人数和打出伤害的进度同步,比如有 5 个武将,每打出目标总伤害的 1 / 5 应该增加一个阵亡武将 - const dmgProgress = Math.floor(roleSt.totalDmg / (robotTotalHurt / roleSt.heroes.length)); - if (dmgProgress > roleSt.killed.length && dmgProgress <= roleSt.heroes.length) { - const newKilledCnt = dmgProgress - roleSt.killed.length; - const aliveHeroes = roleSt.heroes.filter(hero => { - return roleSt.killed.indexOf(hero.id) == -1; - }).map(cur => cur.id); - const newKilledHeroes = getRandEelm(aliveHeroes, newKilledCnt); - roleSt.killed = roleSt.killed.concat(newKilledHeroes); - } -} - -export async function handleComBtlProgress(teamStatus: MemComBtlTeam) { - const { teamCode } = teamStatus; - // 判断战斗是否结束 - let battleSt = checkComBattleResult(teamStatus); - teamStatus.status = battleSt; - if (battleSt === COM_TEAM_STATUS.WIN || battleSt === COM_TEAM_STATUS.LOOSE) { - let result = battleSt === COM_TEAM_STATUS.WIN; - if (result) { - teamStatus.bossHpArr.forEach(bs => { - bs.curHp = 0; - }); - for (let st of teamStatus.roleStatus) { - st.rewards = await getRealReward(teamStatus.blueprtId, teamStatus.roleStatus, st, teamStatus.hasTimeExtraReward); - }; - await checkTaskInComBattleEnd(teamStatus.roleStatus, teamStatus.capId); - } - let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: battleSt, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: teamStatus.endTime }); - if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); - - // 战斗胜利队长扣减藏宝图 - if (result && teamStatus.capId != 'robot') { - let res = await handleCost(teamStatus.capId, teamStatus.sid, [{ id: teamStatus.blueprtId, count: 1 }], ITEM_CHANGE_REASON.COM_BATTLE_USE_BLUEPRT); - if (res === false) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); - } - - clearRobotHurtTimer(teamStatus); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result }); - - deleteComBattle(teamCode); - clearComBattleRoute(redisClient(), teamCode); - } -} - -/** - * @description 更新机器人对 boss 的伤害 - * @export - * @param {*} teamStatus 要更新的队伍信息 - * @param {RoleStatus} roleSt 要更新的玩家信息 - */ -export function updateRobotHurt(teamStatus: MemComBtlTeam, roleSt: RoleStatus) { - // 机器人的伤害为:boss 血量的一定比例,平均到一定回合数内,再平均到每个敌军,上下浮动一定比例 - let eachHurtHp = robotEachHurt(teamStatus.bossHp, teamStatus.bossHpArr.length); - let robotTotalHurt = 0; - let actBossHurts = []; - let hero = getRandSingleEelm(roleSt.heroes); - for (let boss of teamStatus.bossHpArr) { - if (boss.curHp === 0) continue; - if (boss.curHp >= eachHurtHp) { - actBossHurts.push({ dataId: boss.dataId, hurtHp: eachHurtHp }); - robotTotalHurt += eachHurtHp; - boss.curHp -= eachHurtHp; - hero.addDamage(eachHurtHp); - } else if (boss.curHp > 0) { // 丢弃溢出的伤害 - actBossHurts.push({ dataId: boss.dataId, hurtHp: boss.curHp }); - robotTotalHurt += boss.curHp; - hero.addDamage(boss.curHp); - boss.curHp = 0; - } - break; - } - teamStatus.bossCurHp -= robotTotalHurt; - roleSt.totalDmg += robotTotalHurt; - updateRobotKilled(teamStatus.bossHp, roleSt); - sendMessageToTeam(teamStatus.teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: teamStatus.roleStatus, actRoleId: roleSt.roleId, actBossHurts }); -} - -/** - * @description 按一定时间间隔刷新机器人伤害 - * @export - * @param {*} teamStatus - * @param {RoleStatus} roleSt - * @param {number} interval - * @param {Channel} channel - */ -export function updateRobotHurtByTime(teamStatus: MemComBtlTeam, roleSt: RoleStatus, interval: number) { - const robotTimer = setInterval(() => { - const robotTotalHurt = teamStatus.bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; - let team = getComTeamByCode(teamStatus.teamCode); - if (roleSt.totalDmg < robotTotalHurt && teamStatus.bossCurHp > 0 && team) { - updateRobotHurt(teamStatus, roleSt); - handleComBtlProgress(teamStatus); - } else { - clearInterval(robotTimer); - } - }, interval * 1000); - setRobotHurtTimerIfNotExist(teamStatus.teamCode, roleSt.roleId, robotTimer); -} - -/** - * @description 清理机器人伤害的 timer - * @export - * @param {MemComBtlTeam} teamStatus 寻宝队伍状态 - */ -export function clearRobotHurtTimer(teamStatus: { teamCode: string, roleStatus: RoleStatus[] }) { - teamStatus.roleStatus.forEach(st => { - let robotHurtTimer = getRobotHurtTimer(teamStatus.teamCode, st.roleId); - if (st.isRobot === true && robotHurtTimer) { - clearInterval(robotHurtTimer); - } - }); -} - -/** - * @description 检查寻宝等级是否合法 - * @export - * @param {number} playerLv 玩家等级 - * @param {number} blueprtLv 藏宝图等级 - * @returns - */ -export function comBtlLvInvalid(playerLv: number, blueprtLvs: number[]) { - for(let blueprtLv of blueprtLvs) { - const range = gameData.comBtlLvRange.get(blueprtLv); - if (!range) return true; - let { min, max } = range; - if(playerLv < min || playerLv > max) return true; - } - return false -} - -export function getComBtlLvByPlayerLv(playerLv: number) { - let lvs: number[] = []; - for(let [lv, {min, max}] of gameData.comBtlLvRange) { - if(playerLv >= min && playerLv <= max) lvs.push(lv); - } - let minLv = Math.min(...lvs); - let maxLv = Math.max(...lvs); - return { minLv, maxLv } -} - -export async function dismissTeam(teamStatus: MemComBtlTeam, roleId: string) { - const { teamCode } = teamStatus; - if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); - if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); - if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); - - let team = await ComBattleTeamModel.removeTeam(teamCode); - if (!team) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); - - let rmSt = deleteComBattle(teamCode); - if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); - clearComBattleRoute(redisClient(), teamCode); - - rmCreatedTeamFromRedis(teamCode, teamStatus.lv); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_DISMISS, { teamCode }); - delTeamChannel(teamCode); - clearComBtlTimer(teamCode); // 队伍解散停止解散计时 - return resResult(STATUS.SUCCESS); -} - -export function setDismissTimer(teamStatus: MemComBtlTeam, roleId: string) { - // if (teamIsFullToStart(teamStatus)) { - clearComBtlTimer(teamStatus.teamCode); - let timer = setTimeout(async () => { - await dismissTeam(teamStatus, roleId); - }, COM_BTL_CONST.CAP_START_TIME); - setComTeamTimer(teamStatus.teamCode, timer);; - // } -} - -/** - * 按照好友关系,新增加成 - * - * @param {RoleStatus[]} roleStatus 队伍内的所有队友 - */ -export async function getComBattleFriendAdd(roleStatus: RoleStatus[]) { - let hasAdd: string[] = []; //roleIds - for (let myRoleStatus of roleStatus) { - for (let rs of roleStatus) { - if (myRoleStatus.roleId == rs.roleId) continue; - if (myRoleStatus.isRobot || rs.isRobot) continue; - - let { roleIds } = getRoleIds([myRoleStatus.roleId, rs.roleId]); - if (hasAdd.includes(roleIds)) continue; - - let add = await getFriendLvAdd(myRoleStatus.roleId, rs.roleId); - rs.addFrdRatio(add); - myRoleStatus.addFrdRatio(add); - - hasAdd.push(roleIds); - } - } -} - -/** - * @description 检查玩家是否符合加入队伍的条件 - * @param {Partial} roleInfo 要加入玩家的信息 - * @param {string} roleId 要加入玩家的 id - * @param {string[]} roleIds 队伍中当前玩家列表 - * @param {number} ceLimit - * @returns - */ -async function teammateValid(roleInfo: Partial, roleId: string, roleIds: string[], ceLimit: number) { - if (!roleInfo || roleIds.indexOf(roleId) !== -1) return false; - - const isBlack = await teammateInBlackList(roleId, roleIds); - if (isBlack) return false; - - let { topLineupCe } = roleInfo; - if (topLineupCe < ceLimit) return false; - - return true; -} - -/** - * @description 将用户信息转换成寻宝组队所需的 RoleStatus - * @export - * @param {string} roleId 要加入玩家的信息 - * @param {string[]} roleIds 队伍中当前玩家列表 - * @param {number} ceLimit - * @returns - */ -export async function getValidTeammateRoleSt(roleId: string, roleIds: string[], ceLimit: number, sid: string) { - let roleInfo = await RoleModel.findByRoleId(roleId, null, true); - - const valid = await teammateValid(roleInfo, roleId, roleIds, ceLimit); - if (!valid) return null; - - let isFrd = await getFrd(roleId); - const result = new RoleStatus(roleInfo, sid, false, isFrd); - return result; -} - -/** - * @description 检查队伍中是否有人互为黑名单 - * @export - * @param {string} roleId 要加入队伍的玩家 id - * @param {string[]} roleIds 队伍中已有的玩家 id - * @returns - */ -export async function teammateInBlackList(roleId: string, roleIds: string[]) { - for (let teammateRoleId of roleIds) { - const isBlack = await FriendRelationModel.isInBlackList(roleId, teammateRoleId); - if (isBlack === true) return true; - } - return false; -} - -export function blueprtIdValid(id: number) { - return gameData.blueprt.has(id); -} - -/** - * @description 检查是否有足够的藏宝图,未结束的战斗也占用一张藏宝图 - * @export - * @param {string} roleId - * @param {number} blueprtId - * @returns - */ -export async function hasEnoughBlueprt(roleId: string, sid: string, blueprtId: number) { - let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1); - if (!blueprt || blueprt.count <= 0) return false; - // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 - // // 背包中占用的藏宝图不显示,所以这里就扣掉,结束再加回去 - // let result = await handleCost(roleId, sid, [{ id: blueprtId, count: 1 }]); - // return result; - let teams = await ComBattleTeamModel.getBlueprtInUse(roleId, COM_TEAM_STATUS.FIGHTING, blueprtId); - console.log('hasEnoughBlueprt', blueprt.count, teams.length) - if (teams && blueprt.count <= teams.length) return false; - return true -} - -/** - * @description 将玩家加入到队伍数据结构中,需将玩家信息做转化 - * @export - * @param {MemComBtlTeam} comTeam 队伍数据结构 - * @param {RoleType} roleInfo 原始玩家信息 - * @param {boolean} isCap - * @param {boolean} isFrd - */ -export function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, sid: string, isCap: boolean, isFrd: boolean) { - const roleSt = new RoleStatus(roleInfo, sid, isCap, isFrd); - addRoleStToTeam(comTeam, roleSt); -} - -/** - * @description 将玩家加入到队伍数据结构中 - * @export - * @param {MemComBtlTeam} comTeam 队伍数据结构 - * @param {RoleStatus} roleSt 要加入的玩家数据 - */ -export function addRoleStToTeam(comTeam: MemComBtlTeam, roleSt: RoleStatus) { - const { roleStatus = [], roleIds = [] } = comTeam; - comTeam.roleStatus = [roleSt, ...roleStatus]; - comTeam.roleIds = [roleSt.roleId, ...roleIds]; - - if(!validToJoin(comTeam)) { // 无人可匹配时,删除存在redis中的匹配信息 - rmCreatedTeamFromRedis(comTeam.teamCode, comTeam.lv); - } -} - -/** - * @description 将符合要求的用户匹配到队伍中 - * @export - * @param {MemComBtlTeam} comTeam 队伍数据 - * @param {string} sid 当前用户 sid - * @returns - */ -export async function addValidSearchingRoles(comTeam: MemComBtlTeam) { - const { lv } = getDicBlueprtById(comTeam.blueprtId); - let teammates = await getTeamSearchByLv(lv); - if (teammates && teammates.length) { - for (let teammate of teammates) { - const { roleId: teammateRoleId, sid } = teammate; - const st = await getValidTeammateRoleSt(teammateRoleId, comTeam.roleIds, comTeam.ceLimit, sid); - if (!st) continue; - await rmRoleFromQueue(teammateRoleId, sid); // 匹配成功后删除redis中该用户的匹配记录 - addRoleStToTeam(comTeam, st); - addUserToTeamChannel(comTeam.teamCode, false, teammateRoleId, sid); - } - sendMessageToUsersWithSuc(PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }, teammates.map(t => { return { uid: t.roleId, sid: t.sid } })); - } -} - -export async function addToSearchingTeams(roleId: string, sid: string, lvs: number[]) { - let teamCodes = await getCreatedTeamByLv(lvs); - if(teamCodes.length <= 0) return false; - - let {lv, teamCode} = getRandSingleEelm(teamCodes); - let battleServer = await getComTeamSidByCode(lv, teamCode); - if(!battleServer) return false; - - return await pinus.app.rpc.comBattle.comBattleRemote.addToSearchingTeams.toServer(battleServer, teamCode, roleId, sid); -} - -export async function _addToSearchingTeams(teamCode: string, roleId: string, sid: string) { - let teamMap = pinus.app.get('teamMap'); - let teamStatus: MemComBtlTeam = teamMap && teamMap.get(teamCode); - if(!teamStatus) return false; - if(!validToJoin(teamStatus, roleId)) return false; - const st = await getValidTeammateRoleSt(roleId, teamStatus.roleIds, teamStatus.ceLimit, sid); - if (!st) return false; - - addRoleStToTeam(teamStatus, st); - await rmRoleFromQueue(roleId, sid); // 匹配成功后删除redis中该用户的匹配记录 - addUserToTeamChannel(teamCode, false, roleId, sid); - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus }); - await ComBattleTeamModel.addRole(teamCode, st); -} - -/** - * @description 判断队伍是否处于可加入状态 - * @export - * @param {MemComBtlTeam} comTeam - * @param {string} [roleId=''] 要加入的玩家 id - * @returns - */ -export function validToJoin(comTeam: MemComBtlTeam, roleId = '') { - return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length < 3 && comTeam.roleIds.indexOf(roleId) === -1; -} - -/** - * @description 判断队伍是否处于可满员状态 - * @export - * @param {MemComBtlTeam} comTeam - * @returns - */ -export function teamIsFullToStart(comTeam: MemComBtlTeam) { - return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length === 3; -} - -/** - * @description 添加指定数量的机器人到队伍 - * @export - * @param {MemComBtlTeam} comTeam - * @param {number} roleCe 真实玩家战力,用来做机器人战力基准 - * @param {number} roleLv 真实玩家等级,用来做机器人等级基准 - * @param {number} [count=1] - */ -export async function addRobotsToTeam(comTeam: MemComBtlTeam, roleId: string, roleCe: number, roleLv: number, count = 1) { - const { teamCode, roleStatus } = comTeam; - let hasCap = roleStatus.findIndex(cur => cur.isCap) != -1; - const { robotStArr, robotIdArr } = getRandComBtlRobots(roleCe, comTeam.ceLimit, roleLv, count); - for (let st of robotStArr) { - if(!hasCap) { - st.isCap = true; - hasCap = true; - } - addRoleStToTeam(comTeam, st); - await ComBattleTeamModel.addRole(teamCode, st); - } - sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }) - setDismissTimer(comTeam, roleId); -} - -/** - * @description 在不同的时间加入机器人 - * @export - * @param {MemComBtlTeam} comTeam - * @param {RoleType} roleInfo - * @param {Map} teamMap - * @param {Map} teamDisTimer - */ -export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType) { - const teamStatus = comTeam; - const { teamCode, lv: blueprtLv } = teamStatus; - const { roleId, lv } = roleInfo; - let { topLineupCe = 1000 } = roleInfo; - - if (validToJoin(teamStatus)) { // 如果可以匹配 - await setCreatedTeamToRedis(teamCode, blueprtLv); - - const robotCnt = 3 - teamStatus.roleIds.length; - for (let robotIdx = 0; robotIdx < robotCnt; robotIdx++) { - const joinTime = getRandValueByMinMax(COM_BTL_CONST.MIN_CAP_TIME, COM_BTL_CONST.MAX_CAP_TIME, 0); - setTimeout(async () => { - const curTeamStatus = getComTeamByCode(teamCode); - if (validToJoin(curTeamStatus)) { - await addRobotsToTeam(curTeamStatus, roleId, topLineupCe, lv, 1); - } - }, joinTime); - } - } -} - -/** - * @description 从数组里找出第一个不在黑名单的队伍 - * @export - * @param {ComBattleTeamType[]} teams 队伍数组 - * @param {string} roleId 要加入的玩家 id - * @returns - */ -export async function oneTeamNotInBlack(teams: ComBattleTeamType[], roleId: string) { - for (let team of teams) { - let { roleIds } = team; - const inBlackList = await teammateInBlackList(roleId, roleIds); - if (!inBlackList) { - return team; - } - } - return null; -} - -// export async function setComBtlOnUserLeave(roleId: string, teamCode: string) { -// let res = dispatch(teamCode, pinus.app.getServersByType('battle'), 'battle'); -// await pinus.app.rpc.battle.comBattleRemote.leaveFromBattle.toServer(res.id, roleId, teamCode); -// } - -export async function checkHasMyTeam(roleId: string) { - return await ComBattleTeamModel.checkHasTeamByRoleId(roleId); -} - -export async function checkTeamStatusAndSend(teamCode: string, roleId: string, sid: string) { - let team = await ComBattleTeamModel.getTeamByCode(teamCode); - if(team && (team.status == 2|| team.status == 3)) { - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: team.status == 2? true: false, timeout: team.timeout }, sid); - } -} - -export async function startTeam(team: MemComBtlTeam) { - team.status = COM_TEAM_STATUS.FIGHTING; - team.startTime = nowSeconds(); - team.endTime = nowSeconds() + COM_BTL_CONST.BTL_TIME_LMT/1000; - team.hasTimeExtraReward = isComBattleTimeLimit(); -} \ No newline at end of file +import { MemComBtlTeam } from '@domain/battleField/ComBattleTeamField'; +import { ItemModel } from '@db/Item'; +import { BATTLE_REWARD_TYPE, ITEM_CHANGE_REASON, IT_TYPE, PUSH_ROUTE, STATUS } from '@consts'; +import { FriendRelationModel } from '@db/FriendRelation'; +import { RoleModel, RoleType } from '@db/Role'; +import { COM_TEAM_STATUS, FRIEND_DROP_TYPE, COM_BTL_CONST, FRIEND_DROP_MAX } from '@consts'; +import { RoleStatus, ComBattleTeamModel, ComBattleTeamType, ComBattleReward } from '@db/ComBattleTeam'; +import { getRandEelm, getRandValue, resResult, ratioReward, getRandValueByMinMax, getRandEelmWithWeight, getRobotInfo, getRandSingleEelm } from "@pubUtils/util"; +import { getRandRobot } from "../battleService"; +import { Channel, ChannelService, pinus } from 'pinus'; +import { TREASURE, EXTERIOR, FRIEND } from '@pubUtils/dicParam'; +import { getFriendLvAdd } from '../friendService'; +import { getRoleIds } from '@pubUtils/friendUtil'; +import { getComTeamSidByCode, getCreatedTeamByLv, getTeamSearchByLv, redisClient, rmCreatedTeamFromRedis, rmRoleFromQueue, setCreatedTeamToRedis } from '../redisService'; +import { getRewardByBlueprtId, gameData, getBossHpByBlueprtId, getDicBlueprtById } from '@pubUtils/data'; +import { getZeroPointD, nowSeconds } from '@pubUtils/timeUtil'; +import { addItems, getFriendPointObject, handleCost } from '../role/rewardService'; +import { addUserToTeamChannel, delTeamChannel, sendMessageToTeam, sendMessageToUsersWithSuc, sendMessageToUserWithSuc } from '../pushService'; +import { checkTaskInComBattleEnd } from '../task/taskService'; +import { RewardInter } from '@pubUtils/interface'; +import { FriendPointModel } from '@db/FriendPoint'; +import { isComBattleTimeLimit } from '@pubUtils/battleUtils'; +import { clearComBtlTimer, deleteComBattle, getComTeamByCode, getComTeamTimerByCode, getRobotHurtTimer, setComTeamTimer, setRobotHurtTimerIfNotExist } from '../memoryCache/comBattleData'; +import { clearComBattleRoute } from '@pubUtils/dispatcher'; + +/** + * 在给定的品质列表中随机返回一定数量的藏宝图Id + * @param lv 品质数组,在所有给定品质的藏宝图中筛选1 + * @param cnt 返回藏宝图数量 + */ +export function getRandBlueprtId(lvs: number[], cnt = 1) { + if (!lvs || !lvs.length) return null; + + let blueprtIdArr: number[] = []; + for (let lv of lvs) { + blueprtIdArr = blueprtIdArr.concat(gameData.blueprtByLv.get(lv)); + } + if (blueprtIdArr.length === 0) return null; + + const res = getRandEelm(blueprtIdArr, cnt); + // console.log('******** getRandBlueprtId', blueprtIdArr, cnt, res) + return res; +} + +export function getRandComBtlRobots(topLineupCe: number, ceLimit: number, lv: number, cnt: number) { + let robotHeroes = getRandRobot(cnt); // 随机几个阵容 + let robotInfos: { robotRoleName: string, robotRoleId: string }[] = []; // 随机几个机器人信息 + for (let i = 0; i < cnt; i++) { + robotInfos.push(getRobotInfo()); + } + // 创建并添加机器人 + let robotStArr: RoleStatus[] = [], robotIdArr: string[] = []; + if (robotHeroes && robotInfos && robotHeroes.length && robotInfos.length && robotInfos.length === robotHeroes.length) { + robotHeroes.forEach((robot, idx) => { + let robotCe = 0; + if (ceLimit && ceLimit > 0) { + robotCe = getRandValueByMinMax(ceLimit, (topLineupCe || 0) * (1 + COM_BTL_CONST.ROBOT_CE_RATIO), 0); + } else { + robotCe = getRandValue(topLineupCe || 0, COM_BTL_CONST.ROBOT_CE_RATIO, 0); + } + let robotLv = getRandValue(lv, COM_BTL_CONST.ROBOT_CE_RATIO, 0); + if(robotLv > gameData.maxPlayerLv.max) robotLv = gameData.maxPlayerLv.max; + // const imgHid = robot[Math.floor(Math.random() * robot.length)]; + const { robotRoleId, robotRoleName } = robotInfos[idx]; + let robotStatus = new RoleStatus({ + roleId: robotRoleId, + roleName: robotRoleName, + topLineupCe: robotCe, + lv: robotLv + }, '', false, false, robot, true); + robotStArr.push(robotStatus); + robotIdArr.push(robotRoleId); + }); + } + return { + robotStArr, robotIdArr + } +} + +export function checkComBattleResult(teamStatus) { + if (teamStatus.bossCurHp === 0) { + return COM_TEAM_STATUS.WIN; + } else { + let allPlayerKilled = true; + let robotRestHurt = 0; + // 看看是否还有活人 + teamStatus.roleStatus.forEach(st => { + // 设置了阵容,且阵容人数和阵亡人数一样,说明玩家战败 + if (!st.isRobot && st.battleStatus != 2 && st.heroes && ((st.heroes.length > 0 && st.killed.length < st.heroes.length) || st.heroes.length === 0 )) { + allPlayerKilled = false + } + }); + // 没有活人的话看看还有没有机器人没打完伤害 + if (allPlayerKilled && teamStatus.curRnd < COM_BTL_CONST.ROBOT_RND_LMT) { + teamStatus.roleStatus.forEach(st => { + if (st.isRobot) { + const deltaRnd = COM_BTL_CONST.ROBOT_RND_LMT - teamStatus.curRnd; + let hurtHp = getRandValue(teamStatus.bossHp / COM_BTL_CONST.ROBOT_RND_LMT * COM_BTL_CONST.ROBOT_HURT_RATIO, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) * deltaRnd; // 1 个机器人对 boss 造成的总伤害 + robotRestHurt += hurtHp; + } + }) + } + if (allPlayerKilled) { + // 没有活人且机器人剩余伤害打不死 boss,战败 + if (teamStatus.bossCurHp > robotRestHurt) { + return COM_TEAM_STATUS.LOOSE; + } else { + return COM_TEAM_STATUS.WIN; + } + } + } + return COM_TEAM_STATUS.FIGHTING; +} + +// /** +// * ! deprecated +// * @description 计算寻宝结算 +// * @export +// * @param {string} roleId +// * @param {string} battleCode +// * @returns +// */ +// export async function checkComBattleDrop(roleId: string, battleCode: string) { +// let team = await ComBattleTeamModel.getTeamByRoleAndBattleCode(roleId, battleCode); +// if (team.status !== COM_TEAM_STATUS.WIN) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; +// let roleSt = null; +// team.roleStatus.forEach(st => { +// if (st.roleId === roleId) { +// roleSt = st; +// } +// }); +// if (!roleSt || roleSt.gotReward) return { status: -1, resResult: resResult(STATUS.COM_BATTLE_REWARD_ERR) }; +// let { fixReward, teammateReward } = getRewardByBlueprtId(team.blueprtId); +// if (!roleSt.isCap) { +// if (roleSt.isFrd) { +// fixReward = []; +// } else { +// fixReward = teammateReward; +// } +// } +// await ComBattleTeamModel.updateRewardSt(team.teamCode, roleId, true); +// return { status: 0, fixReward }; +// } + +export async function getRealReward(blueprtId: number, roleSts: RoleStatus[], roleSt: RoleStatus, hasTimeExtraReward: boolean): Promise { + let dicReward = getRewardByBlueprtId(blueprtId); + if(!dicReward) return []; + + let fixRewards: RewardInter[] = [], extraRewards: RewardInter[] = [], hasExtraReward = true; + if (roleSt.isCap) { + fixRewards.push(...dicReward.captainReward); + if(roleSt.isFrd && !roleSt.isRobot) { + hasExtraReward = false; + } + } else { + if (roleSt.isFrd && !roleSt.isRobot) { + // 情谊值有上限,送到上限为止 + let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleSt.roleId, FRIEND_DROP_TYPE.COM_BATTLE); + let { comBattleCnt = 0 } = frdPointRec || {}; + if(comBattleCnt < FRIEND.FRIEND_FRIENDPOINT_MAX) { + let count = FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt > TREASURE.REWARD_FRIENDPOINT? TREASURE.REWARD_FRIENDPOINT: FRIEND.FRIEND_FRIENDPOINT_MAX - comBattleCnt; + fixRewards.push(getFriendPointObject(count)); + await FriendPointModel.updateComBattleCntToday(roleSt.roleId, roleSt.roleName, count, FRIEND.FRIEND_FRIENDPOINT_MAX, FRIEND_DROP_TYPE.COM_BATTLE); + } + hasExtraReward = false; + } else { + fixRewards.push(...dicReward.teammateReward) + } + } + if(hasTimeExtraReward && hasExtraReward) { + let sameGuildCnt = roleSts.filter(cur => !!roleSt.guildCode && cur.guildCode == roleSt.guildCode && cur.roleId != roleSt.roleId).length; + if(sameGuildCnt > 0) { + let dicGuildReward = roleSt.isCap? dicReward.captainTimeGuildReward: dicReward.teammateTimeGuildReward; + let guildRewards = dicGuildReward.get(sameGuildCnt)||[] + extraRewards.push(...guildRewards); + } else { + let guildRewards = roleSt.isCap? dicReward.captainTimeReward: dicReward.teammateTimeReward; + extraRewards.push(...guildRewards); + } + } + return [ + ...fixRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.FIX_REWARD, ...reward })), + ...extraRewards.map(reward => ({ type: BATTLE_REWARD_TYPE.EXTRA_REWARD, ...reward })) + ] +} + +export async function getAllAssistCnt(roleId: string) { + let teams = await ComBattleTeamModel.getAssistTeamsByTime(roleId, getZeroPointD(), true); + if (teams.length > 0) { + // 过滤掉情谊助战次数 + teams = teams.filter(team => { + let roleSt = team.roleStatus.find(st => st.roleId === roleId); + return !roleSt.isFrd; + }); + } + return teams.length; +} + +export async function getCapExtraCnt(roleId: string) { + let teams = await ComBattleTeamModel.getCapExtraRewardCnt(roleId, getZeroPointD()); + return teams.length; +} + +export async function getFrd(roleId: string) { + let isFrd = false; + let cnt = await getAllAssistCnt(roleId); + if (cnt >= TREASURE.TREASURE_ASSIST_TIME) isFrd = true; + return isFrd; +} + +export async function getCapFrd(roleId: string) { + let isFrd = false; + let cnt = await getCapExtraCnt(roleId); + if (cnt >= TREASURE.TREASURE_CAP_EXTRA_TIME) isFrd = true; + return isFrd; +} + +/** + * @description 更新队伍状态 + * @export + * @param {number} preStatus 更新前状态,作为筛选条件 + * @param {number} newStatus 要设置的新状态 + */ +export async function updateTeamStatus(preStatus: number, newStatus: number) { + if (preStatus === newStatus) return; + await ComBattleTeamModel.updateStatusByStatus(preStatus, newStatus); +} + +/** + * @description 计算机器人每次对 boss 造成的伤害 + * @param {number} bossHp boss 总血量 + */ +function robotEachHurt(bossHp: number, bossCnt: number) { + const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; + const robotAverageHurt = robotTotalHurt / COM_BTL_CONST.ROBOT_ACT_LMT / bossCnt; + return getRandValue(robotAverageHurt, COM_BTL_CONST.ROBOT_HURT_CH_RATIO, 0) +} + +/** + * @description 更新机器人阵亡情况 + * @param {number} bossHp + * @param {RoleStatus} roleSt + */ +function updateRobotKilled(bossHp: number, roleSt: RoleStatus) { + const robotTotalHurt = bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; + // 让阵亡人数和打出伤害的进度同步,比如有 5 个武将,每打出目标总伤害的 1 / 5 应该增加一个阵亡武将 + const dmgProgress = Math.floor(roleSt.totalDmg / (robotTotalHurt / roleSt.heroes.length)); + if (dmgProgress > roleSt.killed.length && dmgProgress <= roleSt.heroes.length) { + const newKilledCnt = dmgProgress - roleSt.killed.length; + const aliveHeroes = roleSt.heroes.filter(hero => { + return roleSt.killed.indexOf(hero.id) == -1; + }).map(cur => cur.id); + const newKilledHeroes = getRandEelm(aliveHeroes, newKilledCnt); + roleSt.killed = roleSt.killed.concat(newKilledHeroes); + } +} + +export async function handleComBtlProgress(teamStatus: MemComBtlTeam) { + const { teamCode } = teamStatus; + // 判断战斗是否结束 + let battleSt = checkComBattleResult(teamStatus); + teamStatus.status = battleSt; + if (battleSt === COM_TEAM_STATUS.WIN || battleSt === COM_TEAM_STATUS.LOOSE) { + let result = battleSt === COM_TEAM_STATUS.WIN; + if (result) { + teamStatus.bossHpArr.forEach(bs => { + bs.curHp = 0; + }); + for (let st of teamStatus.roleStatus) { + st.rewards = await getRealReward(teamStatus.blueprtId, teamStatus.roleStatus, st, teamStatus.hasTimeExtraReward); + }; + await checkTaskInComBattleEnd(teamStatus.roleStatus, teamStatus.capId); + } + let team = await ComBattleTeamModel.syncTeamData({ teamCode, status: battleSt, roleStatus: teamStatus.roleStatus, bossHpArr: teamStatus.bossHpArr, endTime: teamStatus.endTime }); + if (!team) return resResult(STATUS.COM_BATTLE_RESULT_ERR); + + // 战斗胜利队长扣减藏宝图 + if (result && teamStatus.capId != 'robot') { + let res = await handleCost(teamStatus.capId, teamStatus.sid, [{ id: teamStatus.blueprtId, count: 1 }], ITEM_CHANGE_REASON.COM_BATTLE_USE_BLUEPRT); + if (res === false) return resResult(STATUS.COM_BATTLE_BLUEPRT_NOT_ENOUGH); + } + + clearRobotHurtTimer(teamStatus); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result }); + + deleteComBattle(teamCode); + clearComBattleRoute(redisClient(), teamCode); + } +} + +/** + * @description 更新机器人对 boss 的伤害 + * @export + * @param {*} teamStatus 要更新的队伍信息 + * @param {RoleStatus} roleSt 要更新的玩家信息 + */ +export function updateRobotHurt(teamStatus: MemComBtlTeam, roleSt: RoleStatus) { + // 机器人的伤害为:boss 血量的一定比例,平均到一定回合数内,再平均到每个敌军,上下浮动一定比例 + let eachHurtHp = robotEachHurt(teamStatus.bossHp, teamStatus.bossHpArr.length); + let robotTotalHurt = 0; + let actBossHurts = []; + let hero = getRandSingleEelm(roleSt.heroes); + for (let boss of teamStatus.bossHpArr) { + if (boss.curHp === 0) continue; + if (boss.curHp >= eachHurtHp) { + actBossHurts.push({ dataId: boss.dataId, hurtHp: eachHurtHp }); + robotTotalHurt += eachHurtHp; + boss.curHp -= eachHurtHp; + hero.addDamage(eachHurtHp); + } else if (boss.curHp > 0) { // 丢弃溢出的伤害 + actBossHurts.push({ dataId: boss.dataId, hurtHp: boss.curHp }); + robotTotalHurt += boss.curHp; + hero.addDamage(boss.curHp); + boss.curHp = 0; + } + break; + } + teamStatus.bossCurHp -= robotTotalHurt; + roleSt.totalDmg += robotTotalHurt; + updateRobotKilled(teamStatus.bossHp, roleSt); + sendMessageToTeam(teamStatus.teamCode, PUSH_ROUTE.TEAMMATE_ACT, { teamCode: teamStatus.teamCode, bossCurHp: teamStatus.bossCurHp, bossHpArr: teamStatus.bossHpArr, roleStatus: teamStatus.roleStatus, actRoleId: roleSt.roleId, actBossHurts }); +} + +/** + * @description 按一定时间间隔刷新机器人伤害 + * @export + * @param {*} teamStatus + * @param {RoleStatus} roleSt + * @param {number} interval + * @param {Channel} channel + */ +export function updateRobotHurtByTime(teamStatus: MemComBtlTeam, roleSt: RoleStatus, interval: number) { + const robotTimer = setInterval(() => { + const robotTotalHurt = teamStatus.bossHp * COM_BTL_CONST.ROBOT_HURT_RATIO; + let team = getComTeamByCode(teamStatus.teamCode); + if (roleSt.totalDmg < robotTotalHurt && teamStatus.bossCurHp > 0 && team) { + updateRobotHurt(teamStatus, roleSt); + handleComBtlProgress(teamStatus); + } else { + clearInterval(robotTimer); + } + }, interval * 1000); + setRobotHurtTimerIfNotExist(teamStatus.teamCode, roleSt.roleId, robotTimer); +} + +/** + * @description 清理机器人伤害的 timer + * @export + * @param {MemComBtlTeam} teamStatus 寻宝队伍状态 + */ +export function clearRobotHurtTimer(teamStatus: { teamCode: string, roleStatus: RoleStatus[] }) { + teamStatus.roleStatus.forEach(st => { + let robotHurtTimer = getRobotHurtTimer(teamStatus.teamCode, st.roleId); + if (st.isRobot === true && robotHurtTimer) { + clearInterval(robotHurtTimer); + } + }); +} + +/** + * @description 检查寻宝等级是否合法 + * @export + * @param {number} playerLv 玩家等级 + * @param {number} blueprtLv 藏宝图等级 + * @returns + */ +export function comBtlLvInvalid(playerLv: number, blueprtLvs: number[]) { + for(let blueprtLv of blueprtLvs) { + const range = gameData.comBtlLvRange.get(blueprtLv); + if (!range) return true; + let { min, max } = range; + if(playerLv < min || playerLv > max) return true; + } + return false +} + +export function getComBtlLvByPlayerLv(playerLv: number) { + let lvs: number[] = []; + for(let [lv, {min, max}] of gameData.comBtlLvRange) { + if(playerLv >= min && playerLv <= max) lvs.push(lv); + } + let minLv = Math.min(...lvs); + let maxLv = Math.max(...lvs); + return { minLv, maxLv } +} + +export async function dismissTeam(teamStatus: MemComBtlTeam, roleId: string) { + const { teamCode } = teamStatus; + if (!teamStatus || !teamStatus.roleIds || teamStatus.roleIds.indexOf(roleId) === -1) return resResult(STATUS.COM_BATTLE_TEAM_INVALID); + if (teamStatus.status !== COM_TEAM_STATUS.DEFAULT) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); + if (roleId !== teamStatus.capId) return resResult(STATUS.COM_BATTLE_CAP_ONLY); + + let team = await ComBattleTeamModel.removeTeam(teamCode); + if (!team) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); + + let rmSt = deleteComBattle(teamCode); + if (!rmSt) return resResult(STATUS.COM_BATTLE_DISSMISS_ERR); + clearComBattleRoute(redisClient(), teamCode); + + rmCreatedTeamFromRedis(teamCode, teamStatus.lv); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_DISMISS, { teamCode }); + delTeamChannel(teamCode); + clearComBtlTimer(teamCode); // 队伍解散停止解散计时 + return resResult(STATUS.SUCCESS); +} + +export function setDismissTimer(teamStatus: MemComBtlTeam, roleId: string) { + // if (teamIsFullToStart(teamStatus)) { + clearComBtlTimer(teamStatus.teamCode); + let timer = setTimeout(async () => { + await dismissTeam(teamStatus, roleId); + }, COM_BTL_CONST.CAP_START_TIME); + setComTeamTimer(teamStatus.teamCode, timer);; + // } +} + +/** + * 按照好友关系,新增加成 + * + * @param {RoleStatus[]} roleStatus 队伍内的所有队友 + */ +export async function getComBattleFriendAdd(roleStatus: RoleStatus[]) { + let hasAdd: string[] = []; //roleIds + for (let myRoleStatus of roleStatus) { + for (let rs of roleStatus) { + if (myRoleStatus.roleId == rs.roleId) continue; + if (myRoleStatus.isRobot || rs.isRobot) continue; + + let { roleIds } = getRoleIds([myRoleStatus.roleId, rs.roleId]); + if (hasAdd.includes(roleIds)) continue; + + let add = await getFriendLvAdd(myRoleStatus.roleId, rs.roleId); + rs.addFrdRatio(add); + myRoleStatus.addFrdRatio(add); + + hasAdd.push(roleIds); + } + } +} + +/** + * @description 检查玩家是否符合加入队伍的条件 + * @param {Partial} roleInfo 要加入玩家的信息 + * @param {string} roleId 要加入玩家的 id + * @param {string[]} roleIds 队伍中当前玩家列表 + * @param {number} ceLimit + * @returns + */ +async function teammateValid(roleInfo: Partial, roleId: string, roleIds: string[], ceLimit: number) { + if (!roleInfo || roleIds.indexOf(roleId) !== -1) return false; + + const isBlack = await teammateInBlackList(roleId, roleIds); + if (isBlack) return false; + + let { topLineupCe } = roleInfo; + if (topLineupCe < ceLimit) return false; + + return true; +} + +/** + * @description 将用户信息转换成寻宝组队所需的 RoleStatus + * @export + * @param {string} roleId 要加入玩家的信息 + * @param {string[]} roleIds 队伍中当前玩家列表 + * @param {number} ceLimit + * @returns + */ +export async function getValidTeammateRoleSt(roleId: string, roleIds: string[], ceLimit: number, sid: string) { + let roleInfo = await RoleModel.findByRoleId(roleId, null, true); + + const valid = await teammateValid(roleInfo, roleId, roleIds, ceLimit); + if (!valid) return null; + + let isFrd = await getFrd(roleId); + const result = new RoleStatus(roleInfo, sid, false, isFrd); + return result; +} + +/** + * @description 检查队伍中是否有人互为黑名单 + * @export + * @param {string} roleId 要加入队伍的玩家 id + * @param {string[]} roleIds 队伍中已有的玩家 id + * @returns + */ +export async function teammateInBlackList(roleId: string, roleIds: string[]) { + for (let teammateRoleId of roleIds) { + const isBlack = await FriendRelationModel.isInBlackList(roleId, teammateRoleId); + if (isBlack === true) return true; + } + return false; +} + +export function blueprtIdValid(id: number) { + return gameData.blueprt.has(id); +} + +/** + * @description 检查是否有足够的藏宝图,未结束的战斗也占用一张藏宝图 + * @export + * @param {string} roleId + * @param {number} blueprtId + * @returns + */ +export async function hasEnoughBlueprt(roleId: string, sid: string, blueprtId: number) { + let blueprt = await ItemModel.findbyRoleAndGidAndCount(roleId, blueprtId, 1); + if (!blueprt || blueprt.count <= 0) return false; + // 检查是否有已创建未结束的寻宝,预先占用一张藏宝图 + // // 背包中占用的藏宝图不显示,所以这里就扣掉,结束再加回去 + // let result = await handleCost(roleId, sid, [{ id: blueprtId, count: 1 }]); + // return result; + let teams = await ComBattleTeamModel.getBlueprtInUse(roleId, COM_TEAM_STATUS.FIGHTING, blueprtId); + console.log('hasEnoughBlueprt', blueprt.count, teams.length) + if (teams && blueprt.count <= teams.length) return false; + return true +} + +/** + * @description 将玩家加入到队伍数据结构中,需将玩家信息做转化 + * @export + * @param {MemComBtlTeam} comTeam 队伍数据结构 + * @param {RoleType} roleInfo 原始玩家信息 + * @param {boolean} isCap + * @param {boolean} isFrd + */ +export function addRoleToTeam(comTeam: MemComBtlTeam, roleInfo: RoleType, sid: string, isCap: boolean, isFrd: boolean) { + const roleSt = new RoleStatus(roleInfo, sid, isCap, isFrd); + addRoleStToTeam(comTeam, roleSt); +} + +/** + * @description 将玩家加入到队伍数据结构中 + * @export + * @param {MemComBtlTeam} comTeam 队伍数据结构 + * @param {RoleStatus} roleSt 要加入的玩家数据 + */ +export function addRoleStToTeam(comTeam: MemComBtlTeam, roleSt: RoleStatus) { + const { roleStatus = [], roleIds = [] } = comTeam; + comTeam.roleStatus = [roleSt, ...roleStatus]; + comTeam.roleIds = [roleSt.roleId, ...roleIds]; + + if(!validToJoin(comTeam)) { // 无人可匹配时,删除存在redis中的匹配信息 + rmCreatedTeamFromRedis(comTeam.teamCode, comTeam.lv); + } +} + +/** + * @description 将符合要求的用户匹配到队伍中 + * @export + * @param {MemComBtlTeam} comTeam 队伍数据 + * @param {string} sid 当前用户 sid + * @returns + */ +export async function addValidSearchingRoles(comTeam: MemComBtlTeam) { + const { lv } = getDicBlueprtById(comTeam.blueprtId); + let teammates = await getTeamSearchByLv(lv); + if (teammates && teammates.length) { + for (let teammate of teammates) { + const { roleId: teammateRoleId, sid } = teammate; + const st = await getValidTeammateRoleSt(teammateRoleId, comTeam.roleIds, comTeam.ceLimit, sid); + if (!st) continue; + await rmRoleFromQueue(teammateRoleId, sid); // 匹配成功后删除redis中该用户的匹配记录 + addRoleStToTeam(comTeam, st); + addUserToTeamChannel(comTeam.teamCode, false, teammateRoleId, sid); + } + sendMessageToUsersWithSuc(PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }, teammates.map(t => { return { uid: t.roleId, sid: t.sid } })); + } +} + +export async function addToSearchingTeams(roleId: string, sid: string, lvs: number[]) { + let teamCodes = await getCreatedTeamByLv(lvs); + if(teamCodes.length <= 0) return false; + + let {lv, teamCode} = getRandSingleEelm(teamCodes); + let battleServer = await getComTeamSidByCode(lv, teamCode); + if(!battleServer) return false; + + return await pinus.app.rpc.comBattle.comBattleRemote.addToSearchingTeams.toServer(battleServer, teamCode, roleId, sid); +} + +export async function _addToSearchingTeams(teamCode: string, roleId: string, sid: string) { + let teamMap = pinus.app.get('teamMap'); + let teamStatus: MemComBtlTeam = teamMap && teamMap.get(teamCode); + if(!teamStatus) return false; + if(!validToJoin(teamStatus, roleId)) return false; + const st = await getValidTeammateRoleSt(roleId, teamStatus.roleIds, teamStatus.ceLimit, sid); + if (!st) return false; + + addRoleStToTeam(teamStatus, st); + await rmRoleFromQueue(roleId, sid); // 匹配成功后删除redis中该用户的匹配记录 + addUserToTeamChannel(teamCode, false, roleId, sid); + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: teamStatus }); + await ComBattleTeamModel.addRole(teamCode, st); +} + +/** + * @description 判断队伍是否处于可加入状态 + * @export + * @param {MemComBtlTeam} comTeam + * @param {string} [roleId=''] 要加入的玩家 id + * @returns + */ +export function validToJoin(comTeam: MemComBtlTeam, roleId = '') { + return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length < 3 && comTeam.roleIds.indexOf(roleId) === -1; +} + +/** + * @description 判断队伍是否处于可满员状态 + * @export + * @param {MemComBtlTeam} comTeam + * @returns + */ +export function teamIsFullToStart(comTeam: MemComBtlTeam) { + return comTeam && comTeam.roleIds && comTeam.status === COM_TEAM_STATUS.DEFAULT && comTeam.roleIds.length === 3; +} + +/** + * @description 添加指定数量的机器人到队伍 + * @export + * @param {MemComBtlTeam} comTeam + * @param {number} roleCe 真实玩家战力,用来做机器人战力基准 + * @param {number} roleLv 真实玩家等级,用来做机器人等级基准 + * @param {number} [count=1] + */ +export async function addRobotsToTeam(comTeam: MemComBtlTeam, roleId: string, roleCe: number, roleLv: number, count = 1) { + const { teamCode, roleStatus } = comTeam; + let hasCap = roleStatus.findIndex(cur => cur.isCap) != -1; + const { robotStArr, robotIdArr } = getRandComBtlRobots(roleCe, comTeam.ceLimit, roleLv, count); + for (let st of robotStArr) { + if(!hasCap) { + st.isCap = true; + hasCap = true; + } + addRoleStToTeam(comTeam, st); + await ComBattleTeamModel.addRole(teamCode, st); + } + sendMessageToTeam(teamCode, PUSH_ROUTE.TEAM_JOIN, { teamInfo: comTeam }) + setDismissTimer(comTeam, roleId); +} + +/** + * @description 在不同的时间加入机器人 + * @export + * @param {MemComBtlTeam} comTeam + * @param {RoleType} roleInfo + * @param {Map} teamMap + * @param {Map} teamDisTimer + */ +export async function addRobotsLater(comTeam: MemComBtlTeam, roleInfo: RoleType) { + const teamStatus = comTeam; + const { teamCode, lv: blueprtLv } = teamStatus; + const { roleId, lv } = roleInfo; + let { topLineupCe = 1000 } = roleInfo; + + if (validToJoin(teamStatus)) { // 如果可以匹配 + await setCreatedTeamToRedis(teamCode, blueprtLv); + + const robotCnt = 3 - teamStatus.roleIds.length; + for (let robotIdx = 0; robotIdx < robotCnt; robotIdx++) { + const joinTime = getRandValueByMinMax(COM_BTL_CONST.MIN_CAP_TIME, COM_BTL_CONST.MAX_CAP_TIME, 0); + setTimeout(async () => { + const curTeamStatus = getComTeamByCode(teamCode); + if (validToJoin(curTeamStatus)) { + await addRobotsToTeam(curTeamStatus, roleId, topLineupCe, lv, 1); + } + }, joinTime); + } + } +} + +/** + * @description 从数组里找出第一个不在黑名单的队伍 + * @export + * @param {ComBattleTeamType[]} teams 队伍数组 + * @param {string} roleId 要加入的玩家 id + * @returns + */ +export async function oneTeamNotInBlack(teams: ComBattleTeamType[], roleId: string) { + for (let team of teams) { + let { roleIds } = team; + const inBlackList = await teammateInBlackList(roleId, roleIds); + if (!inBlackList) { + return team; + } + } + return null; +} + +// export async function setComBtlOnUserLeave(roleId: string, teamCode: string) { +// let res = dispatch(teamCode, pinus.app.getServersByType('battle'), 'battle'); +// await pinus.app.rpc.battle.comBattleRemote.leaveFromBattle.toServer(res.id, roleId, teamCode); +// } + +export async function checkHasMyTeam(roleId: string) { + return await ComBattleTeamModel.checkHasTeamByRoleId(roleId); +} + +export async function checkTeamStatusAndSend(teamCode: string, roleId: string, sid: string) { + let team = await ComBattleTeamModel.getTeamByCode(teamCode); + if(team && (team.status == 2|| team.status == 3)) { + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TEAM_COMPLETE, { teamCode, result: team.status == 2? true: false, timeout: team.timeout }, sid); + } +} + +export async function startTeam(team: MemComBtlTeam) { + team.status = COM_TEAM_STATUS.FIGHTING; + team.startTime = nowSeconds(); + team.endTime = nowSeconds() + COM_BTL_CONST.BTL_TIME_LMT/1000; + team.hasTimeExtraReward = isComBattleTimeLimit(); +} diff --git a/game-server/app/services/battle/rougeCollectService.ts b/game-server/app/services/battle/rougeCollectService.ts index 53a069c47..8419cce0f 100644 --- a/game-server/app/services/battle/rougeCollectService.ts +++ b/game-server/app/services/battle/rougeCollectService.ts @@ -1,209 +1,209 @@ -import { RougelikeRecordDetailType } from '../../db/RougelikeRecordDetail'; -import { COLLECTION_TYPE, PUSH_ROUTE, ROUGE_LIKE_CARD_TYPE, TASK_ROUGE_CARD_TYPE, TASK_TYPE } from '../../consts'; -import { genCode } from '../../pubUtils/util'; -import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from '../../db/RougelikeChara'; -import { RougelikeCardPara, RougelikeCardModel } from '../../db/RougelikeCard'; -import { CommonCard, CommonChara } from '../../pubUtils/interface'; -import { RougelikeCollectionModel } from '../../db/RougelikeCollection'; -import { sendMessageToUserWithSuc } from '../pushService'; -import { gameData } from '../../pubUtils/data'; -import { clone } from 'underscore'; -import { RougeEffect, getSlotUnlockPoint } from './rougeEffectService'; -import { BackendSession } from 'pinus'; -import { checkTask } from '../task/taskService'; -import { RougelikeRecordModel } from '../../db/RougelikeRecord'; -import { updateMaxHp } from './rougeService'; - -export class HandleAddCard { - roleId: string; - sid: string; - serverId: number; - gameCode: string; - getLayer: number = 0; - getWay: number = 0; - addCharas: RougelikeCharaPara[] = []; // 需要更新的角色 - addPassiveCards: RougelikeCardPara[] = []; // 需要更新的特性卡 - addHolyCards: RougelikeCardPara[] = []; // 需要更新的圣物 - addCoin: number = 0; // 需要增加的试炼币 - - constructor(session: BackendSession, gameCode: string, recordDetail?: RougelikeRecordDetailType) { - this.roleId = session.get('roleId'); - this.sid = session.get('sid'); - this.serverId = session.get('serverId'); - this.gameCode = gameCode; - if (recordDetail) { - this.getLayer = recordDetail.layer; - this.getWay = recordDetail.nodeType; - } - } - - private getCommonParam() { - let { roleId, gameCode, getLayer, getWay } = this; - return { roleId, gameCode, getLayer, getWay }; - } - - public pushChara(id: number, maxHp: number, passiveCardIds: number[]) { - let cards: Card[] = []; - for (let index = 0; index < passiveCardIds.length; index++) { - let cardId = passiveCardIds[index]; - let cardCode = this.pushPassiveCard(cardId, id); - cards.push({ index, cardCode, cardId }); - } - let charaCode = genCode(8); - this.addCharas.push({ ...this.getCommonParam(), cards, charaCode, charaId: id, maxHp, hp: maxHp, ap: 0, shield: 0, others: '', roundSkill: 0, apSkill: 0 }); - return charaCode; - } - - public pushCard(id: number, rewardType: ROUGE_LIKE_CARD_TYPE, charaId: number = 0) { - if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE) { - return this.pushPassiveCard(id, charaId); - } else if (rewardType == ROUGE_LIKE_CARD_TYPE.HOLY) { - return this.pushHolyCard(id); - } - } - - public pushPassiveCard(id: number, charaId: number = 0) { - let cardCode = genCode(8); - this.addPassiveCards.push({ - ...this.getCommonParam(), cardCode, cardId: id, type: ROUGE_LIKE_CARD_TYPE.PASSIVE, lv: gameData.rougePassiveCard.get(id)?.lv || 0, charaId - }); - return cardCode - } - - public pushHolyCards(ids: number[]) { - for (let id of ids) this.pushHolyCard(id); - } - - public pushHolyCard(id: number) { - let cardCode = genCode(8); - this.addHolyCards.push({ - ...this.getCommonParam(), cardCode, cardId: id, type: ROUGE_LIKE_CARD_TYPE.HOLY, useCount: 0 - }); - return cardCode - } - - private getHolyUseCount(holyId: number) { - const holyCardData = gameData.rougeHolyCard.get(holyId); - return holyCardData?.useCount || 0; - } - - public async save() { - let result: { addCharas?: CommonChara[], addCards?: CommonCard[] } = {}; - if (this.addCharas.length > 0) { - let updateParams = this.addCharas || []; - let resultArrs = await RougelikeCharaModel.createCharas(updateParams); - this.addCharas = resultArrs; - result.addCharas = resultArrs.map(param => new CommonChara(param)); - } - if (this.addPassiveCards.length > 0 || this.addHolyCards.length > 0) { - let updateParams = [...(this.addPassiveCards || []), ...(this.addHolyCards || [])]; - // await RougelikeCardModel.bulkWriteUpdate(updateParams); - updateParams.map(async param => { - const { gameCode, cardCode } = param; - await RougelikeCardModel.updateByCode(gameCode, cardCode, { $set: param }) - }); - result.addCards = updateParams.map(param => new CommonCard(param)); - } - let collections: { type: number, id: number, addNum?: number }[] = []; - for (let { cardId, type } of result.addCards || []) { - if (type == ROUGE_LIKE_CARD_TYPE.PASSIVE) { - collections.push({ type: COLLECTION_TYPE.PASSIVE_CARD, id: cardId }); - } - if (type == ROUGE_LIKE_CARD_TYPE.HOLY) collections.push({ type: COLLECTION_TYPE.HOLY_CARD, id: cardId }); - } - if (collections.length > 0) await addCollection(this.roleId, this.sid, this.gameCode, collections); - - //任务 - if (this.addPassiveCards.length > 0) { - let passiveCardMap = new Map(); - for (const { cardId } of this.addPassiveCards) { - const passiveCardData = gameData.rougePassiveCard.get(cardId); - let count = passiveCardMap.get(passiveCardData.authorType) || 0; - passiveCardMap.set(passiveCardData.authorType, count + 1); - } - for (const [authorType, count] of passiveCardMap) { - await checkTask(this.serverId, this.roleId, this.sid, TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT, { authorType, cardType: TASK_ROUGE_CARD_TYPE.PASSIVE, cardIds: this.addPassiveCards.map(cur => cur.cardId) }); - } - } - if (this.addHolyCards.length > 0) { - await checkTask(this.serverId, this.roleId, this.sid, TASK_TYPE.ROUGE_HOLY_COLLECT, { cardIds: this.addHolyCards.map(cur => cur.cardId) }); - } - - if (this.addCharas.length > 0) { - result.addCharas = await this.getCharasByHolyEffect(); - } - - return result; - } - - // 处理获得角色卡时拥有圣物效果 - public async getCharasByHolyEffect() { - let result = await getSlotUnlockPoint(this.roleId, this.gameCode, this.addCharas || []); - this.addCharas = result.dbCharas; - if (result.isUpdate) { - await RougelikeCharaModel.bulkWriteUpdate(this.addCharas || []); - } - return this.addCharas.map(param => new CommonChara(param)); - } - - // 处理圣物效果 - public async getHolyEffect() { - let result: { addCharas?: CommonChara[], addCards?: CommonCard[] } = {}; - let charasMap = (this.addCharas || []).reduce((result, cur) => { result.set(cur.charaCode, cur); return result; }, new Map()); - let cardsMap = [...(this.addPassiveCards || []), ...(this.addHolyCards || [])].reduce((result, cur) => { result.set(cur.cardCode, cur); return result; }, new Map()); - if ((this.addHolyCards || []).length > 0) { - let rougeEffect = new RougeEffect(this.roleId, this.gameCode, this.sid); - let holyIds = clone(this.addHolyCards.map(cur => { return { cardCode: cur.cardCode, cardId: cur.cardId, useCount: cur.useCount } })); - - let { charas, cards } = await rougeEffect.getEffectImmediate(holyIds); - if (charas && charas.size > 0) { - await RougelikeCharaModel.bulkWriteUpdate([...charas.values()]); - charasMap = new Map([...charasMap, ...charas]) - } - if (cards && cards.size > 0) { - await RougelikeCardModel.bulkWriteUpdate([...cards.values()]) - cardsMap = new Map([...cardsMap, ...cards]) - } - } - result.addCharas = [...charasMap.values()].map(param => new CommonChara(param)); - result.addCards = [...cardsMap.values()].map(param => new CommonCard(param)); - - const dbRecord = await RougelikeRecordModel.findByGameCode(this.gameCode); - result.addCharas = await updateMaxHp(this.roleId, this.gameCode, (dbRecord?.type || 0), (dbRecord?.grade || 0), charasMap) - return result; - } -} - -export function formateCharasOrCards(params: RougelikeCharaPara[] | RougelikeCardPara[], type: number) { - let result: { charas?: CommonChara[], cards?: CommonCard[] } = {}; - if (!params || params.length == 0) return result; - const updateParams = params || []; - if (type == ROUGE_LIKE_CARD_TYPE.CHARA) result.charas = updateParams.map(param => new CommonChara(param)); - else result.cards = updateParams.map(param => new CommonCard(param)).filter(cur => cur.cardId > 0); - return result; -} - -export async function addCollection(roleId: string, sid: string, gameCode: string, arr: { type: number, id: number, addNum?: number }[]) { - let collections: { type: number, id: number, num: number }[] = [], passiveCnt = 0; - for (let { type, id, addNum = 1 } of arr) { - if (type == COLLECTION_TYPE.PASSIVE_CARD_SUM || id == 0) continue; - let collection = await RougelikeCollectionModel.addRec(roleId, type, id, gameCode, addNum); - if (!collection || collection.num > 1) continue; - if (type == COLLECTION_TYPE.PASSIVE_CARD && collection.num == 1) passiveCnt++; - collections.push({ type, id, num: collection.num }); - } - if (passiveCnt > 0) { - let collection = await RougelikeCollectionModel.addRec(roleId, COLLECTION_TYPE.PASSIVE_CARD_SUM, 0, gameCode, passiveCnt); - collections.push({ type: COLLECTION_TYPE.PASSIVE_CARD, id: 0, num: collection.num }); - } - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ROUGE_COLLECT_UPDATE, { collections }, sid); - return collections; -} - -export async function addSingleCollect(roleId: string, sid: string, gameCode: string, type: number, id: number) { - return await addCollection(roleId, sid, gameCode, [{ type, id }]); -} - -export async function addSameTypeCollect(roleId: string, sid: string, gameCode: string, type: number, ids: number[]) { - return await addCollection(roleId, sid, gameCode, ids.map(id => ({ type, id }))); -} \ No newline at end of file +import { RougelikeRecordDetailType } from '@db/RougelikeRecordDetail'; +import { COLLECTION_TYPE, PUSH_ROUTE, ROUGE_LIKE_CARD_TYPE, TASK_ROUGE_CARD_TYPE, TASK_TYPE } from '@consts'; +import { genCode } from '@pubUtils/util'; +import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from '@db/RougelikeChara'; +import { RougelikeCardPara, RougelikeCardModel } from '@db/RougelikeCard'; +import { CommonCard, CommonChara } from '@pubUtils/interface'; +import { RougelikeCollectionModel } from '@db/RougelikeCollection'; +import { sendMessageToUserWithSuc } from '../pushService'; +import { gameData } from '@pubUtils/data'; +import { clone } from 'underscore'; +import { RougeEffect, getSlotUnlockPoint } from './rougeEffectService'; +import { BackendSession } from 'pinus'; +import { checkTask } from '../task/taskService'; +import { RougelikeRecordModel } from '@db/RougelikeRecord'; +import { updateMaxHp } from './rougeService'; + +export class HandleAddCard { + roleId: string; + sid: string; + serverId: number; + gameCode: string; + getLayer: number = 0; + getWay: number = 0; + addCharas: RougelikeCharaPara[] = []; // 需要更新的角色 + addPassiveCards: RougelikeCardPara[] = []; // 需要更新的特性卡 + addHolyCards: RougelikeCardPara[] = []; // 需要更新的圣物 + addCoin: number = 0; // 需要增加的试炼币 + + constructor(session: BackendSession, gameCode: string, recordDetail?: RougelikeRecordDetailType) { + this.roleId = session.get('roleId'); + this.sid = session.get('sid'); + this.serverId = session.get('serverId'); + this.gameCode = gameCode; + if (recordDetail) { + this.getLayer = recordDetail.layer; + this.getWay = recordDetail.nodeType; + } + } + + private getCommonParam() { + let { roleId, gameCode, getLayer, getWay } = this; + return { roleId, gameCode, getLayer, getWay }; + } + + public pushChara(id: number, maxHp: number, passiveCardIds: number[]) { + let cards: Card[] = []; + for (let index = 0; index < passiveCardIds.length; index++) { + let cardId = passiveCardIds[index]; + let cardCode = this.pushPassiveCard(cardId, id); + cards.push({ index, cardCode, cardId }); + } + let charaCode = genCode(8); + this.addCharas.push({ ...this.getCommonParam(), cards, charaCode, charaId: id, maxHp, hp: maxHp, ap: 0, shield: 0, others: '', roundSkill: 0, apSkill: 0 }); + return charaCode; + } + + public pushCard(id: number, rewardType: ROUGE_LIKE_CARD_TYPE, charaId: number = 0) { + if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE) { + return this.pushPassiveCard(id, charaId); + } else if (rewardType == ROUGE_LIKE_CARD_TYPE.HOLY) { + return this.pushHolyCard(id); + } + } + + public pushPassiveCard(id: number, charaId: number = 0) { + let cardCode = genCode(8); + this.addPassiveCards.push({ + ...this.getCommonParam(), cardCode, cardId: id, type: ROUGE_LIKE_CARD_TYPE.PASSIVE, lv: gameData.rougePassiveCard.get(id)?.lv || 0, charaId + }); + return cardCode + } + + public pushHolyCards(ids: number[]) { + for (let id of ids) this.pushHolyCard(id); + } + + public pushHolyCard(id: number) { + let cardCode = genCode(8); + this.addHolyCards.push({ + ...this.getCommonParam(), cardCode, cardId: id, type: ROUGE_LIKE_CARD_TYPE.HOLY, useCount: 0 + }); + return cardCode + } + + private getHolyUseCount(holyId: number) { + const holyCardData = gameData.rougeHolyCard.get(holyId); + return holyCardData?.useCount || 0; + } + + public async save() { + let result: { addCharas?: CommonChara[], addCards?: CommonCard[] } = {}; + if (this.addCharas.length > 0) { + let updateParams = this.addCharas || []; + let resultArrs = await RougelikeCharaModel.createCharas(updateParams); + this.addCharas = resultArrs; + result.addCharas = resultArrs.map(param => new CommonChara(param)); + } + if (this.addPassiveCards.length > 0 || this.addHolyCards.length > 0) { + let updateParams = [...(this.addPassiveCards || []), ...(this.addHolyCards || [])]; + // await RougelikeCardModel.bulkWriteUpdate(updateParams); + updateParams.map(async param => { + const { gameCode, cardCode } = param; + await RougelikeCardModel.updateByCode(gameCode, cardCode, { $set: param }) + }); + result.addCards = updateParams.map(param => new CommonCard(param)); + } + let collections: { type: number, id: number, addNum?: number }[] = []; + for (let { cardId, type } of result.addCards || []) { + if (type == ROUGE_LIKE_CARD_TYPE.PASSIVE) { + collections.push({ type: COLLECTION_TYPE.PASSIVE_CARD, id: cardId }); + } + if (type == ROUGE_LIKE_CARD_TYPE.HOLY) collections.push({ type: COLLECTION_TYPE.HOLY_CARD, id: cardId }); + } + if (collections.length > 0) await addCollection(this.roleId, this.sid, this.gameCode, collections); + + //任务 + if (this.addPassiveCards.length > 0) { + let passiveCardMap = new Map(); + for (const { cardId } of this.addPassiveCards) { + const passiveCardData = gameData.rougePassiveCard.get(cardId); + let count = passiveCardMap.get(passiveCardData.authorType) || 0; + passiveCardMap.set(passiveCardData.authorType, count + 1); + } + for (const [authorType, count] of passiveCardMap) { + await checkTask(this.serverId, this.roleId, this.sid, TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT, { authorType, cardType: TASK_ROUGE_CARD_TYPE.PASSIVE, cardIds: this.addPassiveCards.map(cur => cur.cardId) }); + } + } + if (this.addHolyCards.length > 0) { + await checkTask(this.serverId, this.roleId, this.sid, TASK_TYPE.ROUGE_HOLY_COLLECT, { cardIds: this.addHolyCards.map(cur => cur.cardId) }); + } + + if (this.addCharas.length > 0) { + result.addCharas = await this.getCharasByHolyEffect(); + } + + return result; + } + + // 处理获得角色卡时拥有圣物效果 + public async getCharasByHolyEffect() { + let result = await getSlotUnlockPoint(this.roleId, this.gameCode, this.addCharas || []); + this.addCharas = result.dbCharas; + if (result.isUpdate) { + await RougelikeCharaModel.bulkWriteUpdate(this.addCharas || []); + } + return this.addCharas.map(param => new CommonChara(param)); + } + + // 处理圣物效果 + public async getHolyEffect() { + let result: { addCharas?: CommonChara[], addCards?: CommonCard[] } = {}; + let charasMap = (this.addCharas || []).reduce((result, cur) => { result.set(cur.charaCode, cur); return result; }, new Map()); + let cardsMap = [...(this.addPassiveCards || []), ...(this.addHolyCards || [])].reduce((result, cur) => { result.set(cur.cardCode, cur); return result; }, new Map()); + if ((this.addHolyCards || []).length > 0) { + let rougeEffect = new RougeEffect(this.roleId, this.gameCode, this.sid); + let holyIds = clone(this.addHolyCards.map(cur => { return { cardCode: cur.cardCode, cardId: cur.cardId, useCount: cur.useCount } })); + + let { charas, cards } = await rougeEffect.getEffectImmediate(holyIds); + if (charas && charas.size > 0) { + await RougelikeCharaModel.bulkWriteUpdate([...charas.values()]); + charasMap = new Map([...charasMap, ...charas]) + } + if (cards && cards.size > 0) { + await RougelikeCardModel.bulkWriteUpdate([...cards.values()]) + cardsMap = new Map([...cardsMap, ...cards]) + } + } + result.addCharas = [...charasMap.values()].map(param => new CommonChara(param)); + result.addCards = [...cardsMap.values()].map(param => new CommonCard(param)); + + const dbRecord = await RougelikeRecordModel.findByGameCode(this.gameCode); + result.addCharas = await updateMaxHp(this.roleId, this.gameCode, (dbRecord?.type || 0), (dbRecord?.grade || 0), charasMap) + return result; + } +} + +export function formateCharasOrCards(params: RougelikeCharaPara[] | RougelikeCardPara[], type: number) { + let result: { charas?: CommonChara[], cards?: CommonCard[] } = {}; + if (!params || params.length == 0) return result; + const updateParams = params || []; + if (type == ROUGE_LIKE_CARD_TYPE.CHARA) result.charas = updateParams.map(param => new CommonChara(param)); + else result.cards = updateParams.map(param => new CommonCard(param)).filter(cur => cur.cardId > 0); + return result; +} + +export async function addCollection(roleId: string, sid: string, gameCode: string, arr: { type: number, id: number, addNum?: number }[]) { + let collections: { type: number, id: number, num: number }[] = [], passiveCnt = 0; + for (let { type, id, addNum = 1 } of arr) { + if (type == COLLECTION_TYPE.PASSIVE_CARD_SUM || id == 0) continue; + let collection = await RougelikeCollectionModel.addRec(roleId, type, id, gameCode, addNum); + if (!collection || collection.num > 1) continue; + if (type == COLLECTION_TYPE.PASSIVE_CARD && collection.num == 1) passiveCnt++; + collections.push({ type, id, num: collection.num }); + } + if (passiveCnt > 0) { + let collection = await RougelikeCollectionModel.addRec(roleId, COLLECTION_TYPE.PASSIVE_CARD_SUM, 0, gameCode, passiveCnt); + collections.push({ type: COLLECTION_TYPE.PASSIVE_CARD, id: 0, num: collection.num }); + } + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ROUGE_COLLECT_UPDATE, { collections }, sid); + return collections; +} + +export async function addSingleCollect(roleId: string, sid: string, gameCode: string, type: number, id: number) { + return await addCollection(roleId, sid, gameCode, [{ type, id }]); +} + +export async function addSameTypeCollect(roleId: string, sid: string, gameCode: string, type: number, ids: number[]) { + return await addCollection(roleId, sid, gameCode, ids.map(id => ({ type, id }))); +} diff --git a/game-server/app/services/battle/rougeEffectService.ts b/game-server/app/services/battle/rougeEffectService.ts index 8c8957d66..2251fb0c9 100644 --- a/game-server/app/services/battle/rougeEffectService.ts +++ b/game-server/app/services/battle/rougeEffectService.ts @@ -1,715 +1,715 @@ -import { ABI_TYPE } from "../../consts/constModules/abilityConst"; -import { PUSH_ROUTE, ROUGELIKE_SKILLTYPE, ROUGE_EFFECT_TYPE, ROUGE_EFFECT_TYPE_KIND, ROUGE_LIKE_CARD_TYPE, ROUGE_SLOT_LIMIT } from "../../consts"; -import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from "../../db/RougelikeCard"; -import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from "../../db/RougelikeChara"; -import { RougelikeRecordModel } from "../../db/RougelikeRecord"; -import { gameData, getRougeEffectTypeKind } from "../../pubUtils/data"; -import { DicRougePassiveCardPlan } from "../../pubUtils/dictionary/DicRougePassiveCardPlan"; -import { getRandEelm } from "../../pubUtils/util"; -import { RougelikeTechModel } from "../../db/RougelikeTech"; -import { getAuthorTypeCardNum } from "./rougeService"; -import * as util from 'util'; -import { DicRougePassiveCard } from "../../pubUtils/dictionary/DicRougePassiveCard"; -import { sendMessageToUserWithSuc } from "../pushService"; - - - -export class holyId { - cardCode: string; - cardId: number; - useCount: number; -} - - -export class RougeEffect { - roleId: string; - gameCode: string; - sid: string; - newEffect: { effectType: number, effectParam: number[], cardCode?: string }[] = []; - holyMap = new Map(); - updateHolyMap = new Map(); - updateCharaMap = new Map(); - updateCardMap = new Map(); - dbCharas: RougelikeCharaType[] = []; - dbCards: RougelikeCardType[] = []; - - constructor(roleId: string, gameCode: string, sid?: string) { - this.roleId = roleId || ''; - this.gameCode = gameCode || ''; - this.sid = sid || ''; - - } - - /** - * 根据类型获取effectId - * @param effectTypes - * @param holyIds - * @returns - */ - public async getEffectData(effectTypes: number[], holyIds?: holyId[]) { - let kinds = getRougeEffectTypeKind(effectTypes); - if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.HOLY)) { - if (!holyIds || holyIds.length == 0) { - const dbCards = await RougelikeCardModel.findByGameCodeAndType(this.gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); - holyIds = dbCards.map((cur) => { return { cardCode: cur.cardCode, cardId: cur.cardId, useCount: cur.useCount || 0 } }); - } - if (!holyIds || holyIds.length == 0) return { newEffect: this.newEffect, holyMap: this.holyMap }; - - for (const { cardCode, cardId, useCount } of holyIds) { - let effectIds = gameData.rougeHolyCard.get(cardId)?.effectId || []; - if (effectIds.length == 0) continue; - - for (const effectId of effectIds) { - const effectDataOne = gameData.rougeEffect.get(effectId); - if (!effectDataOne) continue; - const effectParam = effectDataOne.effectParam || []; - for (let effectType of effectTypes) { - if (effectType != effectDataOne.effectType || 0) continue; - this.newEffect.push({ effectType, effectParam, cardCode }); - this.holyMap.set(cardCode, { cardCode, cardId, useCount }) - } - } - } - } - - if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.TECH)) { - let tech = await RougelikeTechModel.findByRoleId(this.roleId, 'effectIds'); - for (let effectId of (tech?.effectIds || [])) { - const effectDataOne = gameData.rougeEffect.get(effectId); - if (!effectDataOne) continue; - for (let effectType of effectTypes) { - if (effectType != effectDataOne.effectType || 0) continue; - this.newEffect.push({ effectType, effectParam: effectDataOne.effectParam || [] }); - } - } - } - - return { newEffect: this.newEffect, holyMap: this.holyMap } - } - - /* ** - * 获取圣物时生效 - * @param gameCode - */ - public async getEffectImmediate(holyIds?: holyId[]) { - let result: { charas?: Map, cards?: Map } = {}; - this.dbCharas = await RougelikeCharaModel.findByGameCode(this.gameCode); - this.dbCards = await RougelikeCardModel.findByGameCode(this.gameCode); - - await this.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL, //2002 - ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND, //2003 - ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND, //2006 - ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV, //2012 - ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY, //2015 - ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 - ], holyIds) - - await this.getCharaSlot(); - - await this.getRandCharaSlot(); - - await this.getRandomCardLv() - - await this.getPassiveLv(); - - await this.getRecoveryHoly(); - - await this.getSlotUnlockPoint() - - result = { charas: this.updateCharaMap, cards: this.updateCardMap }; - - return result; - } - - - // 获得该圣物时,所有学员立刻解锁X个特性槽 2002 - private async getCharaSlot() { - if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL) continue; - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - for (let val of this.dbCharas) { - let { charaCode, cards = [] } = val; - let unlockNum = effectParam[0] || 0; - for (let i = 0; i < unlockNum; i++) { - unlockNum = effectParam[0] || 0; - if (cards.length >= ROUGE_SLOT_LIMIT) continue; - for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { - if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; - cards.push({ index, cardCode: '', cardId: 0 }); - this.updateCharaMap.set(charaCode, val); - unlockNum--; - isUseCount = true; - } - } - } - if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - } - - private updateHolyMapUseCount(holy: { cardCode: string, cardId: number, useCount: number }) { - let { cardCode, useCount = 0, cardId } = (holy || {}); - if (!cardId || !cardCode) return; - let val = this.dbCards.find(cur => cur.cardCode == cardCode); - if (val == undefined) return; - useCount = (useCount + 1) >= 0 ? (useCount + 1) : 0 - this.updateCardMap.set(cardCode, { ...val, useCount }); - this.holyMap.set(cardCode, { cardCode, cardId, useCount }); - } - - // 获得该圣物时,随机解锁X个学员的Y个特性槽 2003 - private async getRandCharaSlot() { - if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND) continue; - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const randomNum = effectParam[0] || 0; - let unlockNum = effectParam[1] || 0; - this.dbCharas.sort((a, b) => { - if (a.seqId < b.seqId) return -1; - if (a.seqId > b.seqId) return 1; - return 0; - }); - let charas = getRandEelm(this.dbCharas.slice(0, 6).filter(cur => cur.cards.length < ROUGE_SLOT_LIMIT), randomNum); - for (let val of charas) { - unlockNum = effectParam[1] || 0; - let { charaCode, cards = [] } = val; - for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { - if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; - cards.push({ index, cardCode: '', cardId: 0 }); - this.updateCharaMap.set(charaCode, val); - unlockNum--; - isUseCount = true; - } - } - if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - } - - // 随机升级X个已装备的特性 2006 - private async getRandomCardLv() { - if (this.newEffect.length == 0 || this.dbCards.length == 0) return; - let pushCards: RougelikeCardType[] = []; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND) continue; - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const randomNum = effectParam[0] || 0; - let random = this.dbCards.filter(cur => cur.type == ROUGE_LIKE_CARD_TYPE.PASSIVE && cur.charaId && cur.charaId != 0); - let newRandom: RougelikeCardType[] = []; - for (let cur of random) { - // if (cur.type != ROUGE_LIKE_CARD_TYPE.PASSIVE || cur.charaId == 0) continue; - let passiveCardDataMap = this.getPassiveData(cur.cardId); - if (!passiveCardDataMap.has(cur.lv + 1)) continue; - newRandom.push({ ...cur, cardId: passiveCardDataMap.get(cur.lv + 1).id, lv: cur.lv + 1 }); - } - - if (newRandom && newRandom.length > 0) { - let cards = getRandEelm(newRandom, randomNum); - cards.forEach(async cur => { this.updateCardMap.set(cur.cardCode, cur), await this.updateCharaCards(cur, cur.cardCode, cur.cardId); }); - pushCards.push(...cards); - - this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - } - if (pushCards.length > 0) { - await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); - } - } - - private getPassiveData(cardId: number) { - let passiveCardDataMap = new Map() - const passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData) return passiveCardDataMap; - const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0); - if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return passiveCardDataMap; - passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map()); - return passiveCardDataMap; - } - - // 获得该圣物时立即升级所有X星特性卡 2012 - private async getPassiveLv() { - if (this.newEffect.length == 0) return; - let pushCards: RougelikeCardType[] = []; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV) continue; - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const level = effectParam[0] || 0; - for (let val of this.dbCards) { - let { lv, cardId, cardCode } = val; - if (lv != level) continue; - let passiveCardDataMap = this.getPassiveData(cardId); - if (!passiveCardDataMap.has(lv + 1)) continue; - let id = passiveCardDataMap.get(lv + 1).id; - this.updateCardMap.set(cardCode, { ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); - pushCards.push({ ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); - - if (val.charaId && val.charaId > 0) { - await this.updateCharaCards(val, cardCode, id); - } - - isUseCount = true; - } - if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - if (pushCards.length > 0) { - await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); - } - } - - private async updateCharaCards(val: RougelikeCardType, cardCode: string, id: number) { - for (let obj of this.dbCharas) { - if (obj.charaId != val.charaId) continue; - for (let card of (obj.cards || [])) { - if (card.cardCode != cardCode) continue; - card.cardId = id; - } - this.updateCharaMap.set(obj.charaCode, obj); - } - } - - - // 获得该圣物时,随机修复X个已损毁的圣物 2015 - private async getRecoveryHoly() { - if (this.newEffect.length == 0) return; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY) continue; - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const num = effectParam[0] || 0; - let canRandomCards: RougelikeCardType[] = [] - this.dbCards.forEach(cur => { - const { cardCode, cardId, useCount = 0, type } = cur; - const holyCardData = gameData.rougeHolyCard.get(cardId); - let tempUseCount = holyCardData?.useCount || 0; - if (tempUseCount - useCount <= 0 && type == ROUGE_LIKE_CARD_TYPE.HOLY) canRandomCards.push(cur); - - }) - - let randomCards = getRandEelm(canRandomCards, num); - for (let val of randomCards) { - let { cardCode, cardId } = val; - val.useCount -= 1; - this.updateCardMap.set(cardCode, val); - - if (this.holyMap.has(cardCode)) this.holyMap.set(cardCode, { cardCode, cardId, useCount: val.useCount }); - isUseCount = true; - } - - if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - } - - //2023 - private async getSlotUnlockPoint() { - if (this.newEffect.length == 0) return; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT) continue; - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const num = effectParam[0] || 0; - const index = effectParam[0] || 0; - for (let val of this.dbCharas) { - let { cards = [], charaCode } = val - if (cards.find(cur => cur.index == index) == undefined) { - cards.push({ index, cardCode: '', cardId: 0 }); - this.updateCharaMap.set(charaCode, val); - isUseCount = true; - } - } - if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - } - - - // 和圣物相关maxhp - public async getEffectMaxHp() { - let addRatio = 0; - await this.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN, // 2005 - ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP, // 2020 - ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP, // 3001 - ]) - - addRatio = await this.getMaxHpByCoin(); - - addRatio += await this.getMaxHpByBase(); - - - await updateCards([...this.updateCardMap.values()]); - - return addRatio; - } - - // 每有X个试炼币,全员基础属性id提高Y 2005 - private async getMaxHpByCoin() { - let addRatio = 0; - const dbRecord = await RougelikeRecordModel.findByGameCode(this.gameCode); - let coinTotal = dbRecord?.coin || 0; - if (this.newEffect.length == 0) return addRatio; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN) continue; - if (effectParam.length == 0) continue; - const count = effectParam[0] || 0; - const id = effectParam[1] || 0; - const value = effectParam[2] || 0; - if (count == 0 || id != ABI_TYPE.ABI_HP || value == 0) continue; - addRatio += Math.floor(coinTotal / count * value) - - this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - - } - - return addRatio; - } - - // 基础属性Id&num 2020 - private async getMaxHpByBase() { - let addRatio = 0; - if (this.newEffect.length == 0) return addRatio; - for (const { effectParam, effectType, cardCode } of this.newEffect) { - if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP && effectType != ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP) continue; - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; - const id = effectParam[0] || 0; - const value = effectParam[1] || 0; - if (id != ABI_TYPE.ABI_HP || value == 0) continue; - addRatio += value; - this.updateHolyMapUseCount(this.holyMap.get(cardCode)); - } - return addRatio; - } -} - - -// 每场战斗结束后,学员恢复血量上限X%的生命 2001 -export async function getCharaHp(roleId: string, gameCode: string) { - let hpRatio = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_CHARA_HP_RECOVERY_UP,// 2001 - ]); - if (newEffect.length == 0) return hpRatio; - for (const { effectType, effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - hpRatio += (effectParam[0] || 0); - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } - return hpRatio; -} - - -// 战斗胜利后,获得的试炼币增加X 2004 -export async function getAddCoin(roleId: string, gameCode: string, nodeType: number) { - let coinRatio = 0, coinAdd = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_COIN_UP, //2004 - ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE, //3007 - ]); - if (newEffect.length == 0) return { coinRatio, coinAdd }; - for (const { effectType, effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - if (effectType == ROUGE_EFFECT_TYPE.HOLY_COIN_UP) { - const type = effectParam[0] || 0; - const value = effectParam[1] || 0; - if (type == 1) coinAdd += value; - else if (type == 2) coinRatio += value; - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } - if (effectType == ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE) { - let [value = 0, ...targetNodeType] = effectParam; - if (targetNodeType && targetNodeType.includes(nodeType)) coinRatio += value; - } - - } - return { coinRatio, coinAdd }; -} - - -// 获得圣物后,X流派特性卡的权重增加Y 2007 -export async function getAddPassiveWeight(roleId: string, gameCode: string, authorType: number) { - let addPassiveWeight = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_PASSIVE_WEIGHT_UP_BY_AUTHOR,//2007 - ]); - if (newEffect.length == 0) return addPassiveWeight; - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const type = effectParam[0] || 0; - const value = effectParam[1] || 0; - if (type != authorType) continue; - addPassiveWeight += value; - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } - return addPassiveWeight; -} - -// 2008 -export async function getEnterGame(roleId: string, gameCode: string) { - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_ENEMY_MAIN_ATTR_DOWN,//2008 - ]); - if (newEffect.length == 0) return; - for (const { effectParam, cardCode } of newEffect) { - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } -} - -// 非boss战斗失败视为胜利,并且满血复活 2009 -export async function getNoBossRecoveryHp(roleId: string, gameCode: string) { - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_REVIVE_ALL,//2009 - ]); - if (newEffect.length == 0) return false; - for (const { effectParam, cardCode } of newEffect) { - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - return true; - } - - return false; // 拿到true 将所有学员更新和hp=maxHp -} - -// 战斗胜利后若有学员死亡,则满血复活X名死亡学员 2010 -export async function getBattleRecoveryNum(roleId: string, gameCode: string) { - let recoveryNum = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_REVIVE_CHARA_RAND,//2010 - ]); - if (newEffect.length == 0) return recoveryNum; - - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - recoveryNum += (effectParam[0] || 0) - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } - return recoveryNum; -} - -// 试炼商店中所有商品X折出售 2011 -export async function getShopDiscount(roleId: string, gameCode: string) { - let discount = 100; - let rougeEffect = new RougeEffect(roleId, gameCode); - - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_SHOP_DISCOUNT,//2011 - ]); - if (newEffect.length == 0) return discount; - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const tempDiscount = effectParam[0] || 0; - discount *= (tempDiscount / 100); - await updateHolyUseCount(holyMap.get(cardCode), gameCode) - } - return Math.floor(discount); -} - - -// 下次选择特性卡时必定出现X星特性卡 2013 -export async function getChooseQualityPassives(roleId: string, gameCode: string, passiveCards: DicRougePassiveCardPlan[]) { - let targetPassives: DicRougePassiveCardPlan[] = []; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_FIX,//2013 - ]); - if (newEffect.length == 0) return targetPassives; - for (const { effectParam, cardCode } of newEffect) { - let isUseCount = false; - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const level = effectParam[0] || 0; - for (let val of passiveCards) { - const { cardId } = val; - const passiveCardData = gameData.rougePassiveCard.get(cardId); - if (level != passiveCardData?.lv || 0) continue; - targetPassives.push(val); - isUseCount = true; - } - if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); - - } - return targetPassives; -} - -// 下次选择特性卡时可多选X张特性卡 2014 -export async function getAddChoosePassive(roleId: string, gameCode: string) { - let addChooseNum = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_NUM_UP,//2014 - ]); - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const num = effectParam[0] || 0; - addChooseNum += num; - await updateHolyUseCount(holyMap.get(cardCode), gameCode); - } - return addChooseNum -} - -// 获得该圣物后,所有角色解锁X号位置的特性槽 2023 -export async function getSlotUnlockPoint(roleId: string, gameCode: string, dbCharas: RougelikeCharaPara[]) { - let isUpdate = false; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 - ]); - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - let isUseCount = false; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const index = effectParam[0] || 0; - for (let { cards = [] } of dbCharas) { - if (cards.find(cur => cur.index == index) == undefined) { - isUpdate = true - cards.push({ index, cardCode: '', cardId: 0 }); - isUseCount = true; - } - } - if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); - } - - return { isUpdate, dbCharas }; -} - - -// 休整点额外恢复上限X%的生命 2017 3006 -export async function getRecoveryExtendHp(roleId: string, gameCode: string) { - let hpRatio = 0; - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_RECOVERY_POINT_UP, // 2017 - ROUGE_EFFECT_TYPE.TECH_RECOVERY_POINT_UP, // 3006 - ]); - if (newEffect.length == 0) return hpRatio; - for (const { effectType, effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - hpRatio += (effectParam[0] || 0); - await updateHolyUseCount(holyMap.get(cardCode), gameCode); - } - return hpRatio; -} - -// 休整点特训价格X折 2018 3009 -export async function getTrainCardDiscount(roleId: string, gameCode: string) { - let discount = 100; - let rougeEffect = new RougeEffect(roleId, gameCode); - - let { newEffect, holyMap } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.HOLY_TRAIN_POINT_DISCOUNT, // 2018 - ROUGE_EFFECT_TYPE.TECH_TRAIN_POINT_DISCOUNT, // 3009 - ]); - if (newEffect.length == 0) return discount; - for (const { effectParam, cardCode } of newEffect) { - if (effectParam.length == 0) continue; - if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; - const tempDiscount = effectParam[0] || 0; - discount *= (tempDiscount / 100); - await updateHolyUseCount(holyMap.get(cardCode), gameCode); - - } - return Math.floor(discount); -} - -// 初始获得试炼币&圣物 3003 3005 -export async function getEffectWhenGameStart(roleId: string, gameCode: string, authorType: number) { - let rougeEffect = new RougeEffect(roleId, gameCode); - - let addCoin = 0, cardIds: number[] = []; - let { newEffect } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR, - ROUGE_EFFECT_TYPE.TECH_INIT_COIN, - ]); - if (newEffect.length == 0) return { addCoin, cardIds }; - for (const { effectType, effectParam } of newEffect) { - if (effectParam.length == 0) continue; - if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR) { - for (let cardId of effectParam) { - let dicCard = gameData.rougeHolyCard.get(cardId); - if (!dicCard || dicCard.authorType != authorType) continue; - cardIds.push(cardId); - } - } - if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_COIN) addCoin += effectParam[0]; - } - return { addCoin, cardIds }; -} - -// 是否可以选择技能卡 3004 -export async function checkCanChooseSkillCard(roleId: string, gameCode: string, skillId: number, cards: Card[]) { - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.TECH_CAN_CHOOSE_SKILL_CARD, // 3004 - ]); - let dicSkillCard = gameData.rougeSkillCard.get(skillId); - if (!dicSkillCard) return false; - let { authorType, skillType } = dicSkillCard; - let num = getAuthorTypeCardNum(authorType, cards); - - let curParam = newEffect.find(({ effectParam }) => { - return effectParam[1] == skillType; - }); - if (!curParam || num < curParam.effectParam[0]) return false; - return true; -} - -// 是否可以重置 -export async function checkCanReRandomReward(roleId: string, gameCode: string, rewardType: number) { - let rougeEffect = new RougeEffect(roleId, gameCode); - let { newEffect } = await rougeEffect.getEffectData([ - ROUGE_EFFECT_TYPE.TECH_PASSIVE_RANDOM_AGAIN, // 3008 - ]); - - let curParam = newEffect.find(({ effectParam }) => { - return effectParam[0] == rewardType; - }); - if (!curParam) return { canReRandom: false, costCoin: 0 } - return { canReRandom: true, costCoin: curParam.effectParam[1] || 0 }; -} - - -export function getHolyCardIsUse(holy: { cardId: number, useCount: number, cardCode: string }) { - const { useCount = 0, cardId, cardCode } = (holy || {}); - if (!cardCode) return true;//法阵不存在cardCode - if (!cardId) return; - const holyCardData = gameData.rougeHolyCard.get(cardId) - if (!holyCardData) return; - if ((holyCardData?.useCount || 0) <= useCount) return; - return true -} - -export async function updateHolyUseCount(holy: { cardId: number, useCount: number, cardCode: string }, gameCode: string) { - const { cardId, cardCode } = (holy || {}); - if (!cardId || !cardCode) return; - await RougelikeCardModel.updateByCode(gameCode, cardCode, { $inc: { useCount: 1 } }) -} - -export async function updateCards(updateCards: RougelikeCardPara[]) { - if (updateCards.length == 0) return; - await RougelikeCardModel.bulkWriteUpdate(updateCards) -} \ No newline at end of file +import { ABI_TYPE } from "@consts/constModules/abilityConst"; +import { PUSH_ROUTE, ROUGELIKE_SKILLTYPE, ROUGE_EFFECT_TYPE, ROUGE_EFFECT_TYPE_KIND, ROUGE_LIKE_CARD_TYPE, ROUGE_SLOT_LIMIT } from "@consts"; +import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from "@db/RougelikeCard"; +import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from "@db/RougelikeChara"; +import { RougelikeRecordModel } from "@db/RougelikeRecord"; +import { gameData, getRougeEffectTypeKind } from "@pubUtils/data"; +import { DicRougePassiveCardPlan } from "@pubUtils/dictionary/DicRougePassiveCardPlan"; +import { getRandEelm } from "@pubUtils/util"; +import { RougelikeTechModel } from "@db/RougelikeTech"; +import { getAuthorTypeCardNum } from "./rougeService"; +import * as util from 'util'; +import { DicRougePassiveCard } from "@pubUtils/dictionary/DicRougePassiveCard"; +import { sendMessageToUserWithSuc } from "../pushService"; + + + +export class holyId { + cardCode: string; + cardId: number; + useCount: number; +} + + +export class RougeEffect { + roleId: string; + gameCode: string; + sid: string; + newEffect: { effectType: number, effectParam: number[], cardCode?: string }[] = []; + holyMap = new Map(); + updateHolyMap = new Map(); + updateCharaMap = new Map(); + updateCardMap = new Map(); + dbCharas: RougelikeCharaType[] = []; + dbCards: RougelikeCardType[] = []; + + constructor(roleId: string, gameCode: string, sid?: string) { + this.roleId = roleId || ''; + this.gameCode = gameCode || ''; + this.sid = sid || ''; + + } + + /** + * 根据类型获取effectId + * @param effectTypes + * @param holyIds + * @returns + */ + public async getEffectData(effectTypes: number[], holyIds?: holyId[]) { + let kinds = getRougeEffectTypeKind(effectTypes); + if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.HOLY)) { + if (!holyIds || holyIds.length == 0) { + const dbCards = await RougelikeCardModel.findByGameCodeAndType(this.gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); + holyIds = dbCards.map((cur) => { return { cardCode: cur.cardCode, cardId: cur.cardId, useCount: cur.useCount || 0 } }); + } + if (!holyIds || holyIds.length == 0) return { newEffect: this.newEffect, holyMap: this.holyMap }; + + for (const { cardCode, cardId, useCount } of holyIds) { + let effectIds = gameData.rougeHolyCard.get(cardId)?.effectId || []; + if (effectIds.length == 0) continue; + + for (const effectId of effectIds) { + const effectDataOne = gameData.rougeEffect.get(effectId); + if (!effectDataOne) continue; + const effectParam = effectDataOne.effectParam || []; + for (let effectType of effectTypes) { + if (effectType != effectDataOne.effectType || 0) continue; + this.newEffect.push({ effectType, effectParam, cardCode }); + this.holyMap.set(cardCode, { cardCode, cardId, useCount }) + } + } + } + } + + if (kinds.includes(ROUGE_EFFECT_TYPE_KIND.TECH)) { + let tech = await RougelikeTechModel.findByRoleId(this.roleId, 'effectIds'); + for (let effectId of (tech?.effectIds || [])) { + const effectDataOne = gameData.rougeEffect.get(effectId); + if (!effectDataOne) continue; + for (let effectType of effectTypes) { + if (effectType != effectDataOne.effectType || 0) continue; + this.newEffect.push({ effectType, effectParam: effectDataOne.effectParam || [] }); + } + } + } + + return { newEffect: this.newEffect, holyMap: this.holyMap } + } + + /* ** + * 获取圣物时生效 + * @param gameCode + */ + public async getEffectImmediate(holyIds?: holyId[]) { + let result: { charas?: Map, cards?: Map } = {}; + this.dbCharas = await RougelikeCharaModel.findByGameCode(this.gameCode); + this.dbCards = await RougelikeCardModel.findByGameCode(this.gameCode); + + await this.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL, //2002 + ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND, //2003 + ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND, //2006 + ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV, //2012 + ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY, //2015 + ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 + ], holyIds) + + await this.getCharaSlot(); + + await this.getRandCharaSlot(); + + await this.getRandomCardLv() + + await this.getPassiveLv(); + + await this.getRecoveryHoly(); + + await this.getSlotUnlockPoint() + + result = { charas: this.updateCharaMap, cards: this.updateCardMap }; + + return result; + } + + + // 获得该圣物时,所有学员立刻解锁X个特性槽 2002 + private async getCharaSlot() { + if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_ALL) continue; + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + for (let val of this.dbCharas) { + let { charaCode, cards = [] } = val; + let unlockNum = effectParam[0] || 0; + for (let i = 0; i < unlockNum; i++) { + unlockNum = effectParam[0] || 0; + if (cards.length >= ROUGE_SLOT_LIMIT) continue; + for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { + if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; + cards.push({ index, cardCode: '', cardId: 0 }); + this.updateCharaMap.set(charaCode, val); + unlockNum--; + isUseCount = true; + } + } + } + if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + } + + private updateHolyMapUseCount(holy: { cardCode: string, cardId: number, useCount: number }) { + let { cardCode, useCount = 0, cardId } = (holy || {}); + if (!cardId || !cardCode) return; + let val = this.dbCards.find(cur => cur.cardCode == cardCode); + if (val == undefined) return; + useCount = (useCount + 1) >= 0 ? (useCount + 1) : 0 + this.updateCardMap.set(cardCode, { ...val, useCount }); + this.holyMap.set(cardCode, { cardCode, cardId, useCount }); + } + + // 获得该圣物时,随机解锁X个学员的Y个特性槽 2003 + private async getRandCharaSlot() { + if (this.newEffect.length == 0 || this.dbCharas.length == 0) return; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_RAND) continue; + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const randomNum = effectParam[0] || 0; + let unlockNum = effectParam[1] || 0; + this.dbCharas.sort((a, b) => { + if (a.seqId < b.seqId) return -1; + if (a.seqId > b.seqId) return 1; + return 0; + }); + let charas = getRandEelm(this.dbCharas.slice(0, 6).filter(cur => cur.cards.length < ROUGE_SLOT_LIMIT), randomNum); + for (let val of charas) { + unlockNum = effectParam[1] || 0; + let { charaCode, cards = [] } = val; + for (let index = 0; index < ROUGE_SLOT_LIMIT; index++) { + if (cards.find(cur => cur.index == index) != undefined || unlockNum == 0) continue; + cards.push({ index, cardCode: '', cardId: 0 }); + this.updateCharaMap.set(charaCode, val); + unlockNum--; + isUseCount = true; + } + } + if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + } + + // 随机升级X个已装备的特性 2006 + private async getRandomCardLv() { + if (this.newEffect.length == 0 || this.dbCards.length == 0) return; + let pushCards: RougelikeCardType[] = []; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_PASSIVE_UPDATE_RAND) continue; + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const randomNum = effectParam[0] || 0; + let random = this.dbCards.filter(cur => cur.type == ROUGE_LIKE_CARD_TYPE.PASSIVE && cur.charaId && cur.charaId != 0); + let newRandom: RougelikeCardType[] = []; + for (let cur of random) { + // if (cur.type != ROUGE_LIKE_CARD_TYPE.PASSIVE || cur.charaId == 0) continue; + let passiveCardDataMap = this.getPassiveData(cur.cardId); + if (!passiveCardDataMap.has(cur.lv + 1)) continue; + newRandom.push({ ...cur, cardId: passiveCardDataMap.get(cur.lv + 1).id, lv: cur.lv + 1 }); + } + + if (newRandom && newRandom.length > 0) { + let cards = getRandEelm(newRandom, randomNum); + cards.forEach(async cur => { this.updateCardMap.set(cur.cardCode, cur), await this.updateCharaCards(cur, cur.cardCode, cur.cardId); }); + pushCards.push(...cards); + + this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + } + if (pushCards.length > 0) { + await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); + } + } + + private getPassiveData(cardId: number) { + let passiveCardDataMap = new Map() + const passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData) return passiveCardDataMap; + const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0); + if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return passiveCardDataMap; + passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map()); + return passiveCardDataMap; + } + + // 获得该圣物时立即升级所有X星特性卡 2012 + private async getPassiveLv() { + if (this.newEffect.length == 0) return; + let pushCards: RougelikeCardType[] = []; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_UPDATE_PASSIVE_BY_LV) continue; + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const level = effectParam[0] || 0; + for (let val of this.dbCards) { + let { lv, cardId, cardCode } = val; + if (lv != level) continue; + let passiveCardDataMap = this.getPassiveData(cardId); + if (!passiveCardDataMap.has(lv + 1)) continue; + let id = passiveCardDataMap.get(lv + 1).id; + this.updateCardMap.set(cardCode, { ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); + pushCards.push({ ...val, lv: lv + 1, cardId: passiveCardDataMap.get(lv + 1).id }); + + if (val.charaId && val.charaId > 0) { + await this.updateCharaCards(val, cardCode, id); + } + + isUseCount = true; + } + if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + if (pushCards.length > 0) { + await sendMessageToUserWithSuc(this.roleId, PUSH_ROUTE.ROUGE_PASSIVE_CARD_UP_LV, { upLvCards: pushCards }, this.sid); + } + } + + private async updateCharaCards(val: RougelikeCardType, cardCode: string, id: number) { + for (let obj of this.dbCharas) { + if (obj.charaId != val.charaId) continue; + for (let card of (obj.cards || [])) { + if (card.cardCode != cardCode) continue; + card.cardId = id; + } + this.updateCharaMap.set(obj.charaCode, obj); + } + } + + + // 获得该圣物时,随机修复X个已损毁的圣物 2015 + private async getRecoveryHoly() { + if (this.newEffect.length == 0) return; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_REPAIRE_HOLY) continue; + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const num = effectParam[0] || 0; + let canRandomCards: RougelikeCardType[] = [] + this.dbCards.forEach(cur => { + const { cardCode, cardId, useCount = 0, type } = cur; + const holyCardData = gameData.rougeHolyCard.get(cardId); + let tempUseCount = holyCardData?.useCount || 0; + if (tempUseCount - useCount <= 0 && type == ROUGE_LIKE_CARD_TYPE.HOLY) canRandomCards.push(cur); + + }) + + let randomCards = getRandEelm(canRandomCards, num); + for (let val of randomCards) { + let { cardCode, cardId } = val; + val.useCount -= 1; + this.updateCardMap.set(cardCode, val); + + if (this.holyMap.has(cardCode)) this.holyMap.set(cardCode, { cardCode, cardId, useCount: val.useCount }); + isUseCount = true; + } + + if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + } + + //2023 + private async getSlotUnlockPoint() { + if (this.newEffect.length == 0) return; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT) continue; + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const num = effectParam[0] || 0; + const index = effectParam[0] || 0; + for (let val of this.dbCharas) { + let { cards = [], charaCode } = val + if (cards.find(cur => cur.index == index) == undefined) { + cards.push({ index, cardCode: '', cardId: 0 }); + this.updateCharaMap.set(charaCode, val); + isUseCount = true; + } + } + if (isUseCount) this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + } + + + // 和圣物相关maxhp + public async getEffectMaxHp() { + let addRatio = 0; + await this.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN, // 2005 + ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP, // 2020 + ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP, // 3001 + ]) + + addRatio = await this.getMaxHpByCoin(); + + addRatio += await this.getMaxHpByBase(); + + + await updateCards([...this.updateCardMap.values()]); + + return addRatio; + } + + // 每有X个试炼币,全员基础属性id提高Y 2005 + private async getMaxHpByCoin() { + let addRatio = 0; + const dbRecord = await RougelikeRecordModel.findByGameCode(this.gameCode); + let coinTotal = dbRecord?.coin || 0; + if (this.newEffect.length == 0) return addRatio; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP_BY_COIN) continue; + if (effectParam.length == 0) continue; + const count = effectParam[0] || 0; + const id = effectParam[1] || 0; + const value = effectParam[2] || 0; + if (count == 0 || id != ABI_TYPE.ABI_HP || value == 0) continue; + addRatio += Math.floor(coinTotal / count * value) + + this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + + } + + return addRatio; + } + + // 基础属性Id&num 2020 + private async getMaxHpByBase() { + let addRatio = 0; + if (this.newEffect.length == 0) return addRatio; + for (const { effectParam, effectType, cardCode } of this.newEffect) { + if (effectType != ROUGE_EFFECT_TYPE.HOLY_CHARA_MAIN_ATTR_UP && effectType != ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP) continue; + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(this.holyMap.get(cardCode))) continue; + const id = effectParam[0] || 0; + const value = effectParam[1] || 0; + if (id != ABI_TYPE.ABI_HP || value == 0) continue; + addRatio += value; + this.updateHolyMapUseCount(this.holyMap.get(cardCode)); + } + return addRatio; + } +} + + +// 每场战斗结束后,学员恢复血量上限X%的生命 2001 +export async function getCharaHp(roleId: string, gameCode: string) { + let hpRatio = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_CHARA_HP_RECOVERY_UP,// 2001 + ]); + if (newEffect.length == 0) return hpRatio; + for (const { effectType, effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + hpRatio += (effectParam[0] || 0); + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } + return hpRatio; +} + + +// 战斗胜利后,获得的试炼币增加X 2004 +export async function getAddCoin(roleId: string, gameCode: string, nodeType: number) { + let coinRatio = 0, coinAdd = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_COIN_UP, //2004 + ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE, //3007 + ]); + if (newEffect.length == 0) return { coinRatio, coinAdd }; + for (const { effectType, effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + if (effectType == ROUGE_EFFECT_TYPE.HOLY_COIN_UP) { + const type = effectParam[0] || 0; + const value = effectParam[1] || 0; + if (type == 1) coinAdd += value; + else if (type == 2) coinRatio += value; + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } + if (effectType == ROUGE_EFFECT_TYPE.TECH_COIN_UP_BY_NODE_TYPE) { + let [value = 0, ...targetNodeType] = effectParam; + if (targetNodeType && targetNodeType.includes(nodeType)) coinRatio += value; + } + + } + return { coinRatio, coinAdd }; +} + + +// 获得圣物后,X流派特性卡的权重增加Y 2007 +export async function getAddPassiveWeight(roleId: string, gameCode: string, authorType: number) { + let addPassiveWeight = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_PASSIVE_WEIGHT_UP_BY_AUTHOR,//2007 + ]); + if (newEffect.length == 0) return addPassiveWeight; + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const type = effectParam[0] || 0; + const value = effectParam[1] || 0; + if (type != authorType) continue; + addPassiveWeight += value; + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } + return addPassiveWeight; +} + +// 2008 +export async function getEnterGame(roleId: string, gameCode: string) { + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_ENEMY_MAIN_ATTR_DOWN,//2008 + ]); + if (newEffect.length == 0) return; + for (const { effectParam, cardCode } of newEffect) { + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } +} + +// 非boss战斗失败视为胜利,并且满血复活 2009 +export async function getNoBossRecoveryHp(roleId: string, gameCode: string) { + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_REVIVE_ALL,//2009 + ]); + if (newEffect.length == 0) return false; + for (const { effectParam, cardCode } of newEffect) { + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + return true; + } + + return false; // 拿到true 将所有学员更新和hp=maxHp +} + +// 战斗胜利后若有学员死亡,则满血复活X名死亡学员 2010 +export async function getBattleRecoveryNum(roleId: string, gameCode: string) { + let recoveryNum = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_REVIVE_CHARA_RAND,//2010 + ]); + if (newEffect.length == 0) return recoveryNum; + + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + recoveryNum += (effectParam[0] || 0) + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } + return recoveryNum; +} + +// 试炼商店中所有商品X折出售 2011 +export async function getShopDiscount(roleId: string, gameCode: string) { + let discount = 100; + let rougeEffect = new RougeEffect(roleId, gameCode); + + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_SHOP_DISCOUNT,//2011 + ]); + if (newEffect.length == 0) return discount; + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const tempDiscount = effectParam[0] || 0; + discount *= (tempDiscount / 100); + await updateHolyUseCount(holyMap.get(cardCode), gameCode) + } + return Math.floor(discount); +} + + +// 下次选择特性卡时必定出现X星特性卡 2013 +export async function getChooseQualityPassives(roleId: string, gameCode: string, passiveCards: DicRougePassiveCardPlan[]) { + let targetPassives: DicRougePassiveCardPlan[] = []; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_FIX,//2013 + ]); + if (newEffect.length == 0) return targetPassives; + for (const { effectParam, cardCode } of newEffect) { + let isUseCount = false; + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const level = effectParam[0] || 0; + for (let val of passiveCards) { + const { cardId } = val; + const passiveCardData = gameData.rougePassiveCard.get(cardId); + if (level != passiveCardData?.lv || 0) continue; + targetPassives.push(val); + isUseCount = true; + } + if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); + + } + return targetPassives; +} + +// 下次选择特性卡时可多选X张特性卡 2014 +export async function getAddChoosePassive(roleId: string, gameCode: string) { + let addChooseNum = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_PASSIVE_CHOOSE_NUM_UP,//2014 + ]); + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const num = effectParam[0] || 0; + addChooseNum += num; + await updateHolyUseCount(holyMap.get(cardCode), gameCode); + } + return addChooseNum +} + +// 获得该圣物后,所有角色解锁X号位置的特性槽 2023 +export async function getSlotUnlockPoint(roleId: string, gameCode: string, dbCharas: RougelikeCharaPara[]) { + let isUpdate = false; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_CHARA_SLOT_UNLOCK_POINT,//2023 + ]); + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + let isUseCount = false; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const index = effectParam[0] || 0; + for (let { cards = [] } of dbCharas) { + if (cards.find(cur => cur.index == index) == undefined) { + isUpdate = true + cards.push({ index, cardCode: '', cardId: 0 }); + isUseCount = true; + } + } + if (isUseCount) await updateHolyUseCount(holyMap.get(cardCode), gameCode); + } + + return { isUpdate, dbCharas }; +} + + +// 休整点额外恢复上限X%的生命 2017 3006 +export async function getRecoveryExtendHp(roleId: string, gameCode: string) { + let hpRatio = 0; + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_RECOVERY_POINT_UP, // 2017 + ROUGE_EFFECT_TYPE.TECH_RECOVERY_POINT_UP, // 3006 + ]); + if (newEffect.length == 0) return hpRatio; + for (const { effectType, effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + hpRatio += (effectParam[0] || 0); + await updateHolyUseCount(holyMap.get(cardCode), gameCode); + } + return hpRatio; +} + +// 休整点特训价格X折 2018 3009 +export async function getTrainCardDiscount(roleId: string, gameCode: string) { + let discount = 100; + let rougeEffect = new RougeEffect(roleId, gameCode); + + let { newEffect, holyMap } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.HOLY_TRAIN_POINT_DISCOUNT, // 2018 + ROUGE_EFFECT_TYPE.TECH_TRAIN_POINT_DISCOUNT, // 3009 + ]); + if (newEffect.length == 0) return discount; + for (const { effectParam, cardCode } of newEffect) { + if (effectParam.length == 0) continue; + if (!getHolyCardIsUse(holyMap.get(cardCode))) continue; + const tempDiscount = effectParam[0] || 0; + discount *= (tempDiscount / 100); + await updateHolyUseCount(holyMap.get(cardCode), gameCode); + + } + return Math.floor(discount); +} + +// 初始获得试炼币&圣物 3003 3005 +export async function getEffectWhenGameStart(roleId: string, gameCode: string, authorType: number) { + let rougeEffect = new RougeEffect(roleId, gameCode); + + let addCoin = 0, cardIds: number[] = []; + let { newEffect } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR, + ROUGE_EFFECT_TYPE.TECH_INIT_COIN, + ]); + if (newEffect.length == 0) return { addCoin, cardIds }; + for (const { effectType, effectParam } of newEffect) { + if (effectParam.length == 0) continue; + if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_HOLY_BY_AUTHOR) { + for (let cardId of effectParam) { + let dicCard = gameData.rougeHolyCard.get(cardId); + if (!dicCard || dicCard.authorType != authorType) continue; + cardIds.push(cardId); + } + } + if (effectType == ROUGE_EFFECT_TYPE.TECH_INIT_COIN) addCoin += effectParam[0]; + } + return { addCoin, cardIds }; +} + +// 是否可以选择技能卡 3004 +export async function checkCanChooseSkillCard(roleId: string, gameCode: string, skillId: number, cards: Card[]) { + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.TECH_CAN_CHOOSE_SKILL_CARD, // 3004 + ]); + let dicSkillCard = gameData.rougeSkillCard.get(skillId); + if (!dicSkillCard) return false; + let { authorType, skillType } = dicSkillCard; + let num = getAuthorTypeCardNum(authorType, cards); + + let curParam = newEffect.find(({ effectParam }) => { + return effectParam[1] == skillType; + }); + if (!curParam || num < curParam.effectParam[0]) return false; + return true; +} + +// 是否可以重置 +export async function checkCanReRandomReward(roleId: string, gameCode: string, rewardType: number) { + let rougeEffect = new RougeEffect(roleId, gameCode); + let { newEffect } = await rougeEffect.getEffectData([ + ROUGE_EFFECT_TYPE.TECH_PASSIVE_RANDOM_AGAIN, // 3008 + ]); + + let curParam = newEffect.find(({ effectParam }) => { + return effectParam[0] == rewardType; + }); + if (!curParam) return { canReRandom: false, costCoin: 0 } + return { canReRandom: true, costCoin: curParam.effectParam[1] || 0 }; +} + + +export function getHolyCardIsUse(holy: { cardId: number, useCount: number, cardCode: string }) { + const { useCount = 0, cardId, cardCode } = (holy || {}); + if (!cardCode) return true;//法阵不存在cardCode + if (!cardId) return; + const holyCardData = gameData.rougeHolyCard.get(cardId) + if (!holyCardData) return; + if ((holyCardData?.useCount || 0) <= useCount) return; + return true +} + +export async function updateHolyUseCount(holy: { cardId: number, useCount: number, cardCode: string }, gameCode: string) { + const { cardId, cardCode } = (holy || {}); + if (!cardId || !cardCode) return; + await RougelikeCardModel.updateByCode(gameCode, cardCode, { $inc: { useCount: 1 } }) +} + +export async function updateCards(updateCards: RougelikeCardPara[]) { + if (updateCards.length == 0) return; + await RougelikeCardModel.bulkWriteUpdate(updateCards) +} diff --git a/game-server/app/services/battle/rougeService.ts b/game-server/app/services/battle/rougeService.ts index 63dbc629d..05a66f69e 100644 --- a/game-server/app/services/battle/rougeService.ts +++ b/game-server/app/services/battle/rougeService.ts @@ -1,1063 +1,1063 @@ -import { clone, result } from "underscore"; -import { ROUGE_CHARA_INITIAL, ROUGE_CHARA_TYPE, ROUGE_EFFECT_TYPE, ROUGE_LIKE_CARD_TYPE, ROUGE_LIKE_CHOOSE_REWARD, ROUGE_LIKE_NODE_TYPE, ROUGE_LIKE_STATUS, SHOP_REFRESH_TYPE } from "../../consts"; -import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from "../../db/RougelikeChara"; -import { RougelikeLayerModel, RougelikeLayerType } from "../../db/RougelikeLayer"; -import { RougelikeRecordModel, RougelikeRecordType } from "../../db/RougelikeRecord"; -import { gameData } from "../../pubUtils/data"; -import { ROUGELIKE } from "../../pubUtils/dicParam"; -import { genCode, getRandEelm, getRandEelmWithWeight, getRandEelmWithWeightAndNum, getRandValueByMinMax } from "../../pubUtils/util"; -import { RougelikeCardModel, RougelikeCardType } from "../../db/RougelikeCard"; -import RougelikeRecordDetail, { RougelikeRecordDetailModel, RougelikeRecordDetailPara, RougelikeRecordDetailType } from "../../db/RougelikeRecordDetail"; -import { CollectionReturnParam, CommonCard, CommonChara, CommonNode, CommonReward, RewardInter, layerNode } from "../../pubUtils/interface"; -import { DicRougeQuestionMarkPlan } from "../../pubUtils/dictionary/DicRougeQuestionMarkPlan"; -import { DicRougeRandomEventPlan } from "../../pubUtils/dictionary/DicRougeRandomEventPlan"; -import * as util from 'util'; -import { RougelikeCollectionModel, } from "../../db/RougelikeCollection"; -import { RougelikeScoreModel, RougelikeScorePara } from "../../db/RougelikeScore"; -import { getTechData } from "./rougeTechService"; -import { getZeroPointOfTimeD } from "../../pubUtils/timeUtil"; -import { sendMailByContent } from "../mailService"; -import { MAIL_TYPE, PUSH_ROUTE } from "../../consts"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { RougeEffect, getAddChoosePassive, getAddPassiveWeight, getChooseQualityPassives, getShopDiscount } from "./rougeEffectService"; -import { formateCharasOrCards } from "./rougeCollectService"; -import { errlogger } from "../../util/logger"; -import { RougelikeExtendModel } from "../../db/RougelikeExtend"; -import { isDevelopEnv } from "../utilService"; -import { DicRougeCharaCardPlan } from "../../pubUtils/dictionary/DicRougeCharaCardPlan"; - -export async function getRougeData(roleId: string) { - - let isPlaying = true, gameCode = ''; - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); - if (!dbRecord) isPlaying = false; - else gameCode = dbRecord.gameCode; - - let dbScore = await RougelikeScoreModel.findByRoleId(roleId); - let techData = await getTechData(roleId); - - let dbCollections = await RougelikeCollectionModel.findByRoleId(roleId); - let collections = dbCollections.map((obj) => new CollectionReturnParam(obj)); - - const dbExtends = await RougelikeExtendModel.findByRoleId(roleId); - const limitIds = dbExtends.map(cur => cur.limitId); - const lastMaxLv = await RougelikeExtendModel.getLastMaxLv(roleId); - return { isPlaying, gameCode, weeklyScore: dbScore?.score || 0, receivedScore: dbScore?.received || [], ...techData, collections, limitIds, takeoutRewardCnt: dbScore?.takeoutRewardCnt, lastMaxLv } -} - -/* -/** - * 获取初始三名角色卡 - * @param - * @returns - */ -export function getInitCharaCard() { - let canRandomCharas = gameData.rougeCharaByInitial.get(ROUGE_CHARA_INITIAL.CAN); - if (!canRandomCharas || canRandomCharas.length < ROUGELIKE.INIT_RANDOM_CHARA_COUNT) { - console.error("getInitChara--配置表中能初始随机的角色卡不足, canRandomCharas=%s", canRandomCharas); - return; - } - - let randomData = getRandEelm(canRandomCharas, ROUGELIKE.INIT_RANDOM_CHARA_COUNT) - - return randomData; -} - -/** - * 获取大地图生成数据 - * @param layerPlan - * @param layerCount - */ -export function getMap(layerPlan: number, layerCount: number) { - let retLayer = getLayerNodeRandom(layerPlan, layerCount); - if (!retLayer) return []; - return getLayerNodeLineRandom(retLayer) || []; - -} -export function getLayerNodeRandom(layerPlan: number, layerCount: number) { - if (!layerPlan || !layerCount) return; - - const layerPlanDatas = gameData.rougeLayerPlanByPlanId.get(layerPlan); - if (!layerPlanDatas || layerPlanDatas.length != layerCount) return console.error("getMap--获取配置层数不一致, layerPlan=%s, layerCount=%s", layerPlan, layerCount); - - let retLayer = new Map(); - - //获取可随机到的节点 - for (let data of layerPlanDatas) { - let layerNodeNumPlanDatas = gameData.rougeLayerNodeNumPlan.get(data.nodeNumPlan); - if (!layerNodeNumPlanDatas) return console.error("getMap--rougeLayerNodeNumPlan配置错误, planId=%s", data.nodeNumPlan); - let nodeNum = 0; - if (layerNodeNumPlanDatas.length == 1) nodeNum = 1; - else nodeNum = getRandEelmWithWeight(layerNodeNumPlanDatas).dic.nodeNum; - - let layerNodePlans = gameData.rougeLayerNodePlan.get(data.nodePlan); - if (!layerNodePlans || layerNodePlans.length == 0) return console.error("getMap--rougeLayerNodePlan配置错误, planId=%s", data.nodePlan); - - let randomNodes: CommonNode['layerNodes'] = [], tempIndex = 0; - if (layerNodePlans.length > nodeNum) { - randomNodes = getRandEelmWithWeightAndNum(layerNodePlans, nodeNum).map((cur) => { - let nodeId = cur.dic.nodeId; - let nodeData = gameData.rougeNode.get(nodeId); - if (!nodeData) errlogger.error(`nodePlane ${data.nodePlan} 's nodeId ${nodeId} not found`); - return { detailCode: genCode(8), index: tempIndex++, nodeId, preNodeIndexs: [], type: nodeData.nodeType, isChoose: 0 }; - }); - } else { - randomNodes = layerNodePlans.map((cur) => { - let nodeId = cur.nodeId; - let nodeData = gameData.rougeNode.get(nodeId); - return { detailCode: genCode(8), index: tempIndex++, nodeId: cur.nodeId, preNodeIndexs: [] as number[], type: nodeData.nodeType, isChoose: 0 }; - }); - } - - retLayer.set(data.layerIndex, { layer: data.layerIndex, layerNodes: randomNodes }); - } - // console.log('-x-x--x-x-x-x-x-x-x-x-x- retLayer', util.inspect(retLayer, { depth: null })); - return retLayer; -} - -/** - * 随机节点连线 - * @param retLayer - * @returns - */ -export function getLayerNodeLineRandom(retLayer: Map) { - for (let [key, value] of retLayer) { - let preLayer = retLayer.get(key - 1); - let curLayer = retLayer.get(key); - if (!preLayer || !curLayer) continue; - let tempPreNodes = preLayer.layerNodes; // 前一层节点数据 - let tempCurNodes = curLayer.layerNodes; // 当前层节点数据 - let indexMap = new Map(); //记录下前一层有那些节点与当前层是否连线 - - //当前层首节点 - tempCurNodes[0].preNodeIndexs.push(tempPreNodes[0].index); - indexMap.set(tempPreNodes[0].index, { dx: 0, index: tempCurNodes[0].index }); - - //当前层尾节点 - if (!(tempCurNodes.length == 1 && tempPreNodes.length == 1)) { - tempCurNodes[tempCurNodes.length - 1].preNodeIndexs.push(tempPreNodes[tempPreNodes.length - 1].index); - indexMap.set(tempPreNodes[tempPreNodes.length - 1].index, { dx: tempCurNodes.length - 1, index: tempCurNodes[tempCurNodes.length - 1].index }); - } - - for (let i = 0; i < tempCurNodes.length - 1; i++) { - let minIndex = 0, maxIndex = 0, start = 0; - if (i != 0) start = minIndex = maxIndex = Math.max(...tempCurNodes[i - 1].preNodeIndexs); - if (tempPreNodes[start + 1]) maxIndex = tempPreNodes[start + 1].index; - if (tempPreNodes[start + 2]) maxIndex = tempPreNodes[start + 2].index; - - let randomIndex = minIndex; - if (minIndex < maxIndex) randomIndex = getRandValueByMinMax(minIndex, maxIndex + 1, 0); - - if (tempCurNodes[i].preNodeIndexs.indexOf(randomIndex) != -1) continue; - tempCurNodes[i].preNodeIndexs.push(randomIndex); - if (indexMap.get(randomIndex) && indexMap.get(randomIndex).dx < i) continue; - indexMap.set(randomIndex, { dx: i, index: tempCurNodes[i].index }); - } - - //处理前一层有节点未连接情况 - for (let i = 1; i < tempPreNodes.length - 1; i++) { - if (indexMap.get(tempPreNodes[i].index)) continue; - - let minDx = 0, maxDx = 0; - let tempMap = new Map(); - - if (tempPreNodes[i - 1] && indexMap.get(tempPreNodes[i - 1].index)) { - minDx = maxDx = indexMap.get(tempPreNodes[i - 1].index).dx - for (let j = 0; j < tempCurNodes.length; j++) { - if (tempPreNodes[i - 1] && tempCurNodes[j].preNodeIndexs.indexOf(tempPreNodes[i - 1].index) != -1) minDx = maxDx = Math.max(minDx, j); - } - tempMap.set(minDx, indexMap.get(tempPreNodes[i - 1].index).index); - } - if (tempPreNodes[i + 1] && indexMap.get(tempPreNodes[i + 1].index)) { - maxDx = indexMap.get(tempPreNodes[i + 1].index).dx - tempMap.set(maxDx, indexMap.get(tempPreNodes[i + 1].index).index); - } - - let randomDx = minDx; - if (minDx < maxDx) randomDx = getRandValueByMinMax(minDx, maxDx + 1, 0); - - tempCurNodes[randomDx].preNodeIndexs.push(tempPreNodes[i].index); - if (indexMap.get(tempPreNodes[i].index) && indexMap.get(tempPreNodes[i].index).dx < randomDx) continue; - indexMap.set(tempPreNodes[i].index, { dx: randomDx, index: tempMap.get(randomDx) }); - } - } - - // console.log('-x-x--x-x-x-x-x-x-x-x-x- [...retLayer.values()]', util.inspect([...retLayer.values()], { depth: null })); - - return [...retLayer.values()]; -} - -/** - * 选择节点 - * @param dbRecord - * @param layerChooseNode - * @returns - */ -export async function chooseNode(dbRecord: RougelikeRecordType, layerChooseNode: layerNode, layer: number) { - - const { roleId, gameCode, type, grade, curLayer, authorType } = dbRecord; - - const { detailCode, nodeId, } = layerChooseNode - let nodeType = layerChooseNode.type; - - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - const nodeData = gameData.rougeNode.get(nodeId); - if (!typeGradeData || !nodeData) return; - - const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); - // console.log("-x--x-x-x-x- nodeData", nodeData) - // console.log("-x--x-x-x-x- typeGradeData", typeGradeData) - // console.log("-x--x-x-x-x- layerPlanData", layerPlanData) - - - if (!layerPlanData) return; - - - let isReward = false, isShop = false; - let warId, reward = {} as CommonReward, shops: RougelikeRecordDetailType['shops'] = [], - challenge = {} as RougelikeRecordDetailType['challenge'], question = {} as RougelikeRecordDetail['question'], restPoints: RougelikeRecordDetail['restPoints'] = []; - - - const dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); - let status = 0; - if (dbDetail) status = dbDetail.status || 0; - - let dbPara = { roleId, layer, nodeId, nodeType, status } as RougelikeRecordDetailPara; - - //普通关、精英关、boss关 - if (nodeType == ROUGE_LIKE_NODE_TYPE.ORDINARY || nodeType == ROUGE_LIKE_NODE_TYPE.ELITE || nodeType == ROUGE_LIKE_NODE_TYPE.BOSS) { - isReward = true; - warId = dbPara.warId = nodeData.param; - } - - //挑战关 - else if (nodeType == ROUGE_LIKE_NODE_TYPE.CHALLENGE) { - if (dbDetail) { - challenge = dbDetail.challenge; - } else { - let getChallengeData = getChallenge(typeGradeData.challengePlan); - if (getChallengeData) { - challenge = { challengeId: getChallengeData.challengeId, status: 1, progress: 0 } as RougelikeRecordDetailType['challenge']; - dbPara.challenge = challenge; - } - // isReward = true; - } - - } - - //商店 - else if (nodeType == ROUGE_LIKE_NODE_TYPE.SHOP) { - isShop = true; - } - - //休整点 - else if (nodeType == ROUGE_LIKE_NODE_TYPE.REST_POINT) { - isReward = true; - if (dbDetail && dbDetail.restPoints) restPoints = dbDetail.restPoints || restPoints; - else dbPara.restPoints = restPoints; - } - - //问号点 - else if (nodeType == ROUGE_LIKE_NODE_TYPE.QUEST_POINT) { - if (dbDetail) { - question = dbDetail.question || {} as RougelikeRecordDetail['question']; - warId = dbDetail.warId; - } - else { - const questionMarkPLanData = gameData.rougeQuestionMarkPlan.get(nodeData.param); - if (!questionMarkPLanData) return; - - let randomData = {} as DicRougeQuestionMarkPlan; - if (questionMarkPLanData.length == 1) randomData = questionMarkPLanData[0]; - else randomData = getRandEelmWithWeight(questionMarkPLanData).dic; - - dbPara.questType = randomData.nodeType; - if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.ORDINARY || randomData.nodeType == ROUGE_LIKE_NODE_TYPE.ELITE) { - isReward = true; - warId = dbPara.warId = randomData.param; - } - else if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.SHOP) { - isShop = true - } - else if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.EVENT) { - let random = {} as DicRougeRandomEventPlan; - const randomEventPlanData = gameData.rougeRandomEventPlan.get(typeGradeData.randomEventPlan); - if (!randomEventPlanData) return; - if (randomEventPlanData.length == 1) random = randomEventPlanData[0]; - else random = getRandEelmWithWeight(randomEventPlanData).dic; - question.randomEventId = random.randomEventId; - question.EventOptions = []; - dbPara.question = question; - } - } - } - - - let weightRecords = []; - if ((!dbDetail || !dbDetail.shops || dbDetail.shops.length == 0) && isShop) { - let result = await getLayerShopReward(roleId, gameCode, authorType, nodeId, layerPlanData.shopPlan); - dbPara.shops = shops = result.shops; - if (isDevelopEnv()) { - weightRecords = dbPara.weightRecords = (result?.weightRecords || []) - } - } - if (dbDetail && dbDetail.shops) { - shops = dbDetail.shops || shops; - if (isDevelopEnv()) { - weightRecords = dbDetail.weightRecords - } - } - - if ((!dbDetail || !dbDetail.rewards || dbDetail.rewards.length == 0) && isReward) { - let startTime = Date.now(); - let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer, dbPara.questType); - console.log('*********************************nodeType=%s getLayerNodeReward time=%s', nodeType, Date.now() - startTime) - if (result && result.rewards) { - reward = result; - dbPara.rewards = result.rewards; - - if (!isDevelopEnv() && reward && reward.weightRecords) { - reward.weightRecords = []; - } - } - - if (isDevelopEnv()) { - weightRecords = dbPara.weightRecords = (result?.weightRecords || []); - } - } - if (dbDetail && dbDetail.rewards) { - let tempType = (dbDetail?.questType || 0) > 0 ? dbDetail?.questType : nodeType - const layerRewardData = gameData.rougeLayerRewardPlan.get(layerPlanData.rewardPlan + '_' + tempType); - if (!layerRewardData) return; - let { coin, score, tech } = layerRewardData; - reward = { rewards: dbDetail.rewards || [], score: score || 0, techScore: tech || 0, takeoutReward: layerPlanData.takeoutReward || [] }; - - if (isDevelopEnv()) { - weightRecords = dbDetail.weightRecords - } - } - - if (!dbDetail) { - // console.log('-x-x--x-x-x-x-x-x-x-x-x- dbPara', util.inspect(dbPara, { depth: null })); - await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: dbPara }); - await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { curLayer: layer } }) - await RougelikeLayerModel.updateByGameCodeAndLayer(gameCode, layer, detailCode, ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) - } - - let curNode = { detailCode, nodeId, nodeType, status, warId, reward, shops, challenge, question, restPoints, weightRecords } - // console.log('-x-x--x-x-x-x-x-x-x-x-x- curNode', util.inspect(curNode, { depth: null })); - return curNode; -} - - -/** - * 获取当前层当前节点奖励 - * @param gameCode - * @param detailCode - * @param nodeId 关卡id - * @param rewardPlan 赠送奖励id - * @returns - */ -export async function getLayerNodeReward(roleId: string, gameCode: string, type: number, nodeId: number, rewardPlan: number, layer: number, nodeType?: number) { - const nodeData = gameData.rougeNode.get(nodeId); - if (!nodeData) return; - if (!nodeType) nodeType = nodeData?.nodeType || 0; - - const layerRewardData = gameData.rougeLayerRewardPlan.get(rewardPlan + '_' + nodeType); - if (!layerRewardData) return; - let { charaPlan, charaRandomNum, charaChooseNum, - passiveCardPlan, charaPassivePlan, passiveCardRandomNum, passiveCardChooseNum, - holyCardPlan, holyCardRandomNum, holyCardChooseNum, - coin, score, tech } = layerRewardData; - - let dbRougelikeCards = await RougelikeCardModel.findByGameCodeAndType(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); - - let rewards: RougelikeRecordDetailType['rewards'] = []; - - let charaCards = getCharaCardPlan(charaPlan, charaRandomNum); - if (charaCards && charaCards.length > 0) { - let tempOptions = [], index = 0; - for (let ele of charaCards) { - tempOptions.push({ - optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, - passiveCardIds: await getSelfPassiveCards(ele.cardId, charaPassivePlan, type, dbRougelikeCards, gameCode, roleId) - }) - } - rewards.push({ - groupIndex: rewards.length + 1, - rewardType: ROUGE_LIKE_CARD_TYPE.CHARA, - options: tempOptions, - groupStatus: charaChooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, - chooseNum: charaChooseNum, - reRandRewardCnt: 0, - }); - } - - passiveCardRandomNum = await getPassiveCardRandom(passiveCardChooseNum, passiveCardRandomNum, gameCode, layer, roleId); - let { passiveCards, passiveWeightRecords } = await getPassiveCardPlan(passiveCardPlan, passiveCardRandomNum, type, dbRougelikeCards, gameCode, roleId); - if (passiveCards && passiveCards.length > 0) { - let chooseNum = await getPassiveCardChooseNum(passiveCardChooseNum, passiveCardRandomNum, gameCode, layer, roleId); - rewards.push({ - groupIndex: rewards.length + 1, - rewardType: ROUGE_LIKE_CARD_TYPE.PASSIVE, - options: passiveCards.map((ele, index) => { return { optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE } }), - groupStatus: chooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, - chooseNum, - reRandRewardCnt: 0, - }); - } - - let { holyCards, holyWeightRecords } = await getHolyCardPlan(holyCardPlan, holyCardRandomNum, dbRougelikeCards, gameCode, roleId); - if (holyCards && holyCards.length > 0) { - rewards.push({ - groupIndex: rewards.length + 1, - rewardType: ROUGE_LIKE_CARD_TYPE.HOLY, - options: holyCards.map((ele, index) => { return { optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE } }), - groupStatus: holyCardChooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, - chooseNum: holyCardChooseNum, - reRandRewardCnt: 0, - }); - } - - // rewards.push({ groupIndex: rewards.length + 1, rewardType: 0, groupStatus: (coin || 0) > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, chooseNum: coin || 0 }) - - return { rewards, score, techScore: tech, weightRecords: [...(passiveWeightRecords || []), ...(holyWeightRecords || [])] }; -} - -// 处理挑战类型中 接下来X次选择特性卡时,可选择的卡片数量少1 -export async function getPassiveCardRandom(passiveCardChooseNum: number, passiveCardRandomNum: number, gameCode: string, layer: number, roleId: string) { - let num = passiveCardRandomNum; - let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); - if (dbDetails.length == 0) return num; - for (let { challenge } of dbDetails) { - if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { - let { challengeId } = challenge; - const rougeChallengeData = gameData.rougeChallenge.get(challengeId); - if (!rougeChallengeData) return num; - for (let effectId of (rougeChallengeData.effectId || [])) { - const rougeEffectTypeData = gameData.rougeEffect.get(effectId); - if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; - num -= (rougeEffectTypeData.effectParam[1] || 0); - } - } - } - - return num >= 0 ? num : 0; -} - -export async function getPassiveCardChooseNum(passiveCardChooseNum: number, passiveCardRandomNum: number, gameCode: string, layer: number, roleId: string) { - let chooseNum = passiveCardChooseNum; - let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); - if (dbDetails.length == 0) return chooseNum; - - // for (let { challenge } of dbDetails) { - // if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { - // let { challengeId } = challenge; - // const rougeChallengeData = gameData.rougeChallenge.get(challengeId); - // if (!rougeChallengeData) return chooseNum; - // for (let effectId of (rougeChallengeData.effectId || [])) { - // const rougeEffectTypeData = gameData.rougeEffect.get(effectId); - // if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; - // chooseNum -= (rougeEffectTypeData.effectParam[1] || 0); - // } - // } - // } - chooseNum += await getAddChoosePassive(roleId, gameCode); - - if (chooseNum < 0) chooseNum = 0; - if (chooseNum > passiveCardRandomNum) chooseNum = passiveCardRandomNum; - - return chooseNum; -} - -/** - * 获取高级角色卡自带特性 - * @param charaId - * @param passiveCardPlan - * @param passiveCardRandomNum - * @param type - * @param dbRougelikeCards - * @returns - */ -export async function getSelfPassiveCards(charaId: number, passiveCardPlan: number, type: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { - let result: number[] = []; - let charaData = gameData.rougeChara.get(charaId); - if (!charaData) return result; - if (charaData.charaType != ROUGE_CHARA_TYPE.HIGH) return result; - let { passiveCards } = await getPassiveCardPlan(passiveCardPlan, charaData.initCardCnt, type, dbRougelikeCards, gameCode, roleId); - if (passiveCards && passiveCards.length > 0) result.push(...passiveCards.map((ele) => { return ele.cardId }),); - - return result; -} - -/** - * 获取当前层当前节点商店数据 - * @param gameCode - * @param detailCode - * @param nodeId - * @param shopPlan - * @returns - */ -export async function getLayerShopReward(roleId: string, gameCode: string, type: number, nodeId: number, shopPlan: number) { - let shops: RougelikeRecordDetailType['shops'] = []; - let shopPlanData = gameData.rougeShopPlan.get(shopPlan); - // let nodeData = gameData.rougeNode.get(nodeId); - - if (!shopPlanData) return { shops }; - - - let dbRougelikeCards = await RougelikeCardModel.findByGameCodeAndType(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); - - let { passiveCards, passiveWeightRecords } = await getPassiveCardPlan(shopPlanData.passivecardPlanId, shopPlanData.passiveCardRandomNum, type || 0, dbRougelikeCards, gameCode, roleId); - let index = 0, discount = await getShopDiscount(roleId, gameCode); - if (passiveCards && passiveCards.length > 0) { - for (let ele of passiveCards) { - let price = gameData.rougePassiveCard.get(ele.cardId)?.price || 0 - shops.push({ - optionIndex: shops.length + index, - rewardType: ROUGE_LIKE_CARD_TYPE.PASSIVE, - rewardId: ele.cardId, - optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, - price, - discountPrice: Math.floor(price * discount / 100), - }) - index++; - } - } - - let { holyCards, holyWeightRecords } = await getHolyCardPlan(shopPlanData?.holyCardPlanId, shopPlanData?.holyCardRandomNum, dbRougelikeCards, gameCode, roleId); - if (holyCards && holyCards.length > 0) { - for (let ele of holyCards) { - let price = gameData.rougeHolyCard.get(ele.cardId)?.purchasePrice || 0; - shops.push({ - optionIndex: shops.length + index, - rewardType: ROUGE_LIKE_CARD_TYPE.HOLY, - rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, - price, - discountPrice: Math.floor(price * discount / 100), - }) - index++; - } - } - - return { shops, weightRecords: [...(passiveWeightRecords || []), ...(holyWeightRecords || [])] }; -} - - - -/** - * 检测配置数据是否满足随机数量 - * @param planId - * @param randomNum - * @returns - */ -export function checkRandomLimit(planId: number, randomNum: number, rewardType: number) { - let cards: DicRougeCharaCardPlan[] = []; - if (!planId || planId == 0 || !randomNum || randomNum == 0) return cards; - - let cardPlanDatas = gameData.rougeCharaCardPlan.get(planId); - if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE) cardPlanDatas = gameData.rougePassiveCardPlan.get(planId); - else if (rewardType == ROUGE_LIKE_CARD_TYPE.HOLY) cardPlanDatas = gameData.rougeHolyCardPlan.get(planId); - - if (!cardPlanDatas) return cards; - else if (cardPlanDatas.length < randomNum) { - console.error("checkRandomLimit可随机的角色卡数量少于需要数量, planId=%s, randomNum=%s", planId, randomNum); - return cardPlanDatas; - } - else if (cardPlanDatas.length >= randomNum) return cardPlanDatas; - - return cards; -} - -/** - * 获取角色卡随机 - * @param planId - * @param charaRandomNum - * @returns - */ -export function getCharaCardPlan(planId: number, charaRandomNum: number) { - let cards = checkRandomLimit(planId, charaRandomNum, ROUGE_LIKE_CARD_TYPE.CHARA); - if (cards.length <= charaRandomNum) return cards; - let randResult = getRandEelmWithWeightAndNum(cards, charaRandomNum); - return randResult.map(cur => cur.dic); -} - - -/** - * 获取特性卡随机 - * @param passiveCardPlan - * @param passiveCardRandomNum - */ -export async function getPassiveCardPlan(passiveCardPlan: number, passiveCardRandomNum: number, type: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { - let cards = checkRandomLimit(passiveCardPlan, passiveCardRandomNum, ROUGE_LIKE_CARD_TYPE.PASSIVE); - // if (cards.length <= passiveCardRandomNum) return { passiveCards: cards }; - if (cards.length == 0) return { passiveCards: cards }; - - // 计算变化权重 - let lableMap = new Map(); //统计lable数量 - if (dbRougelikeCards && dbRougelikeCards.length > ROUGELIKE.PASSIVE_LABLE_NUM) { - for (let { cardId } of dbRougelikeCards) { - if (!cardId) continue; - - let passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData || !passiveCardData.passiveLabel || passiveCardData.passiveLabel.length == 0) continue; - - for (let val of passiveCardData.passiveLabel) { - if (!lableMap.get(val)) { - lableMap.set(val, 1); - continue; - } - lableMap.set(val, lableMap.get(val) + 1); - } - } - } - - let newCards = []; - let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); - const { chooseCardsMap, noChooseCardsMap } = await getIsChooseCard(gameCode); - - let isHolyAddWeight = false; - for (let obj of cards) { - let { cardId, weight } = obj || {}; - let passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData || !passiveCardData.authorType) continue; - if (passiveCardData.authorType == type) { - isHolyAddWeight = true; - break; - } - } - let holyAddWeight = 0; - if (isHolyAddWeight) { - holyAddWeight = await getAddPassiveWeight(roleId, gameCode, type); - } - - for (let obj of cards) { - let weightRecord: { originalWight?: number, passiveRedWight?: number, holyAddWeight?: number, passiveLableNum?: number, authorAddWeight?: number, passiveLableNumAddWeight?: number, finalWeight?: number } = {}; - if (!obj) continue; - let { cardId, weight } = obj; - if (!cardId || !weight) continue; - - let passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData) continue; - const getLimit = cardsMap.get(cardId) || 0; - if (getLimit >= (passiveCardData?.getLimit || 0)) continue; //处理限制获取数量 - - weightRecord.originalWight = weight; - - if (chooseCardsMap.has(cardId)) { - weight = Math.floor(weight * (1 - ROUGELIKE.SELECT_PASSIVECARD_WEIGHT / 100)); - weightRecord.passiveRedWight = Math.floor(weight * ROUGELIKE.SELECT_PASSIVECARD_WEIGHT / 100); - } - else if (noChooseCardsMap.has(cardId)) { - weight = Math.floor(weight * (1 - ROUGELIKE.RANDOM_PASSIVECARD_WEIGHT / 100)); - weightRecord.passiveRedWight = Math.floor(weight * ROUGELIKE.RANDOM_PASSIVECARD_WEIGHT / 100); - } - - const { authorType = 0, quality = 0, lv = 0 } = passiveCardData; - if (authorType == type) { - weight += holyAddWeight; - weightRecord.holyAddWeight = holyAddWeight; - - const passiveWeightData = gameData.rougePassiveWeight.get(authorType + '_' + quality + '_' + lv); - if (passiveWeightData && passiveWeightData.authorTypeWeightAdd) { - weight += passiveWeightData.authorTypeWeightAdd; - weightRecord.authorAddWeight = passiveWeightData.authorTypeWeightAdd; - } - } - - - let labelNum = lableMap.get(cardId) || 0; - if (labelNum >= ROUGELIKE.PASSIVE_LABLE_NUM) { - weight += ROUGELIKE.PASSIVE_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.PASSIVE_LABLE_NUM)); - weightRecord.passiveLableNum = labelNum; - weightRecord.passiveLableNumAddWeight = ROUGELIKE.PASSIVE_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.PASSIVE_LABLE_NUM)); - } - - weightRecord.finalWeight = weight; - - newCards.push({ ...obj, weight, weightRecord }); - } - - let targetPassives = await getChooseQualityPassives(roleId, gameCode, newCards); - let result = []; - if (passiveCardRandomNum >= 1 && targetPassives.length > 0) result.push(getRandEelmWithWeight(targetPassives).dic); - - let randResult = getRandEelmWithWeightAndNum(newCards, passiveCardRandomNum - result.length); - - return { passiveCards: [...result, ...randResult.map(cur => cur.dic)], passiveWeightRecords: newCards } -} - -export async function getIsChooseCard(gameCode: string) { - const dbDetails = await RougelikeRecordDetailModel.findByGameCode(gameCode); - let chooseCardsMap = new Map(); - let noChooseCardsMap = new Map(); - for (const { rewards } of dbDetails) { - if (!rewards || rewards.length == 0) continue; - for (const { options } of rewards) { - if (!options || options.length == 0) continue; - for (const { rewardId, optionStatus } of options) { - if (optionStatus != 0) { - chooseCardsMap.set(rewardId, rewardId); - continue; - } - noChooseCardsMap.set(rewardId, rewardId); - } - } - } - return { chooseCardsMap, noChooseCardsMap }; -} - - -export async function getCardCount(gameCode: string, type: number) { - const dbCards: RougelikeCardType[] = await RougelikeCardModel.findByGameCodeAndType(gameCode, type); - let cardsMap = new Map(); - dbCards.forEach((cur) => { cardsMap.set(cur.cardId, (cardsMap.get(cur.cardId) || 0) + 1); }) - return cardsMap; -} - -/** - * 获取圣物随机 - * @param planId - * @param holyCardPlan - */ -export async function getHolyCardPlan(holyCardPlan: number, holyCardRandomNum: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { - - let cards = checkRandomLimit(holyCardPlan, holyCardRandomNum, ROUGE_LIKE_CARD_TYPE.HOLY); - // if (cards.length <= holyCardRandomNum) return { holyCards: cards }; - if (cards.length == 0) return { holyCards: cards }; - - let lableMap = new Map();//统计lable数量 - if (dbRougelikeCards && dbRougelikeCards.length > ROUGELIKE.HOLY_LABLE_NUM) { - for (let { cardId } of dbRougelikeCards) { - if (!cardId) continue; - - let passiveCardData = gameData.rougePassiveCard.get(cardId); - if (!passiveCardData || !passiveCardData.holyLabel || passiveCardData.holyLabel.length == 0) continue; - - for (let val of passiveCardData.holyLabel) { - if (!lableMap.get(val)) { - lableMap.set(val, 1); - continue; - } - lableMap.set(val, lableMap.get(val) + 1); - } - } - } - // 计算变化权重 - let newCards = []; - let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); - const { chooseCardsMap, noChooseCardsMap } = await getIsChooseCard(gameCode); - for (let obj of cards) { - let weightRecord: { - originalWight?: number, passiveRedWight?: number, holyRedWight?: number, authorAddWeight?: number, - passiveLableNum?: number, passiveLableNumAddWeight?: number, holyLableNum?: number, holyLableNumAddWeight?: number, - finalWeight?: number - } = {}; - - if (!obj) continue; - let { cardId, weight } = obj; - if (!cardId || !weight) continue; - - let holyCardData = gameData.rougeHolyCard.get(cardId); - if (!holyCardData) continue; - const getLimit = cardsMap.get(cardId) || 0; - if (getLimit >= (holyCardData?.getLimit || 0)) continue; //处理限制获取数量 - - weightRecord.originalWight = weight; - - if (chooseCardsMap.has(cardId)) { - weight = Math.floor(weight * (1 - ROUGELIKE.SELECT_HOLLYCARD_WEIGHT / 100)); - weightRecord.holyRedWight = Math.floor(weight * ROUGELIKE.SELECT_HOLLYCARD_WEIGHT / 100); - } - else if (noChooseCardsMap.has(cardId)) { - weight = Math.floor(weight * (1 - ROUGELIKE.RANDOM_HOLLYCARD_WEIGHT / 100)); - weightRecord.holyRedWight = Math.floor(weight * ROUGELIKE.RANDOM_HOLLYCARD_WEIGHT / 100); - } - if (!holyCardData.label) { - newCards.push({ ...obj }); - weightRecord.finalWeight = weight; - continue; - }; - - let labelNum = lableMap.get(holyCardData.label) || 0; - if (labelNum < ROUGELIKE.HOLY_LABLE_NUM || ROUGELIKE.HOLY_LABLE_NUM == 0) { - newCards.push({ ...obj }); - weightRecord.finalWeight = weight; - continue; - }; - - weight += ROUGELIKE.HOLY_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.HOLY_LABLE_NUM)); - - weightRecord.holyLableNum = labelNum; - weightRecord.holyLableNumAddWeight = ROUGELIKE.HOLY_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.HOLY_LABLE_NUM)); - weightRecord.finalWeight = weight; - - newCards.push({ ...obj, weight, weightRecord }); - } - - let randResult = getRandEelmWithWeightAndNum(newCards, holyCardRandomNum); - return { holyCards: randResult.map(cur => cur.dic), holyWeightRecords: newCards } -} - - -/** - * 获取挑战关卡数据 - * @param planId - * @returns - */ -export function getChallenge(planId: number) { - const randomChallenge = getChallengePlan(planId); - if (!randomChallenge) return; - - const rougeChallengeData = gameData.rougeChallenge.get(randomChallenge.challengeId); - if (!rougeChallengeData) return; - - return rougeChallengeData; -} - -/** - * 获取挑战关随机 - * @param planId - * @returns - */ -export function getChallengePlan(planId: number) { - const challengePlanData = gameData.rougeChallengePlan.get(planId); - if (!challengePlanData) return; - if (challengePlanData.length == 1) return challengePlanData[0]; - - return getRandEelmWithWeight(challengePlanData).dic; -} - - -export async function updateChalleng(dbRecord: RougelikeRecordType, roleId: string, sid: string, gameCode: string, curLayer: number, rougeDamage, isAp?: boolean, isRound?: boolean) { - let len = rougeDamage.length; - let challenges: { challengeId: number, status: number, progress: number, detailCode: string }[] = []; - const { authorType, type, grade } = dbRecord; - let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, curLayer); - if (dbDetails.length == 0) return true; - - let updateChallengs: RougelikeRecordDetailPara[] = []; - for (let { detailCode, challenge, rewards = [], nodeId, layer } of dbDetails) { - if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { - let { challengeId } = challenge; - - const rougeChallengeData = gameData.rougeChallenge.get(challengeId); - if (!rougeChallengeData) return true; - for (let effectId of (rougeChallengeData.effectId || [])) { - const rougeEffectTypeData = gameData.rougeEffect.get(effectId); - if (len == 0) { - //接下来X次选择特性卡时,可选择的卡片数量少1 - if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; - } else { - if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; - if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NO_AP_SKILL && isAp) continue; - if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NO_ROUND_SKILL && isRound) continue; - if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_HP_LIMIT) { - let isNext = true; - for (let obj of rougeDamage) { - const { maxHp = 0, hp = 0 } = (obj || {}); - if (maxHp == 0 || hp == 0) { isNext = false; break; } - if (maxHp * (rougeEffectTypeData.effectParam[1] || 0) / 100 > hp) { isNext = false; break; } - } - - if (!isNext) continue; - } - - if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NUM_LIMIT && (rougeEffectTypeData.effectParam[1] || 0) < len) continue;//接下来X场战斗,每场战斗不超过上阵2名学员 - } - - challenge.progress += 1; - - - if (challenge.progress == rougeChallengeData.condition) { - challenge.status = 2; - - //处理在挑战进度完成时再随机奖励 - // const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - // if (!typeGradeData) continue; - // const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); - // if (!layerPlanData) continue; - // let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer); - // rewards = result.rewards; - - }; - } - challenges.push({ challengeId, status: challenge.status, progress: challenge.progress, detailCode }); - updateChallengs.push({ gameCode, detailCode, challenge, status: 1 }); - } - } - - await RougelikeRecordDetailModel.bulkWriteUpdate(updateChallengs); - - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ROUGE_CHALLENGE_UPDATE, { challenges }, sid); - - return true; -} - -export function getLayerRewardOneData(type: number, grade: number, layer: number, nodeType: number) { - let result: { takeoutReward?: RewardInter[], coin?: number, score?: number, tech?: number, spiritPlan?: RewardInter[] } = {}; - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - if (!typeGradeData) return result; - const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); - if (!layerPlanData) return result; - result = { takeoutReward: layerPlanData.takeoutReward, spiritPlan: layerPlanData.spiritPlan } - - const layerRewardData = gameData.rougeLayerRewardPlan.get(layerPlanData.rewardPlan + '_' + nodeType); - if (!layerRewardData) return result; - result = { ...layerRewardData, ...result }; - - return result; -} - -export function getRandomSpirit(spiritPlan: number, randomNum: number) { - let spiritId: number[] = []; - const spiritPlanData = gameData.spiritPlan.get(spiritPlan); - if (randomNum == 0 || !spiritPlanData || spiritPlanData.length == 0) return spiritId; - let random = getRandEelmWithWeightAndNum(spiritPlanData, randomNum); - for (let cur of random) { - if (cur.dic && cur.dic.spiritId) spiritId.push(cur.dic.spiritId) - } - - return spiritId; -} - -/** - * 获取 - * @param authorType - * @param cards - * @returns - */ -export function getAuthorTypeCardNum(authorType: number, cards: Card[]) { - return cards.filter(card => { - let dicCard = card.cardId == 0 ? null : gameData.rougePassiveCard.get(card.cardId); - if (!dicCard) return false; - return dicCard.authorType == authorType; - }).length; -} - -export async function repaireSendScoreReward() { - let refTime = new Date(getZeroPointOfTimeD(Date.now() + 1 * 60 * 60 * 1000, SHOP_REFRESH_TYPE.WEEKLY).getTime() - (86400000 * 7)); - let allRewards = await RougelikeScoreModel.findByRefTime(refTime); - let updateArr: RougelikeScorePara[] = []; - - const roleIds = allRewards.map(cur => { return cur.roleId }); - const lastMaxLvMap = await RougelikeExtendModel.getLastMaxLvMap(roleIds); - for (let { roleId, received, score, receiveNum } of allRewards) { - let lastMaxLv = lastMaxLvMap.get(roleId) ? lastMaxLvMap.get(roleId) : 1; - let goods: RewardInter[] = []; - const rougeScoreRewardByLvData = gameData.rougeScoreRewardByLv.get(lastMaxLv); - if (receiveNum >= rougeScoreRewardByLvData.size) continue; - for (let [index, { reward, score: targetScore }] of rougeScoreRewardByLvData) { - if (score >= targetScore && !received.includes(index)) { - goods.push(...reward); - received.push(index); - } - } - if (goods.length > 0) { - await sendMailByContent(MAIL_TYPE.ROUGE_SCORE_REPAIRE, roleId, { goods }); - updateArr.push({ roleId, refTime, receiveNum: rougeScoreRewardByLvData.size, received }); - } - } - await RougelikeScoreModel.bulkWriteUpdate(updateArr); -} - -/** - * 获取最大血量 - * @param charaId - * @param type - * @param grade - * @returns - */ -export async function getMaxHp(roleId: string, gameCode: string, charaId: number, type: number, grade: number,) { - let maxHp = 0; - const charaData = gameData.rougeChara.get(charaId); - if (!charaData || !charaData.heroId) return maxHp; - const heroData = gameData.hero.get(charaData.heroId); - // console.log("x-x-x-x--x-xx- heroData", heroData); - if (!heroData || !heroData.hp) return maxHp; - - const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); - // console.log("x-x-x-x--x-xx- typeGradeData", typeGradeData); - - if (!typeGradeData || !typeGradeData.heroValue) return maxHp; - - let rougeEffect = new RougeEffect(roleId, gameCode); - const holyMaxHp = await rougeEffect.getEffectMaxHp(); - - - maxHp = heroData.hp * typeGradeData.heroValue / 10000 * (1 + holyMaxHp / 100); - - return Math.floor(maxHp); -} - -export async function updateMaxHp(roleId: string, gameCode: string, type: number, grade: number, updateCharasMap?: Map) { - let dbCharas = await RougelikeCharaModel.findByGameCode(gameCode); - if (dbCharas.length == 0) return []; - - let result: RougelikeCharaType[] = []; - for (let val of dbCharas) { - if (updateCharasMap && updateCharasMap.has(val.charaCode)) { - val = { ...val, ...updateCharasMap.get(val.charaCode) } - } - let tempMaxHp = await getMaxHp(roleId, gameCode, val.charaId, type, grade); - if (tempMaxHp == val.maxHp && updateCharasMap && !updateCharasMap.has(val.charaCode)) continue; - let preMaxHp = val.maxHp; - val.maxHp = tempMaxHp; - if (val.hp > 0) { - val.hp = Math.min(val.hp + tempMaxHp - preMaxHp, tempMaxHp); - } - result.push(val); - } - await RougelikeCharaModel.bulkWriteUpdate(result); - let { charas } = formateCharasOrCards(result, ROUGE_LIKE_CARD_TYPE.CHARA) - return charas || []; -} - - -// 获取当前层之前所有未完成挑战关 -export async function getPreCurLayerChallengs(gameCode: string, layer: number) { - let challenges: { challengeId: number, status: number, progress: number, detailCode: string, reward: CommonReward }[] = []; - let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); - if (dbDetails.length == 0) return challenges; - for (let { detailCode, challenge, rewards } of dbDetails) { - if (!challenge) continue; - const { challengeId, status, progress } = challenge; - if (status == 3) continue; - challenges.push({ challengeId, status, progress, detailCode, reward: { rewards } }); - } - - return challenges; -} - -export async function getGame(roleId: string) { - let isPlaying = true, nodes: RougelikeLayerType[] = [], hasPass = false, curNode = {}; - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); - if (!dbRecord) { - isPlaying = false; - return { isPlaying }; - } - const { gameCode, grade, type, authorType = 0, curLayer = 0, maxLayer = 0, coin = 0, score = 0, techScore = 0, coinTotal = 0 } = dbRecord; - - const dbNodes = await RougelikeLayerModel.findByGameCode(gameCode); - let dbCurLayerChooseNode = {} as layerNode; - if (dbNodes) nodes = dbNodes.map((obj) => { - const { layer, layerNodes, hasPass: dbHasPass = false } = obj; - if (layer == curLayer) { - hasPass = dbHasPass; - dbCurLayerChooseNode = layerNodes.find(cur => cur.isChoose == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE); - } - return { layer, layerNodes } as RougelikeLayerType - }) - - const charas: CommonChara[] = formateCharasOrCards(await RougelikeCharaModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; - const cards: CommonCard[] = formateCharasOrCards(await RougelikeCardModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.PASSIVE | ROUGE_LIKE_CARD_TYPE.HOLY)?.cards || []; - - // console.log("x-x-x-x-x-x-x-x- dbCurLayerChooseNode", dbCurLayerChooseNode) - if (Object.entries(dbCurLayerChooseNode).length != 0) curNode = await chooseNode(dbRecord, dbCurLayerChooseNode, curLayer) - - return { - isPlaying, gameCode, grade, type, authorType, - curLayer, hasPass, maxLayer, coin, coinTotal, score, techScore, nodes: nodes || [], charas, cards, curNode, - preChallengs: await getPreCurLayerChallengs(gameCode, curLayer) - }; -} \ No newline at end of file +import { clone, result } from "underscore"; +import { ROUGE_CHARA_INITIAL, ROUGE_CHARA_TYPE, ROUGE_EFFECT_TYPE, ROUGE_LIKE_CARD_TYPE, ROUGE_LIKE_CHOOSE_REWARD, ROUGE_LIKE_NODE_TYPE, ROUGE_LIKE_STATUS, SHOP_REFRESH_TYPE } from "@consts"; +import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from "@db/RougelikeChara"; +import { RougelikeLayerModel, RougelikeLayerType } from "@db/RougelikeLayer"; +import { RougelikeRecordModel, RougelikeRecordType } from "@db/RougelikeRecord"; +import { gameData } from "@pubUtils/data"; +import { ROUGELIKE } from "@pubUtils/dicParam"; +import { genCode, getRandEelm, getRandEelmWithWeight, getRandEelmWithWeightAndNum, getRandValueByMinMax } from "@pubUtils/util"; +import { RougelikeCardModel, RougelikeCardType } from "@db/RougelikeCard"; +import RougelikeRecordDetail, { RougelikeRecordDetailModel, RougelikeRecordDetailPara, RougelikeRecordDetailType } from "@db/RougelikeRecordDetail"; +import { CollectionReturnParam, CommonCard, CommonChara, CommonNode, CommonReward, RewardInter, layerNode } from "@pubUtils/interface"; +import { DicRougeQuestionMarkPlan } from "@pubUtils/dictionary/DicRougeQuestionMarkPlan"; +import { DicRougeRandomEventPlan } from "@pubUtils/dictionary/DicRougeRandomEventPlan"; +import * as util from 'util'; +import { RougelikeCollectionModel, } from "@db/RougelikeCollection"; +import { RougelikeScoreModel, RougelikeScorePara } from "@db/RougelikeScore"; +import { getTechData } from "./rougeTechService"; +import { getZeroPointOfTimeD } from "@pubUtils/timeUtil"; +import { sendMailByContent } from "../mailService"; +import { MAIL_TYPE, PUSH_ROUTE } from "@consts"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { RougeEffect, getAddChoosePassive, getAddPassiveWeight, getChooseQualityPassives, getShopDiscount } from "./rougeEffectService"; +import { formateCharasOrCards } from "./rougeCollectService"; +import { errlogger } from "../../util/logger"; +import { RougelikeExtendModel } from "@db/RougelikeExtend"; +import { isDevelopEnv } from "../utilService"; +import { DicRougeCharaCardPlan } from "@pubUtils/dictionary/DicRougeCharaCardPlan"; + +export async function getRougeData(roleId: string) { + + let isPlaying = true, gameCode = ''; + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); + if (!dbRecord) isPlaying = false; + else gameCode = dbRecord.gameCode; + + let dbScore = await RougelikeScoreModel.findByRoleId(roleId); + let techData = await getTechData(roleId); + + let dbCollections = await RougelikeCollectionModel.findByRoleId(roleId); + let collections = dbCollections.map((obj) => new CollectionReturnParam(obj)); + + const dbExtends = await RougelikeExtendModel.findByRoleId(roleId); + const limitIds = dbExtends.map(cur => cur.limitId); + const lastMaxLv = await RougelikeExtendModel.getLastMaxLv(roleId); + return { isPlaying, gameCode, weeklyScore: dbScore?.score || 0, receivedScore: dbScore?.received || [], ...techData, collections, limitIds, takeoutRewardCnt: dbScore?.takeoutRewardCnt, lastMaxLv } +} + +/* +/** + * 获取初始三名角色卡 + * @param + * @returns + */ +export function getInitCharaCard() { + let canRandomCharas = gameData.rougeCharaByInitial.get(ROUGE_CHARA_INITIAL.CAN); + if (!canRandomCharas || canRandomCharas.length < ROUGELIKE.INIT_RANDOM_CHARA_COUNT) { + console.error("getInitChara--配置表中能初始随机的角色卡不足, canRandomCharas=%s", canRandomCharas); + return; + } + + let randomData = getRandEelm(canRandomCharas, ROUGELIKE.INIT_RANDOM_CHARA_COUNT) + + return randomData; +} + +/** + * 获取大地图生成数据 + * @param layerPlan + * @param layerCount + */ +export function getMap(layerPlan: number, layerCount: number) { + let retLayer = getLayerNodeRandom(layerPlan, layerCount); + if (!retLayer) return []; + return getLayerNodeLineRandom(retLayer) || []; + +} +export function getLayerNodeRandom(layerPlan: number, layerCount: number) { + if (!layerPlan || !layerCount) return; + + const layerPlanDatas = gameData.rougeLayerPlanByPlanId.get(layerPlan); + if (!layerPlanDatas || layerPlanDatas.length != layerCount) return console.error("getMap--获取配置层数不一致, layerPlan=%s, layerCount=%s", layerPlan, layerCount); + + let retLayer = new Map(); + + //获取可随机到的节点 + for (let data of layerPlanDatas) { + let layerNodeNumPlanDatas = gameData.rougeLayerNodeNumPlan.get(data.nodeNumPlan); + if (!layerNodeNumPlanDatas) return console.error("getMap--rougeLayerNodeNumPlan配置错误, planId=%s", data.nodeNumPlan); + let nodeNum = 0; + if (layerNodeNumPlanDatas.length == 1) nodeNum = 1; + else nodeNum = getRandEelmWithWeight(layerNodeNumPlanDatas).dic.nodeNum; + + let layerNodePlans = gameData.rougeLayerNodePlan.get(data.nodePlan); + if (!layerNodePlans || layerNodePlans.length == 0) return console.error("getMap--rougeLayerNodePlan配置错误, planId=%s", data.nodePlan); + + let randomNodes: CommonNode['layerNodes'] = [], tempIndex = 0; + if (layerNodePlans.length > nodeNum) { + randomNodes = getRandEelmWithWeightAndNum(layerNodePlans, nodeNum).map((cur) => { + let nodeId = cur.dic.nodeId; + let nodeData = gameData.rougeNode.get(nodeId); + if (!nodeData) errlogger.error(`nodePlane ${data.nodePlan} 's nodeId ${nodeId} not found`); + return { detailCode: genCode(8), index: tempIndex++, nodeId, preNodeIndexs: [], type: nodeData.nodeType, isChoose: 0 }; + }); + } else { + randomNodes = layerNodePlans.map((cur) => { + let nodeId = cur.nodeId; + let nodeData = gameData.rougeNode.get(nodeId); + return { detailCode: genCode(8), index: tempIndex++, nodeId: cur.nodeId, preNodeIndexs: [] as number[], type: nodeData.nodeType, isChoose: 0 }; + }); + } + + retLayer.set(data.layerIndex, { layer: data.layerIndex, layerNodes: randomNodes }); + } + // console.log('-x-x--x-x-x-x-x-x-x-x-x- retLayer', util.inspect(retLayer, { depth: null })); + return retLayer; +} + +/** + * 随机节点连线 + * @param retLayer + * @returns + */ +export function getLayerNodeLineRandom(retLayer: Map) { + for (let [key, value] of retLayer) { + let preLayer = retLayer.get(key - 1); + let curLayer = retLayer.get(key); + if (!preLayer || !curLayer) continue; + let tempPreNodes = preLayer.layerNodes; // 前一层节点数据 + let tempCurNodes = curLayer.layerNodes; // 当前层节点数据 + let indexMap = new Map(); //记录下前一层有那些节点与当前层是否连线 + + //当前层首节点 + tempCurNodes[0].preNodeIndexs.push(tempPreNodes[0].index); + indexMap.set(tempPreNodes[0].index, { dx: 0, index: tempCurNodes[0].index }); + + //当前层尾节点 + if (!(tempCurNodes.length == 1 && tempPreNodes.length == 1)) { + tempCurNodes[tempCurNodes.length - 1].preNodeIndexs.push(tempPreNodes[tempPreNodes.length - 1].index); + indexMap.set(tempPreNodes[tempPreNodes.length - 1].index, { dx: tempCurNodes.length - 1, index: tempCurNodes[tempCurNodes.length - 1].index }); + } + + for (let i = 0; i < tempCurNodes.length - 1; i++) { + let minIndex = 0, maxIndex = 0, start = 0; + if (i != 0) start = minIndex = maxIndex = Math.max(...tempCurNodes[i - 1].preNodeIndexs); + if (tempPreNodes[start + 1]) maxIndex = tempPreNodes[start + 1].index; + if (tempPreNodes[start + 2]) maxIndex = tempPreNodes[start + 2].index; + + let randomIndex = minIndex; + if (minIndex < maxIndex) randomIndex = getRandValueByMinMax(minIndex, maxIndex + 1, 0); + + if (tempCurNodes[i].preNodeIndexs.indexOf(randomIndex) != -1) continue; + tempCurNodes[i].preNodeIndexs.push(randomIndex); + if (indexMap.get(randomIndex) && indexMap.get(randomIndex).dx < i) continue; + indexMap.set(randomIndex, { dx: i, index: tempCurNodes[i].index }); + } + + //处理前一层有节点未连接情况 + for (let i = 1; i < tempPreNodes.length - 1; i++) { + if (indexMap.get(tempPreNodes[i].index)) continue; + + let minDx = 0, maxDx = 0; + let tempMap = new Map(); + + if (tempPreNodes[i - 1] && indexMap.get(tempPreNodes[i - 1].index)) { + minDx = maxDx = indexMap.get(tempPreNodes[i - 1].index).dx + for (let j = 0; j < tempCurNodes.length; j++) { + if (tempPreNodes[i - 1] && tempCurNodes[j].preNodeIndexs.indexOf(tempPreNodes[i - 1].index) != -1) minDx = maxDx = Math.max(minDx, j); + } + tempMap.set(minDx, indexMap.get(tempPreNodes[i - 1].index).index); + } + if (tempPreNodes[i + 1] && indexMap.get(tempPreNodes[i + 1].index)) { + maxDx = indexMap.get(tempPreNodes[i + 1].index).dx + tempMap.set(maxDx, indexMap.get(tempPreNodes[i + 1].index).index); + } + + let randomDx = minDx; + if (minDx < maxDx) randomDx = getRandValueByMinMax(minDx, maxDx + 1, 0); + + tempCurNodes[randomDx].preNodeIndexs.push(tempPreNodes[i].index); + if (indexMap.get(tempPreNodes[i].index) && indexMap.get(tempPreNodes[i].index).dx < randomDx) continue; + indexMap.set(tempPreNodes[i].index, { dx: randomDx, index: tempMap.get(randomDx) }); + } + } + + // console.log('-x-x--x-x-x-x-x-x-x-x-x- [...retLayer.values()]', util.inspect([...retLayer.values()], { depth: null })); + + return [...retLayer.values()]; +} + +/** + * 选择节点 + * @param dbRecord + * @param layerChooseNode + * @returns + */ +export async function chooseNode(dbRecord: RougelikeRecordType, layerChooseNode: layerNode, layer: number) { + + const { roleId, gameCode, type, grade, curLayer, authorType } = dbRecord; + + const { detailCode, nodeId, } = layerChooseNode + let nodeType = layerChooseNode.type; + + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + const nodeData = gameData.rougeNode.get(nodeId); + if (!typeGradeData || !nodeData) return; + + const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); + // console.log("-x--x-x-x-x- nodeData", nodeData) + // console.log("-x--x-x-x-x- typeGradeData", typeGradeData) + // console.log("-x--x-x-x-x- layerPlanData", layerPlanData) + + + if (!layerPlanData) return; + + + let isReward = false, isShop = false; + let warId, reward = {} as CommonReward, shops: RougelikeRecordDetailType['shops'] = [], + challenge = {} as RougelikeRecordDetailType['challenge'], question = {} as RougelikeRecordDetail['question'], restPoints: RougelikeRecordDetail['restPoints'] = []; + + + const dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode); + let status = 0; + if (dbDetail) status = dbDetail.status || 0; + + let dbPara = { roleId, layer, nodeId, nodeType, status } as RougelikeRecordDetailPara; + + //普通关、精英关、boss关 + if (nodeType == ROUGE_LIKE_NODE_TYPE.ORDINARY || nodeType == ROUGE_LIKE_NODE_TYPE.ELITE || nodeType == ROUGE_LIKE_NODE_TYPE.BOSS) { + isReward = true; + warId = dbPara.warId = nodeData.param; + } + + //挑战关 + else if (nodeType == ROUGE_LIKE_NODE_TYPE.CHALLENGE) { + if (dbDetail) { + challenge = dbDetail.challenge; + } else { + let getChallengeData = getChallenge(typeGradeData.challengePlan); + if (getChallengeData) { + challenge = { challengeId: getChallengeData.challengeId, status: 1, progress: 0 } as RougelikeRecordDetailType['challenge']; + dbPara.challenge = challenge; + } + // isReward = true; + } + + } + + //商店 + else if (nodeType == ROUGE_LIKE_NODE_TYPE.SHOP) { + isShop = true; + } + + //休整点 + else if (nodeType == ROUGE_LIKE_NODE_TYPE.REST_POINT) { + isReward = true; + if (dbDetail && dbDetail.restPoints) restPoints = dbDetail.restPoints || restPoints; + else dbPara.restPoints = restPoints; + } + + //问号点 + else if (nodeType == ROUGE_LIKE_NODE_TYPE.QUEST_POINT) { + if (dbDetail) { + question = dbDetail.question || {} as RougelikeRecordDetail['question']; + warId = dbDetail.warId; + } + else { + const questionMarkPLanData = gameData.rougeQuestionMarkPlan.get(nodeData.param); + if (!questionMarkPLanData) return; + + let randomData = {} as DicRougeQuestionMarkPlan; + if (questionMarkPLanData.length == 1) randomData = questionMarkPLanData[0]; + else randomData = getRandEelmWithWeight(questionMarkPLanData).dic; + + dbPara.questType = randomData.nodeType; + if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.ORDINARY || randomData.nodeType == ROUGE_LIKE_NODE_TYPE.ELITE) { + isReward = true; + warId = dbPara.warId = randomData.param; + } + else if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.SHOP) { + isShop = true + } + else if (randomData.nodeType == ROUGE_LIKE_NODE_TYPE.EVENT) { + let random = {} as DicRougeRandomEventPlan; + const randomEventPlanData = gameData.rougeRandomEventPlan.get(typeGradeData.randomEventPlan); + if (!randomEventPlanData) return; + if (randomEventPlanData.length == 1) random = randomEventPlanData[0]; + else random = getRandEelmWithWeight(randomEventPlanData).dic; + question.randomEventId = random.randomEventId; + question.EventOptions = []; + dbPara.question = question; + } + } + } + + + let weightRecords = []; + if ((!dbDetail || !dbDetail.shops || dbDetail.shops.length == 0) && isShop) { + let result = await getLayerShopReward(roleId, gameCode, authorType, nodeId, layerPlanData.shopPlan); + dbPara.shops = shops = result.shops; + if (isDevelopEnv()) { + weightRecords = dbPara.weightRecords = (result?.weightRecords || []) + } + } + if (dbDetail && dbDetail.shops) { + shops = dbDetail.shops || shops; + if (isDevelopEnv()) { + weightRecords = dbDetail.weightRecords + } + } + + if ((!dbDetail || !dbDetail.rewards || dbDetail.rewards.length == 0) && isReward) { + let startTime = Date.now(); + let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer, dbPara.questType); + console.log('*********************************nodeType=%s getLayerNodeReward time=%s', nodeType, Date.now() - startTime) + if (result && result.rewards) { + reward = result; + dbPara.rewards = result.rewards; + + if (!isDevelopEnv() && reward && reward.weightRecords) { + reward.weightRecords = []; + } + } + + if (isDevelopEnv()) { + weightRecords = dbPara.weightRecords = (result?.weightRecords || []); + } + } + if (dbDetail && dbDetail.rewards) { + let tempType = (dbDetail?.questType || 0) > 0 ? dbDetail?.questType : nodeType + const layerRewardData = gameData.rougeLayerRewardPlan.get(layerPlanData.rewardPlan + '_' + tempType); + if (!layerRewardData) return; + let { coin, score, tech } = layerRewardData; + reward = { rewards: dbDetail.rewards || [], score: score || 0, techScore: tech || 0, takeoutReward: layerPlanData.takeoutReward || [] }; + + if (isDevelopEnv()) { + weightRecords = dbDetail.weightRecords + } + } + + if (!dbDetail) { + // console.log('-x-x--x-x-x-x-x-x-x-x-x- dbPara', util.inspect(dbPara, { depth: null })); + await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: dbPara }); + await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { curLayer: layer } }) + await RougelikeLayerModel.updateByGameCodeAndLayer(gameCode, layer, detailCode, ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) + } + + let curNode = { detailCode, nodeId, nodeType, status, warId, reward, shops, challenge, question, restPoints, weightRecords } + // console.log('-x-x--x-x-x-x-x-x-x-x-x- curNode', util.inspect(curNode, { depth: null })); + return curNode; +} + + +/** + * 获取当前层当前节点奖励 + * @param gameCode + * @param detailCode + * @param nodeId 关卡id + * @param rewardPlan 赠送奖励id + * @returns + */ +export async function getLayerNodeReward(roleId: string, gameCode: string, type: number, nodeId: number, rewardPlan: number, layer: number, nodeType?: number) { + const nodeData = gameData.rougeNode.get(nodeId); + if (!nodeData) return; + if (!nodeType) nodeType = nodeData?.nodeType || 0; + + const layerRewardData = gameData.rougeLayerRewardPlan.get(rewardPlan + '_' + nodeType); + if (!layerRewardData) return; + let { charaPlan, charaRandomNum, charaChooseNum, + passiveCardPlan, charaPassivePlan, passiveCardRandomNum, passiveCardChooseNum, + holyCardPlan, holyCardRandomNum, holyCardChooseNum, + coin, score, tech } = layerRewardData; + + let dbRougelikeCards = await RougelikeCardModel.findByGameCodeAndType(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); + + let rewards: RougelikeRecordDetailType['rewards'] = []; + + let charaCards = getCharaCardPlan(charaPlan, charaRandomNum); + if (charaCards && charaCards.length > 0) { + let tempOptions = [], index = 0; + for (let ele of charaCards) { + tempOptions.push({ + optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, + passiveCardIds: await getSelfPassiveCards(ele.cardId, charaPassivePlan, type, dbRougelikeCards, gameCode, roleId) + }) + } + rewards.push({ + groupIndex: rewards.length + 1, + rewardType: ROUGE_LIKE_CARD_TYPE.CHARA, + options: tempOptions, + groupStatus: charaChooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, + chooseNum: charaChooseNum, + reRandRewardCnt: 0, + }); + } + + passiveCardRandomNum = await getPassiveCardRandom(passiveCardChooseNum, passiveCardRandomNum, gameCode, layer, roleId); + let { passiveCards, passiveWeightRecords } = await getPassiveCardPlan(passiveCardPlan, passiveCardRandomNum, type, dbRougelikeCards, gameCode, roleId); + if (passiveCards && passiveCards.length > 0) { + let chooseNum = await getPassiveCardChooseNum(passiveCardChooseNum, passiveCardRandomNum, gameCode, layer, roleId); + rewards.push({ + groupIndex: rewards.length + 1, + rewardType: ROUGE_LIKE_CARD_TYPE.PASSIVE, + options: passiveCards.map((ele, index) => { return { optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE } }), + groupStatus: chooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, + chooseNum, + reRandRewardCnt: 0, + }); + } + + let { holyCards, holyWeightRecords } = await getHolyCardPlan(holyCardPlan, holyCardRandomNum, dbRougelikeCards, gameCode, roleId); + if (holyCards && holyCards.length > 0) { + rewards.push({ + groupIndex: rewards.length + 1, + rewardType: ROUGE_LIKE_CARD_TYPE.HOLY, + options: holyCards.map((ele, index) => { return { optionIndex: index++, rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE } }), + groupStatus: holyCardChooseNum > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, + chooseNum: holyCardChooseNum, + reRandRewardCnt: 0, + }); + } + + // rewards.push({ groupIndex: rewards.length + 1, rewardType: 0, groupStatus: (coin || 0) > 0 ? ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE : ROUGE_LIKE_CHOOSE_REWARD.CHOOSE, chooseNum: coin || 0 }) + + return { rewards, score, techScore: tech, weightRecords: [...(passiveWeightRecords || []), ...(holyWeightRecords || [])] }; +} + +// 处理挑战类型中 接下来X次选择特性卡时,可选择的卡片数量少1 +export async function getPassiveCardRandom(passiveCardChooseNum: number, passiveCardRandomNum: number, gameCode: string, layer: number, roleId: string) { + let num = passiveCardRandomNum; + let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); + if (dbDetails.length == 0) return num; + for (let { challenge } of dbDetails) { + if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { + let { challengeId } = challenge; + const rougeChallengeData = gameData.rougeChallenge.get(challengeId); + if (!rougeChallengeData) return num; + for (let effectId of (rougeChallengeData.effectId || [])) { + const rougeEffectTypeData = gameData.rougeEffect.get(effectId); + if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; + num -= (rougeEffectTypeData.effectParam[1] || 0); + } + } + } + + return num >= 0 ? num : 0; +} + +export async function getPassiveCardChooseNum(passiveCardChooseNum: number, passiveCardRandomNum: number, gameCode: string, layer: number, roleId: string) { + let chooseNum = passiveCardChooseNum; + let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); + if (dbDetails.length == 0) return chooseNum; + + // for (let { challenge } of dbDetails) { + // if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { + // let { challengeId } = challenge; + // const rougeChallengeData = gameData.rougeChallenge.get(challengeId); + // if (!rougeChallengeData) return chooseNum; + // for (let effectId of (rougeChallengeData.effectId || [])) { + // const rougeEffectTypeData = gameData.rougeEffect.get(effectId); + // if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; + // chooseNum -= (rougeEffectTypeData.effectParam[1] || 0); + // } + // } + // } + chooseNum += await getAddChoosePassive(roleId, gameCode); + + if (chooseNum < 0) chooseNum = 0; + if (chooseNum > passiveCardRandomNum) chooseNum = passiveCardRandomNum; + + return chooseNum; +} + +/** + * 获取高级角色卡自带特性 + * @param charaId + * @param passiveCardPlan + * @param passiveCardRandomNum + * @param type + * @param dbRougelikeCards + * @returns + */ +export async function getSelfPassiveCards(charaId: number, passiveCardPlan: number, type: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { + let result: number[] = []; + let charaData = gameData.rougeChara.get(charaId); + if (!charaData) return result; + if (charaData.charaType != ROUGE_CHARA_TYPE.HIGH) return result; + let { passiveCards } = await getPassiveCardPlan(passiveCardPlan, charaData.initCardCnt, type, dbRougelikeCards, gameCode, roleId); + if (passiveCards && passiveCards.length > 0) result.push(...passiveCards.map((ele) => { return ele.cardId }),); + + return result; +} + +/** + * 获取当前层当前节点商店数据 + * @param gameCode + * @param detailCode + * @param nodeId + * @param shopPlan + * @returns + */ +export async function getLayerShopReward(roleId: string, gameCode: string, type: number, nodeId: number, shopPlan: number) { + let shops: RougelikeRecordDetailType['shops'] = []; + let shopPlanData = gameData.rougeShopPlan.get(shopPlan); + // let nodeData = gameData.rougeNode.get(nodeId); + + if (!shopPlanData) return { shops }; + + + let dbRougelikeCards = await RougelikeCardModel.findByGameCodeAndType(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); + + let { passiveCards, passiveWeightRecords } = await getPassiveCardPlan(shopPlanData.passivecardPlanId, shopPlanData.passiveCardRandomNum, type || 0, dbRougelikeCards, gameCode, roleId); + let index = 0, discount = await getShopDiscount(roleId, gameCode); + if (passiveCards && passiveCards.length > 0) { + for (let ele of passiveCards) { + let price = gameData.rougePassiveCard.get(ele.cardId)?.price || 0 + shops.push({ + optionIndex: shops.length + index, + rewardType: ROUGE_LIKE_CARD_TYPE.PASSIVE, + rewardId: ele.cardId, + optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, + price, + discountPrice: Math.floor(price * discount / 100), + }) + index++; + } + } + + let { holyCards, holyWeightRecords } = await getHolyCardPlan(shopPlanData?.holyCardPlanId, shopPlanData?.holyCardRandomNum, dbRougelikeCards, gameCode, roleId); + if (holyCards && holyCards.length > 0) { + for (let ele of holyCards) { + let price = gameData.rougeHolyCard.get(ele.cardId)?.purchasePrice || 0; + shops.push({ + optionIndex: shops.length + index, + rewardType: ROUGE_LIKE_CARD_TYPE.HOLY, + rewardId: ele.cardId, optionStatus: ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE, + price, + discountPrice: Math.floor(price * discount / 100), + }) + index++; + } + } + + return { shops, weightRecords: [...(passiveWeightRecords || []), ...(holyWeightRecords || [])] }; +} + + + +/** + * 检测配置数据是否满足随机数量 + * @param planId + * @param randomNum + * @returns + */ +export function checkRandomLimit(planId: number, randomNum: number, rewardType: number) { + let cards: DicRougeCharaCardPlan[] = []; + if (!planId || planId == 0 || !randomNum || randomNum == 0) return cards; + + let cardPlanDatas = gameData.rougeCharaCardPlan.get(planId); + if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE) cardPlanDatas = gameData.rougePassiveCardPlan.get(planId); + else if (rewardType == ROUGE_LIKE_CARD_TYPE.HOLY) cardPlanDatas = gameData.rougeHolyCardPlan.get(planId); + + if (!cardPlanDatas) return cards; + else if (cardPlanDatas.length < randomNum) { + console.error("checkRandomLimit可随机的角色卡数量少于需要数量, planId=%s, randomNum=%s", planId, randomNum); + return cardPlanDatas; + } + else if (cardPlanDatas.length >= randomNum) return cardPlanDatas; + + return cards; +} + +/** + * 获取角色卡随机 + * @param planId + * @param charaRandomNum + * @returns + */ +export function getCharaCardPlan(planId: number, charaRandomNum: number) { + let cards = checkRandomLimit(planId, charaRandomNum, ROUGE_LIKE_CARD_TYPE.CHARA); + if (cards.length <= charaRandomNum) return cards; + let randResult = getRandEelmWithWeightAndNum(cards, charaRandomNum); + return randResult.map(cur => cur.dic); +} + + +/** + * 获取特性卡随机 + * @param passiveCardPlan + * @param passiveCardRandomNum + */ +export async function getPassiveCardPlan(passiveCardPlan: number, passiveCardRandomNum: number, type: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { + let cards = checkRandomLimit(passiveCardPlan, passiveCardRandomNum, ROUGE_LIKE_CARD_TYPE.PASSIVE); + // if (cards.length <= passiveCardRandomNum) return { passiveCards: cards }; + if (cards.length == 0) return { passiveCards: cards }; + + // 计算变化权重 + let lableMap = new Map(); //统计lable数量 + if (dbRougelikeCards && dbRougelikeCards.length > ROUGELIKE.PASSIVE_LABLE_NUM) { + for (let { cardId } of dbRougelikeCards) { + if (!cardId) continue; + + let passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData || !passiveCardData.passiveLabel || passiveCardData.passiveLabel.length == 0) continue; + + for (let val of passiveCardData.passiveLabel) { + if (!lableMap.get(val)) { + lableMap.set(val, 1); + continue; + } + lableMap.set(val, lableMap.get(val) + 1); + } + } + } + + let newCards = []; + let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.PASSIVE); + const { chooseCardsMap, noChooseCardsMap } = await getIsChooseCard(gameCode); + + let isHolyAddWeight = false; + for (let obj of cards) { + let { cardId, weight } = obj || {}; + let passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData || !passiveCardData.authorType) continue; + if (passiveCardData.authorType == type) { + isHolyAddWeight = true; + break; + } + } + let holyAddWeight = 0; + if (isHolyAddWeight) { + holyAddWeight = await getAddPassiveWeight(roleId, gameCode, type); + } + + for (let obj of cards) { + let weightRecord: { originalWight?: number, passiveRedWight?: number, holyAddWeight?: number, passiveLableNum?: number, authorAddWeight?: number, passiveLableNumAddWeight?: number, finalWeight?: number } = {}; + if (!obj) continue; + let { cardId, weight } = obj; + if (!cardId || !weight) continue; + + let passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData) continue; + const getLimit = cardsMap.get(cardId) || 0; + if (getLimit >= (passiveCardData?.getLimit || 0)) continue; //处理限制获取数量 + + weightRecord.originalWight = weight; + + if (chooseCardsMap.has(cardId)) { + weight = Math.floor(weight * (1 - ROUGELIKE.SELECT_PASSIVECARD_WEIGHT / 100)); + weightRecord.passiveRedWight = Math.floor(weight * ROUGELIKE.SELECT_PASSIVECARD_WEIGHT / 100); + } + else if (noChooseCardsMap.has(cardId)) { + weight = Math.floor(weight * (1 - ROUGELIKE.RANDOM_PASSIVECARD_WEIGHT / 100)); + weightRecord.passiveRedWight = Math.floor(weight * ROUGELIKE.RANDOM_PASSIVECARD_WEIGHT / 100); + } + + const { authorType = 0, quality = 0, lv = 0 } = passiveCardData; + if (authorType == type) { + weight += holyAddWeight; + weightRecord.holyAddWeight = holyAddWeight; + + const passiveWeightData = gameData.rougePassiveWeight.get(authorType + '_' + quality + '_' + lv); + if (passiveWeightData && passiveWeightData.authorTypeWeightAdd) { + weight += passiveWeightData.authorTypeWeightAdd; + weightRecord.authorAddWeight = passiveWeightData.authorTypeWeightAdd; + } + } + + + let labelNum = lableMap.get(cardId) || 0; + if (labelNum >= ROUGELIKE.PASSIVE_LABLE_NUM) { + weight += ROUGELIKE.PASSIVE_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.PASSIVE_LABLE_NUM)); + weightRecord.passiveLableNum = labelNum; + weightRecord.passiveLableNumAddWeight = ROUGELIKE.PASSIVE_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.PASSIVE_LABLE_NUM)); + } + + weightRecord.finalWeight = weight; + + newCards.push({ ...obj, weight, weightRecord }); + } + + let targetPassives = await getChooseQualityPassives(roleId, gameCode, newCards); + let result = []; + if (passiveCardRandomNum >= 1 && targetPassives.length > 0) result.push(getRandEelmWithWeight(targetPassives).dic); + + let randResult = getRandEelmWithWeightAndNum(newCards, passiveCardRandomNum - result.length); + + return { passiveCards: [...result, ...randResult.map(cur => cur.dic)], passiveWeightRecords: newCards } +} + +export async function getIsChooseCard(gameCode: string) { + const dbDetails = await RougelikeRecordDetailModel.findByGameCode(gameCode); + let chooseCardsMap = new Map(); + let noChooseCardsMap = new Map(); + for (const { rewards } of dbDetails) { + if (!rewards || rewards.length == 0) continue; + for (const { options } of rewards) { + if (!options || options.length == 0) continue; + for (const { rewardId, optionStatus } of options) { + if (optionStatus != 0) { + chooseCardsMap.set(rewardId, rewardId); + continue; + } + noChooseCardsMap.set(rewardId, rewardId); + } + } + } + return { chooseCardsMap, noChooseCardsMap }; +} + + +export async function getCardCount(gameCode: string, type: number) { + const dbCards: RougelikeCardType[] = await RougelikeCardModel.findByGameCodeAndType(gameCode, type); + let cardsMap = new Map(); + dbCards.forEach((cur) => { cardsMap.set(cur.cardId, (cardsMap.get(cur.cardId) || 0) + 1); }) + return cardsMap; +} + +/** + * 获取圣物随机 + * @param planId + * @param holyCardPlan + */ +export async function getHolyCardPlan(holyCardPlan: number, holyCardRandomNum: number, dbRougelikeCards: RougelikeCardType[], gameCode: string, roleId: string) { + + let cards = checkRandomLimit(holyCardPlan, holyCardRandomNum, ROUGE_LIKE_CARD_TYPE.HOLY); + // if (cards.length <= holyCardRandomNum) return { holyCards: cards }; + if (cards.length == 0) return { holyCards: cards }; + + let lableMap = new Map();//统计lable数量 + if (dbRougelikeCards && dbRougelikeCards.length > ROUGELIKE.HOLY_LABLE_NUM) { + for (let { cardId } of dbRougelikeCards) { + if (!cardId) continue; + + let passiveCardData = gameData.rougePassiveCard.get(cardId); + if (!passiveCardData || !passiveCardData.holyLabel || passiveCardData.holyLabel.length == 0) continue; + + for (let val of passiveCardData.holyLabel) { + if (!lableMap.get(val)) { + lableMap.set(val, 1); + continue; + } + lableMap.set(val, lableMap.get(val) + 1); + } + } + } + // 计算变化权重 + let newCards = []; + let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.HOLY); + const { chooseCardsMap, noChooseCardsMap } = await getIsChooseCard(gameCode); + for (let obj of cards) { + let weightRecord: { + originalWight?: number, passiveRedWight?: number, holyRedWight?: number, authorAddWeight?: number, + passiveLableNum?: number, passiveLableNumAddWeight?: number, holyLableNum?: number, holyLableNumAddWeight?: number, + finalWeight?: number + } = {}; + + if (!obj) continue; + let { cardId, weight } = obj; + if (!cardId || !weight) continue; + + let holyCardData = gameData.rougeHolyCard.get(cardId); + if (!holyCardData) continue; + const getLimit = cardsMap.get(cardId) || 0; + if (getLimit >= (holyCardData?.getLimit || 0)) continue; //处理限制获取数量 + + weightRecord.originalWight = weight; + + if (chooseCardsMap.has(cardId)) { + weight = Math.floor(weight * (1 - ROUGELIKE.SELECT_HOLLYCARD_WEIGHT / 100)); + weightRecord.holyRedWight = Math.floor(weight * ROUGELIKE.SELECT_HOLLYCARD_WEIGHT / 100); + } + else if (noChooseCardsMap.has(cardId)) { + weight = Math.floor(weight * (1 - ROUGELIKE.RANDOM_HOLLYCARD_WEIGHT / 100)); + weightRecord.holyRedWight = Math.floor(weight * ROUGELIKE.RANDOM_HOLLYCARD_WEIGHT / 100); + } + if (!holyCardData.label) { + newCards.push({ ...obj }); + weightRecord.finalWeight = weight; + continue; + }; + + let labelNum = lableMap.get(holyCardData.label) || 0; + if (labelNum < ROUGELIKE.HOLY_LABLE_NUM || ROUGELIKE.HOLY_LABLE_NUM == 0) { + newCards.push({ ...obj }); + weightRecord.finalWeight = weight; + continue; + }; + + weight += ROUGELIKE.HOLY_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.HOLY_LABLE_NUM)); + + weightRecord.holyLableNum = labelNum; + weightRecord.holyLableNumAddWeight = ROUGELIKE.HOLY_LABLE_ADD_RANDOM * (Math.ceil(labelNum / ROUGELIKE.HOLY_LABLE_NUM)); + weightRecord.finalWeight = weight; + + newCards.push({ ...obj, weight, weightRecord }); + } + + let randResult = getRandEelmWithWeightAndNum(newCards, holyCardRandomNum); + return { holyCards: randResult.map(cur => cur.dic), holyWeightRecords: newCards } +} + + +/** + * 获取挑战关卡数据 + * @param planId + * @returns + */ +export function getChallenge(planId: number) { + const randomChallenge = getChallengePlan(planId); + if (!randomChallenge) return; + + const rougeChallengeData = gameData.rougeChallenge.get(randomChallenge.challengeId); + if (!rougeChallengeData) return; + + return rougeChallengeData; +} + +/** + * 获取挑战关随机 + * @param planId + * @returns + */ +export function getChallengePlan(planId: number) { + const challengePlanData = gameData.rougeChallengePlan.get(planId); + if (!challengePlanData) return; + if (challengePlanData.length == 1) return challengePlanData[0]; + + return getRandEelmWithWeight(challengePlanData).dic; +} + + +export async function updateChalleng(dbRecord: RougelikeRecordType, roleId: string, sid: string, gameCode: string, curLayer: number, rougeDamage, isAp?: boolean, isRound?: boolean) { + let len = rougeDamage.length; + let challenges: { challengeId: number, status: number, progress: number, detailCode: string }[] = []; + const { authorType, type, grade } = dbRecord; + let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, curLayer); + if (dbDetails.length == 0) return true; + + let updateChallengs: RougelikeRecordDetailPara[] = []; + for (let { detailCode, challenge, rewards = [], nodeId, layer } of dbDetails) { + if (challenge && Object.entries(challenge).length != 0 && challenge.status == 1) { + let { challengeId } = challenge; + + const rougeChallengeData = gameData.rougeChallenge.get(challengeId); + if (!rougeChallengeData) return true; + for (let effectId of (rougeChallengeData.effectId || [])) { + const rougeEffectTypeData = gameData.rougeEffect.get(effectId); + if (len == 0) { + //接下来X次选择特性卡时,可选择的卡片数量少1 + if (rougeEffectTypeData.effectType != ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; + } else { + if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_PASSIVE_CARD_REDUCE) continue; + if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NO_AP_SKILL && isAp) continue; + if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NO_ROUND_SKILL && isRound) continue; + if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_HP_LIMIT) { + let isNext = true; + for (let obj of rougeDamage) { + const { maxHp = 0, hp = 0 } = (obj || {}); + if (maxHp == 0 || hp == 0) { isNext = false; break; } + if (maxHp * (rougeEffectTypeData.effectParam[1] || 0) / 100 > hp) { isNext = false; break; } + } + + if (!isNext) continue; + } + + if (rougeEffectTypeData.effectType == ROUGE_EFFECT_TYPE.CHALLENGE_CHARA_NUM_LIMIT && (rougeEffectTypeData.effectParam[1] || 0) < len) continue;//接下来X场战斗,每场战斗不超过上阵2名学员 + } + + challenge.progress += 1; + + + if (challenge.progress == rougeChallengeData.condition) { + challenge.status = 2; + + //处理在挑战进度完成时再随机奖励 + // const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + // if (!typeGradeData) continue; + // const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); + // if (!layerPlanData) continue; + // let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer); + // rewards = result.rewards; + + }; + } + challenges.push({ challengeId, status: challenge.status, progress: challenge.progress, detailCode }); + updateChallengs.push({ gameCode, detailCode, challenge, status: 1 }); + } + } + + await RougelikeRecordDetailModel.bulkWriteUpdate(updateChallengs); + + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ROUGE_CHALLENGE_UPDATE, { challenges }, sid); + + return true; +} + +export function getLayerRewardOneData(type: number, grade: number, layer: number, nodeType: number) { + let result: { takeoutReward?: RewardInter[], coin?: number, score?: number, tech?: number, spiritPlan?: RewardInter[] } = {}; + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + if (!typeGradeData) return result; + const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer); + if (!layerPlanData) return result; + result = { takeoutReward: layerPlanData.takeoutReward, spiritPlan: layerPlanData.spiritPlan } + + const layerRewardData = gameData.rougeLayerRewardPlan.get(layerPlanData.rewardPlan + '_' + nodeType); + if (!layerRewardData) return result; + result = { ...layerRewardData, ...result }; + + return result; +} + +export function getRandomSpirit(spiritPlan: number, randomNum: number) { + let spiritId: number[] = []; + const spiritPlanData = gameData.spiritPlan.get(spiritPlan); + if (randomNum == 0 || !spiritPlanData || spiritPlanData.length == 0) return spiritId; + let random = getRandEelmWithWeightAndNum(spiritPlanData, randomNum); + for (let cur of random) { + if (cur.dic && cur.dic.spiritId) spiritId.push(cur.dic.spiritId) + } + + return spiritId; +} + +/** + * 获取 + * @param authorType + * @param cards + * @returns + */ +export function getAuthorTypeCardNum(authorType: number, cards: Card[]) { + return cards.filter(card => { + let dicCard = card.cardId == 0 ? null : gameData.rougePassiveCard.get(card.cardId); + if (!dicCard) return false; + return dicCard.authorType == authorType; + }).length; +} + +export async function repaireSendScoreReward() { + let refTime = new Date(getZeroPointOfTimeD(Date.now() + 1 * 60 * 60 * 1000, SHOP_REFRESH_TYPE.WEEKLY).getTime() - (86400000 * 7)); + let allRewards = await RougelikeScoreModel.findByRefTime(refTime); + let updateArr: RougelikeScorePara[] = []; + + const roleIds = allRewards.map(cur => { return cur.roleId }); + const lastMaxLvMap = await RougelikeExtendModel.getLastMaxLvMap(roleIds); + for (let { roleId, received, score, receiveNum } of allRewards) { + let lastMaxLv = lastMaxLvMap.get(roleId) ? lastMaxLvMap.get(roleId) : 1; + let goods: RewardInter[] = []; + const rougeScoreRewardByLvData = gameData.rougeScoreRewardByLv.get(lastMaxLv); + if (receiveNum >= rougeScoreRewardByLvData.size) continue; + for (let [index, { reward, score: targetScore }] of rougeScoreRewardByLvData) { + if (score >= targetScore && !received.includes(index)) { + goods.push(...reward); + received.push(index); + } + } + if (goods.length > 0) { + await sendMailByContent(MAIL_TYPE.ROUGE_SCORE_REPAIRE, roleId, { goods }); + updateArr.push({ roleId, refTime, receiveNum: rougeScoreRewardByLvData.size, received }); + } + } + await RougelikeScoreModel.bulkWriteUpdate(updateArr); +} + +/** + * 获取最大血量 + * @param charaId + * @param type + * @param grade + * @returns + */ +export async function getMaxHp(roleId: string, gameCode: string, charaId: number, type: number, grade: number,) { + let maxHp = 0; + const charaData = gameData.rougeChara.get(charaId); + if (!charaData || !charaData.heroId) return maxHp; + const heroData = gameData.hero.get(charaData.heroId); + // console.log("x-x-x-x--x-xx- heroData", heroData); + if (!heroData || !heroData.hp) return maxHp; + + const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade); + // console.log("x-x-x-x--x-xx- typeGradeData", typeGradeData); + + if (!typeGradeData || !typeGradeData.heroValue) return maxHp; + + let rougeEffect = new RougeEffect(roleId, gameCode); + const holyMaxHp = await rougeEffect.getEffectMaxHp(); + + + maxHp = heroData.hp * typeGradeData.heroValue / 10000 * (1 + holyMaxHp / 100); + + return Math.floor(maxHp); +} + +export async function updateMaxHp(roleId: string, gameCode: string, type: number, grade: number, updateCharasMap?: Map) { + let dbCharas = await RougelikeCharaModel.findByGameCode(gameCode); + if (dbCharas.length == 0) return []; + + let result: RougelikeCharaType[] = []; + for (let val of dbCharas) { + if (updateCharasMap && updateCharasMap.has(val.charaCode)) { + val = { ...val, ...updateCharasMap.get(val.charaCode) } + } + let tempMaxHp = await getMaxHp(roleId, gameCode, val.charaId, type, grade); + if (tempMaxHp == val.maxHp && updateCharasMap && !updateCharasMap.has(val.charaCode)) continue; + let preMaxHp = val.maxHp; + val.maxHp = tempMaxHp; + if (val.hp > 0) { + val.hp = Math.min(val.hp + tempMaxHp - preMaxHp, tempMaxHp); + } + result.push(val); + } + await RougelikeCharaModel.bulkWriteUpdate(result); + let { charas } = formateCharasOrCards(result, ROUGE_LIKE_CARD_TYPE.CHARA) + return charas || []; +} + + +// 获取当前层之前所有未完成挑战关 +export async function getPreCurLayerChallengs(gameCode: string, layer: number) { + let challenges: { challengeId: number, status: number, progress: number, detailCode: string, reward: CommonReward }[] = []; + let dbDetails = await RougelikeRecordDetailModel.findByGameCodeAndLtLayer(gameCode, layer); + if (dbDetails.length == 0) return challenges; + for (let { detailCode, challenge, rewards } of dbDetails) { + if (!challenge) continue; + const { challengeId, status, progress } = challenge; + if (status == 3) continue; + challenges.push({ challengeId, status, progress, detailCode, reward: { rewards } }); + } + + return challenges; +} + +export async function getGame(roleId: string) { + let isPlaying = true, nodes: RougelikeLayerType[] = [], hasPass = false, curNode = {}; + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS); + if (!dbRecord) { + isPlaying = false; + return { isPlaying }; + } + const { gameCode, grade, type, authorType = 0, curLayer = 0, maxLayer = 0, coin = 0, score = 0, techScore = 0, coinTotal = 0 } = dbRecord; + + const dbNodes = await RougelikeLayerModel.findByGameCode(gameCode); + let dbCurLayerChooseNode = {} as layerNode; + if (dbNodes) nodes = dbNodes.map((obj) => { + const { layer, layerNodes, hasPass: dbHasPass = false } = obj; + if (layer == curLayer) { + hasPass = dbHasPass; + dbCurLayerChooseNode = layerNodes.find(cur => cur.isChoose == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE); + } + return { layer, layerNodes } as RougelikeLayerType + }) + + const charas: CommonChara[] = formateCharasOrCards(await RougelikeCharaModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || []; + const cards: CommonCard[] = formateCharasOrCards(await RougelikeCardModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.PASSIVE | ROUGE_LIKE_CARD_TYPE.HOLY)?.cards || []; + + // console.log("x-x-x-x-x-x-x-x- dbCurLayerChooseNode", dbCurLayerChooseNode) + if (Object.entries(dbCurLayerChooseNode).length != 0) curNode = await chooseNode(dbRecord, dbCurLayerChooseNode, curLayer) + + return { + isPlaying, gameCode, grade, type, authorType, + curLayer, hasPass, maxLayer, coin, coinTotal, score, techScore, nodes: nodes || [], charas, cards, curNode, + preChallengs: await getPreCurLayerChallengs(gameCode, curLayer) + }; +} diff --git a/game-server/app/services/battle/rougeTechService.ts b/game-server/app/services/battle/rougeTechService.ts index aef89f45a..80a43e39a 100644 --- a/game-server/app/services/battle/rougeTechService.ts +++ b/game-server/app/services/battle/rougeTechService.ts @@ -1,142 +1,142 @@ -import { Circle, RougelikeTechModel, RougelikeTechType } from '../../db/RougelikeTech'; -import { gameData } from '../../pubUtils/data'; -import { HeroModel } from '../../db/Hero'; -import { compareNumberArray } from '../../pubUtils/util'; -import { ROUGE_EFFECT_TYPE, ROUGE_LIKE_STATUS } from '../../consts'; -import { updateMaxHp } from './rougeService'; -import { RougelikeRecordModel } from '../../db/RougelikeRecord'; - -/** - * 首页获得的科技树数据 - * @param techData - * @returns - */ -export async function getTechData(roleId: string) { - let techData = await RougelikeTechModel.findByRoleId(roleId); - if(!techData) return { techTrees: [], sumTechScore: 0 }; - let { unlockedTech = [], circles = [] } = techData; - circles = await calCircleCe(roleId, unlockedTech, circles); - let techTrees = unlockedTech.map(techId => getSingleTechData(techId, circles)); - return { - techTrees - } -} - -/** - * 从首页重新进入,重新计算他的战力 - * @param roleId - * @param circles - * @returns - */ -async function calCircleCe(roleId: string, unlockedTech: number[], circles: Circle[]) { - let hids: number[] = circles.map(circle => circle.hid).filter(hid => hid > 0); - if(hids.length <= 0) return circles - let heroes = await HeroModel.findByHidRange(hids, roleId); - let newCircle = circles.map(circle => { - if(circle.hid == 0) return circle; - let hero = heroes.find(cur => cur.hid == circle.hid); - return { ...circle, ce: hero?.ce||0 } - }); - let effectIds = getTechEffectIds(unlockedTech, circles) - await RougelikeTechModel.updateCircle(roleId, newCircle, effectIds); - return newCircle; -} - -export async function updateEffectId(techData: RougelikeTechType) { - let effectIds = getTechEffectIdsByData(techData); - if(!compareNumberArray(effectIds, techData.effectIds||[])) { - await RougelikeTechModel.updateEffectId(techData.roleId, effectIds); - if (hasMaxHpUpdate(effectIds, techData.effectIds||[])) { - const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(techData.roleId, ROUGE_LIKE_STATUS.SUCCESS) - if(dbRecord) await updateMaxHp(techData.roleId, dbRecord.gameCode, dbRecord.type, dbRecord.grade) - } - } -} - -function hasMaxHpUpdate(effectIds: number[], oldEffectIds: number[]) { - let newEffectIds: number[] = []; - for(let effectId of effectIds) { - if (!oldEffectIds.includes(effectId)) newEffectIds.push(effectId); - } - for(let effectId of newEffectIds) { - let dicRougeEffect = gameData.rougeEffect.get(effectId); - if(dicRougeEffect && dicRougeEffect.effectType == ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP) { - return true; - } - } - return false; -} - -/** - * 处理后单个科技点的数据 - * @param techData - * @param techId - * @returns - */ -export function getCurTechData(techData: RougelikeTechType, techId: number) { - if(!techData || !techId) return { curTechTree: { techId, circles: [] } } - let { circles = [] } = techData; - return { - curTechTree: getSingleTechData(techId, circles) - } -} - -/** - * 获取单片科技树数据 - * @param techId - * @param circles - * @returns - */ -function getSingleTechData(techId: number, circles: Circle[]) { - let result: { circleId: number, hid: number, ce: number }[] = []; - for(let { techId: curTechId, hid, circleId, ce } of circles) { - if(curTechId == techId) result.push({ hid, circleId, ce }); - } - return { techId, circles: result }; -} - -/** - * 检查前置科技点是否解锁 - * @param techId - * @param unlockedTech - * @returns - */ -export function checkPreRougeTech(techId: number, unlockedTech: number[]) { - let dicTech = gameData.rougeTech.get(techId); - let preTechId = dicTech?.preTechId||[]; - for(let techId of preTechId) { - if(!unlockedTech.includes(techId)) return false; - } - return true; -} - -/** - * 获取科技树带来的type加成 - * @param roleId - * @returns [{ type: number, param: number[] }] - */ -export function getTechEffectIdsByData(techData: RougelikeTechType) { - if(!techData) return []; - return getTechEffectIds(techData.unlockedTech, techData.circles); -} - -export function getTechEffectIds(unlockedTech: number[], circles: Circle[]) { - let result: number[] = []; - let techMap = new Map(); - for(let techId of unlockedTech) { - techMap.set(techId, 0); - } - for(let { techId, ce } of circles) { - let oldCe = techMap.get(techId)||0; - techMap.set(techId, oldCe + ce); - } - for(let [techId, ce] of techMap) { - let levelDatas = gameData.rougeTechLevel.get(techId)||[]; - let effectIds: number[] = []; - for(let { techEffectIds, ce: targetCe } of levelDatas) { - if(ce >= targetCe) effectIds = techEffectIds; - } - result.push(...effectIds); - } - return result; -} \ No newline at end of file +import { Circle, RougelikeTechModel, RougelikeTechType } from '@db/RougelikeTech'; +import { gameData } from '@pubUtils/data'; +import { HeroModel } from '@db/Hero'; +import { compareNumberArray } from '@pubUtils/util'; +import { ROUGE_EFFECT_TYPE, ROUGE_LIKE_STATUS } from '@consts'; +import { updateMaxHp } from './rougeService'; +import { RougelikeRecordModel } from '@db/RougelikeRecord'; + +/** + * 首页获得的科技树数据 + * @param techData + * @returns + */ +export async function getTechData(roleId: string) { + let techData = await RougelikeTechModel.findByRoleId(roleId); + if(!techData) return { techTrees: [], sumTechScore: 0 }; + let { unlockedTech = [], circles = [] } = techData; + circles = await calCircleCe(roleId, unlockedTech, circles); + let techTrees = unlockedTech.map(techId => getSingleTechData(techId, circles)); + return { + techTrees + } +} + +/** + * 从首页重新进入,重新计算他的战力 + * @param roleId + * @param circles + * @returns + */ +async function calCircleCe(roleId: string, unlockedTech: number[], circles: Circle[]) { + let hids: number[] = circles.map(circle => circle.hid).filter(hid => hid > 0); + if(hids.length <= 0) return circles + let heroes = await HeroModel.findByHidRange(hids, roleId); + let newCircle = circles.map(circle => { + if(circle.hid == 0) return circle; + let hero = heroes.find(cur => cur.hid == circle.hid); + return { ...circle, ce: hero?.ce||0 } + }); + let effectIds = getTechEffectIds(unlockedTech, circles) + await RougelikeTechModel.updateCircle(roleId, newCircle, effectIds); + return newCircle; +} + +export async function updateEffectId(techData: RougelikeTechType) { + let effectIds = getTechEffectIdsByData(techData); + if(!compareNumberArray(effectIds, techData.effectIds||[])) { + await RougelikeTechModel.updateEffectId(techData.roleId, effectIds); + if (hasMaxHpUpdate(effectIds, techData.effectIds||[])) { + const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(techData.roleId, ROUGE_LIKE_STATUS.SUCCESS) + if(dbRecord) await updateMaxHp(techData.roleId, dbRecord.gameCode, dbRecord.type, dbRecord.grade) + } + } +} + +function hasMaxHpUpdate(effectIds: number[], oldEffectIds: number[]) { + let newEffectIds: number[] = []; + for(let effectId of effectIds) { + if (!oldEffectIds.includes(effectId)) newEffectIds.push(effectId); + } + for(let effectId of newEffectIds) { + let dicRougeEffect = gameData.rougeEffect.get(effectId); + if(dicRougeEffect && dicRougeEffect.effectType == ROUGE_EFFECT_TYPE.TECH_CHARA_MAIN_ATTR_UP) { + return true; + } + } + return false; +} + +/** + * 处理后单个科技点的数据 + * @param techData + * @param techId + * @returns + */ +export function getCurTechData(techData: RougelikeTechType, techId: number) { + if(!techData || !techId) return { curTechTree: { techId, circles: [] } } + let { circles = [] } = techData; + return { + curTechTree: getSingleTechData(techId, circles) + } +} + +/** + * 获取单片科技树数据 + * @param techId + * @param circles + * @returns + */ +function getSingleTechData(techId: number, circles: Circle[]) { + let result: { circleId: number, hid: number, ce: number }[] = []; + for(let { techId: curTechId, hid, circleId, ce } of circles) { + if(curTechId == techId) result.push({ hid, circleId, ce }); + } + return { techId, circles: result }; +} + +/** + * 检查前置科技点是否解锁 + * @param techId + * @param unlockedTech + * @returns + */ +export function checkPreRougeTech(techId: number, unlockedTech: number[]) { + let dicTech = gameData.rougeTech.get(techId); + let preTechId = dicTech?.preTechId||[]; + for(let techId of preTechId) { + if(!unlockedTech.includes(techId)) return false; + } + return true; +} + +/** + * 获取科技树带来的type加成 + * @param roleId + * @returns [{ type: number, param: number[] }] + */ +export function getTechEffectIdsByData(techData: RougelikeTechType) { + if(!techData) return []; + return getTechEffectIds(techData.unlockedTech, techData.circles); +} + +export function getTechEffectIds(unlockedTech: number[], circles: Circle[]) { + let result: number[] = []; + let techMap = new Map(); + for(let techId of unlockedTech) { + techMap.set(techId, 0); + } + for(let { techId, ce } of circles) { + let oldCe = techMap.get(techId)||0; + techMap.set(techId, oldCe + ce); + } + for(let [techId, ce] of techMap) { + let levelDatas = gameData.rougeTechLevel.get(techId)||[]; + let effectIds: number[] = []; + for(let { techEffectIds, ce: targetCe } of levelDatas) { + if(ce >= targetCe) effectIds = techEffectIds; + } + result.push(...effectIds); + } + return result; +} diff --git a/game-server/app/services/battleService.ts b/game-server/app/services/battleService.ts index 66b8db10a..041e58e75 100644 --- a/game-server/app/services/battleService.ts +++ b/game-server/app/services/battleService.ts @@ -1,687 +1,687 @@ -import { HeroModel, HeroType } from './../db/Hero'; -import { HangUpRecordModel } from './../db/HangUpRecord'; -import { HANG_UP_CONSTS, REDIS_KEY, TASK_TYPE, TOWER_FORBIDDEN_CHARA_TYPE, TOWER_TASK_STATUS, MAIL_TYPE, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE } from './../consts'; -import { BattleRecordModel } from './../db/BattleRecord'; -import { TowerRecordModel, WarStatus } from './../db/TowerRecord'; -import { RoleModel, RoleType } from './../db/Role'; -import { shouldRefresh, resResult, cal, getRandEelmWithWeight, genCode, } from '../pubUtils/util'; -import { STATUS } from '../consts/statusCode'; -import { HangUpSpdUpRecModel } from '../db/HangUpSpdUpRec'; -import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from '../db/TowerTaskRec'; -import { Rank } from './rankService'; -import { checkTask } from './task/taskService'; -import { getRandExpedition, gameData } from '../pubUtils/data'; -import { ItemInter, RewardInter, pvpEndParamInter } from '../pubUtils/interface'; -import { getTimeFunM } from '../pubUtils/timeUtil'; -import { ComRoleStatusHero } from '../db/ComBattleTeam'; -import { sendMailByContent } from './mailService'; -import { DicTowerTask } from '../pubUtils/dictionary/DicTowerTask'; -import * as dicParam from '../pubUtils/dicParam'; -import { getVipHungupReward } from './activity/monthlyTicketService'; -import { pushTowerMsg } from './sysChatService'; -import { checkPopUpCondition } from './activity/popUpShopService'; - -/** - * 获取当前镇念塔状态 - * @param role - */ -export async function getTowerStatus(role: RoleType) { - let { towerLv, roleId, serverId, towerReceived } = role; - if (!towerLv) { - let role = await RoleModel.towerLvUp(roleId); - towerLv = role.towerLv; - } - let towerRec = await getTowerRecByLv(roleId, towerLv); - - return { - canHungUp: canHungUp(towerLv), - canSendTask: towerLv - 1 >= dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED, - sendTaskEnableLv: dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED, - curLv: towerLv, - usedHeroes: towerRec.heroes, - progress: towerRec.warStatus, - receivedBox: towerReceived||[], - }; -} - -export async function getTowerRecByLv(roleId: string, towerLv: number) { - - let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv); - if (!towerRec) { - const sts = getWarStatusByLv(towerLv); - towerRec = await TowerRecordModel.createRecord({roleId, lv: towerLv, warStatus: sts}); - // return { code: 201, data: '天梯记录异常' }; - } - return towerRec; -} - -export function getTowerStatusByWarId(warId: number, warStatus: WarStatus[] = []) { - let curWarStatus = warStatus.find(cur => cur.warId == warId); - return curWarStatus? curWarStatus.status: false; -} - -export function getWarStatusByLv(towerLv: number) { - let dicWar = gameData.tower.get(towerLv); - if(!dicWar) return []; - - const { warArray } = dicWar; - return warArray.map(id => { - return {warId: id, status: false}; - }); -} - -export function getTowerHeroCe(warId: number, heroes: HeroType[], recHeroes: number[] = []) { - let dicWar = gameData.war.get(warId); - let heroNum = 0, heroesCeSum = 0; - for(let hero of heroes) { - if(recHeroes.indexOf(hero.hid) == -1 && !checkForbiddenChar(hero.skinId, hero.job, dicWar.fobiddenCharactor)) { - heroNum++; - heroesCeSum += hero.ce; - } - if(heroNum >= dicWar.minHeroNum) break; - } - return heroesCeSum; -} - -/** - * 获取镇念塔挂机收益 - * @param roleId - */ -export async function getHungupRewards(roleId: string, role?: RoleType) { - if(!role) role = await RoleModel.findByRoleId(roleId); - const result = await calcuHangUpReward(role); - if(!result) return false; - - let { hangUpSpdUpCnt = 0, lastSpdUpTime } = role; - let {timeReward, startTime, deltaTime} = result; - let curTime = new Date(); - if (shouldRefresh(lastSpdUpTime, curTime)) { - hangUpSpdUpCnt = 0; - } - let nextCostGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, 1); - - return { startTime, hangUpPassTime: Math.floor(deltaTime/1000), hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - hangUpSpdUpCnt, nextCostGold, rewards: timeReward } -} - -/** - * 获取派遣任务列表 - * @param role - */ -export async function getTasks(roleId: string) { - let role = await RoleModel.findByRoleId(roleId, 'roleName towerLv towerTaskRefTime towerTaskReCnt'); - let { roleName, towerLv, towerTaskRefTime, towerTaskReCnt = 0 } = role; - - // towerLv:从1开始,下次打得层数,dicParam内的:从0开始,打过的层数 - if(towerLv - 1 < dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED) { - return {curTasks: [], refRemainTime: 0, nextCostGold: 0} - } - - let curTime = new Date(); - const needRefresh = shouldRefresh(towerTaskRefTime, curTime); - let curTasks: TowerTaskRecType[] = [] - if(needRefresh) { - role = await RoleModel.resetTowerCnt(roleId, curTime); - const batchCode = genCode(8); - let tasksData = await TowerTaskRecModel.getPreTasks(roleId); - let preTasksMap = treatPreTasks(tasksData); - for(let [batchCode, preTasks] of preTasksMap) { - if(preTasks && preTasks.length) { - let checkResult = checkTaskRewards(batchCode, preTasks ); - if(checkResult) { - await sendMailByContent(MAIL_TYPE.TOWER_TASK_REWARD, roleId, { goods: checkResult.rewards }); - await TowerTaskRecModel.finishTask(batchCode, preTasks.map(cur => cur.taskCode)); - }; - } - } - - curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, []); // 新建任务 - - // 重置派遣次数 - towerTaskReCnt = role.towerTaskReCnt; - } - if(curTasks.length <=0 ) { - curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 - } - - let refRemainTime = getRemainTime(curTime); - let nextCostGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); - - return { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold, towerTaskReCnt } -} - -function treatPreTasks(tasks: TowerTaskRecType[]) { - let map = new Map(); - for(let task of tasks) { - if(!map.has(task.batchCode)) { - map.set(task.batchCode, []); - } - map.get(task.batchCode).push(task); - } - return map -} - -export function checkTaskRewards(batchCode: string, tasks: TowerTaskRecType[]) { - const curTime = new Date(); - let compTasks: string[] = []; - let rewards: RewardInter[] = []; - for (let task of tasks) { - if ( task.batchCode == batchCode && task.status === TOWER_TASK_STATUS.DOINING) { - let {completeTime, reward, termsForAdd, additionalReward} = gameData.towerTask.get(task.taskId); - if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) { - compTasks.push(task.taskCode); - rewards.push(...reward); - if(termsForAdd) { - const result = checkTaskConditions(task.heroes, termsForAdd); - if(result) { - rewards.push(...additionalReward); - } - } - } - } - } - return { compTasks, rewards }; -} - -export async function checkTowerWar(roleId: string, battleId: number, seqIds: number[], heroes: HeroType[]) { - let { towerLv } = await RoleModel.findByRoleId(roleId); - const towerInfo = gameData.tower.get(towerLv); - if (!towerInfo) { - console.error(`天梯层数异常,lv ${towerLv} by ${roleId}`); - return { status: -1, resResult: resResult(STATUS.TOWER_INFO_NOT_FOUND) }; - } - const warIds = towerInfo.warArray; - - if (warIds.indexOf(battleId) === -1) { - return { status: -1, resResult: resResult(STATUS.TOWER_WRONG_BATTLE_ID) }; - } - - const tower = await TowerRecordModel.getRecordByLv(roleId, towerLv); - if (!tower) { - return { status: -1, resResult: resResult(STATUS.TOWER_NOT_FOUND) }; - } - let { heroes: recHeroes = [], warStatus = [] } = tower; - let dicWar = gameData.war.get(battleId); - let { fobiddenCharactor } = dicWar; - for (let hid of seqIds) { - if (recHeroes.indexOf(hid) !== -1) { - return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) }; - } - } - for(let {skinId, job} of heroes) { - if(checkForbiddenChar(skinId, job, fobiddenCharactor)) { - return { status: -1, resResult: resResult(STATUS.TOWER_HERO_FORBIDDEN) }; - } - } - const curWarStatus = warStatus.find(elem => elem.warId == battleId); - if (curWarStatus && curWarStatus.status) { - return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_CHALLENGE) }; - } - - return { - status: 0, data: { - heroes: recHeroes, warStatus: curWarStatus - } - }; -} - -export function checkForbiddenChar(hid: number, job: number, fobiddenCharactor: {type: number, id: number}[]) { - let dicHero = gameData.hero.get(hid); - let dicJob = gameData.job.get(job); - let flag = false; - for(let { type, id } of fobiddenCharactor) { - switch(type) { - case TOWER_FORBIDDEN_CHARA_TYPE.CHAR: - if(id == hid) flag = true; - break; - case TOWER_FORBIDDEN_CHARA_TYPE.JOB: - if(id == dicJob.job_class) flag = true; - break; - case TOWER_FORBIDDEN_CHARA_TYPE.CAMP: - if(id == dicHero.camp) flag = true; - break; - } - if(flag) break; - } - return flag; -} - -export async function towerBattleEnd(sid: string, roleId: string, serverId: number, battleCode: string, battleId: number, succeed: boolean, dbHeroes: number[], dbSeqIds: number[], damageRecords: pvpEndParamInter[]) { - if (succeed) { - let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode); - if (battleRec.battleId != battleId) { - return { status: -1, resResult: resResult(STATUS.BATTLE_ID_NOT_MATCH) }; - } - - let { towerLv, roleName } = await RoleModel.findByRoleId(roleId); - let { warStatus, heroes: recHeroes } = await TowerRecordModel.getRecordByLv(roleId, towerLv); - // console.log('*******', towerLv, heroes.join(), recHeroes.join()) - for (let hid of dbSeqIds) { - if (recHeroes.indexOf(hid) !== -1) { - return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) }; - } - } - - let inc = 0; - let dicTower = gameData.tower.get(towerLv); - // console.log('towerBattleEnd', towerLv, dicTower?.warArray, warStatus) - if(dicTower && dicTower.warArray) { - let wars = dicTower.warArray.filter(warId => { - let ws = warStatus.find(cur => cur.warId == warId); - let isPass = warId == battleId || (ws && ws.status == true); - return isPass; - }); - inc = wars.length == dicTower.warArray.length? 1: 0; - } - - let subHids: number[] = []; - for (let hid of dbHeroes) { - let damageRecord = damageRecords.find(cur => cur.hid == hid); - if (damageRecord && damageRecord.subHid > 0) subHids.push(damageRecord.subHid); - } - - const dbDamageSub = await HeroModel.findByHidsAndRole(roleId, subHids); - let newRec = await TowerRecordModel.updateRecord(roleId, towerLv, battleCode, battleId, [...dbSeqIds, ...dbDamageSub.map(cur => cur.seqId)], inc); - let towerReward: RewardInter[] = []; - if (inc === 1) { - let role = await RoleModel.towerLvUp(roleId); - // 更新redis - let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role); - - await createNewTowerRecord(roleId, role.towerLv); - const { reward } = gameData.tower.get(role.towerLv - 1); - if (reward) towerReward = [...reward]; - await checkAndStartHungUp(roleId, roleName, role.towerLv); - // 任务 - await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_TOWER_LV, { towerLv: role.towerLv - 1 }); - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: towerLv - 1, newLv: role.towerLv - 1 }) - - pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1); - } - return { - status: 0, - data: { - newRec, - towerReward, - towerStatus: !!inc - } - }; - } -} - -/** - * 创建下一层记录 - * @param roleId - * @param nextTowerLv 下一层塔 - */ -export async function createNewTowerRecord(roleId: string, nextTowerLv: number) { - const nextTowerInfo = gameData.tower.get(nextTowerLv); - if (nextTowerInfo) { - const { warArray } = nextTowerInfo; - const sts = warArray.map(id => { - return { warId: id, status: false }; - }); - - await TowerRecordModel.createRecord({ roleId, lv: nextTowerLv, warStatus: sts }); - } -} - -/** - * 当可以挂机的时候开始挂机 - * @param roleId - * @param roleName - * @param towerLv 当前楼层,升过级之后的层 - */ -export async function checkAndStartHungUp(roleId: string, roleName: string, towerLv: number) { - if (towerLv - 1 == dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV) { - await HangUpRecordModel.initRecord(roleId, roleName, towerLv); - } -} - -/** - * 是否可以挂机,如果是10,那么要打过10层,即11层时可以开始挂机 - * @param towerLv - * @returns - */ -export function canHungUp(towerLv: number) { - return towerLv - 1 >= dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV -} - -export async function calcuHangUpReward(role: RoleType, speedUp = false, speedUpCnt = 1, curTime = new Date()) { - let { roleId, towerLv = 1, hangUpSpdUpCnt = 0, lastSpdUpTime, vipStartTime } = role; - if (!canHungUp(towerLv)) { - return false - } - - let towerInfo = gameData.tower.get(towerLv - 1); // towerLv 是当前层,奖励计算按照已经通过的层,即上一层 - let baseReward = towerInfo.rewardOfcollect; - - if (speedUp) { // 加速,直接收取2小时收益,小数的累积和普通收取独立 - if (hangUpSpdUpCnt + speedUpCnt <= dicParam.TOWER_BOOST.TOWER_BOOSTTIME || !lastSpdUpTime || shouldRefresh(lastSpdUpTime, new Date)) { // 可加速 - let startTime = curTime; - let endTime = new Date(curTime.getTime() + HANG_UP_CONSTS.SPD_UP_REC_TIME); - let deltaTime = endTime.getTime() - startTime.getTime(); // 累计的挂机时间,受最大时间限制 - - let goods: {gid: number, count: number}[] = []; - let spdUpRec = await HangUpSpdUpRecModel.getLatestSpdUpRec(roleId); - if (spdUpRec) { - let { notReceivedGoodsList = [], cnt } = spdUpRec; - let notReceivedGoods = notReceivedGoodsList.find(cur => cur.cnt == cnt); - goods = notReceivedGoods ? notReceivedGoods.goods : []; - } - - let { timeReward, needReceiveGoods } = getVipHungupReward(startTime.getTime(), endTime.getTime(), baseReward, goods, vipStartTime); - - return { - endLv: towerLv, startTime, deltaTime, endTime, timeReward, needReceiveGoods - }; - } else { - return false - } - } else { - let { startTime } = await HangUpRecordModel.getCurRec(roleId); - let endTime = curTime; // 挂机结束时间,现在到开始时间,经历了10的倍数的时间 - let deltaTime = curTime.getTime() - startTime.getTime(); // 累计的挂机时间,受最大时间限制 - if (deltaTime > HANG_UP_CONSTS.MAX_TIME) { - deltaTime = HANG_UP_CONSTS.MAX_TIME; - startTime = new Date(curTime.getTime() - deltaTime); - endTime = curTime; // 累积到超过24小时,那么结束时间和下一次开启时间就取整了 - } else { - let multiReal = Math.floor(deltaTime / HANG_UP_CONSTS.UNIT_TIME);// 距开始挂机实际过去的时间单位 - endTime = new Date(startTime.getTime() + multiReal * HANG_UP_CONSTS.UNIT_TIME) - } - - let lastRec = await HangUpRecordModel.getLastRec(roleId); - let notReceivedGoods = lastRec ? lastRec.notReceivedGoods : []; - - let { timeReward, needReceiveGoods } = getVipHungupReward(startTime.getTime(), endTime.getTime(), baseReward, notReceivedGoods, vipStartTime); - - return { - endLv: towerLv, startTime, deltaTime, endTime, timeReward, needReceiveGoods - }; - } -} - -function checkCond(heroes: TaskHero[], type: number, param: number, cnt: number) { - - let heroCnt = 0; - - switch (type) { - case 1: - for (let { star, colorStar } of heroes) { - if (star + colorStar >= param) { - heroCnt++; - } - } - break; - case 2: - for (let { camp } of heroes) { - if (camp === param) { - heroCnt++; - } - } - break; - case 3: - for (let { jobClass } of heroes) { - if (jobClass === param) { - heroCnt++; - } - } - break; - default: - break; - } - if (heroCnt >= cnt) { - return true; - } - return false; -} - -export function checkTaskConditions(heroes: TaskHero[], condition: { type: number, param: number, count: number }[]) { - - let res = true; - for (let { type, param, count } of condition) { - const checkRes = checkCond(heroes, type, param, count); - if (!checkRes) { - res = false; - break; - } - } - return res; -} - -export async function refreshTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, oldTasks:TowerTaskRecType[]) { - let needFloor = !oldTasks || oldTasks.length <= 0; // 首次刷新需要一个保底 - - let ridTaskIds: number[] = []; - let positions = new Map (); // 需要创建或更新 - for(let i = 1; i <= dicParam.TOWER_SEARCH.TOWER_SEARCH_LIMITED; i++) { - positions.set(i, null); - } - let tasks: TowerTaskRecType[] = []; - for(let task of oldTasks) { - if( task.status == TOWER_TASK_STATUS.WAITING ) { - positions.set(task.position, task); - } else { - positions.delete(task.position); - ridTaskIds.push(task.taskId); - tasks.push(task); - } - } - - for(let [ position, task ] of positions) { - let dicOldTask = task? gameData.towerTask.get(task.taskId): null; - - let dicTask = randomTask(towerLv, dicOldTask?dicOldTask.quality: 0, ridTaskIds); - if(!dicTask) break; // 任务池没有可刷新了 - - let { taskId, quality } = dicTask; - if(quality == 4 || quality == 5) needFloor = false; - if(task) { // 更新 - tasks.push(await TowerTaskRecModel.updateTask(roleId, batchCode, position, taskId)); - } else { - tasks.push(await TowerTaskRecModel.createTask(roleId, roleName, batchCode, taskId, position)); - } - ridTaskIds.push(taskId); - } - - - if(needFloor) { // 塞一个保底 - let dicTask = randomTask(towerLv, 3, ridTaskIds); - if(dicTask) { - let index = Math.floor(Math.random() * tasks.length); - tasks[index] = await TowerTaskRecModel.updateTask(roleId, batchCode, tasks[index].position, dicTask.taskId); - } - } - - return tasks -} - -function randomTask(towerLv: number, oldQuality: number, rids: number[]) { - let qualityRange = oldQuality + 1; - - let randomList: DicTowerTask[] = []; - while(randomList.length <= 0) { // 如果这个品质范围里面没有,就降一品质再找 - for (let [_id, task] of gameData.towerTask) { - if(task.quality >= qualityRange && !rids.includes(task.taskId)) { - let { suitFloor: { min, max } } = task; - let flag = max ? (towerLv >= min && towerLv <= max) : (towerLv >= min); - if (flag) { - randomList.push(task); - } - } - } - if(randomList.length <= 0) qualityRange--; - if(qualityRange == 0) return null; - } - - let { dic } = getRandEelmWithWeight(randomList); - - return dic; -} - -// /** -// * 创建新的派遣任务 -// * @param towerLv 玩家层数 -// * @param roleId 玩家id -// * @param roleName 玩家名 -// * @param hideNum 隐藏的任务数量 -// */ -// export async function createCurTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, hideNum: number, showNum: number, rids: Array) { - -// let returnTasks = new Array(); -// const arr = [{ refreshStatus: 0, num: hideNum }, { refreshStatus: 1, num: showNum }]; -// for (let { refreshStatus, num } of arr) { -// let taskIds = []; -// for (let i = 0; i < num; i++) { -// } -// const curTasks = await TowerTaskRecModel.createTasks(roleId, roleName, batchCode, taskIds, refreshStatus); - -// if (refreshStatus == 1) { -// returnTasks = curTasks; -// } -// } - -// return returnTasks; -// } - -export function getRemainTime(curTime: Date) { - let nextTime = getTimeFunM(curTime).getAfterDayWithHour(); - return Math.floor((nextTime - curTime.getTime()) / 1000); -} - -export function treatTask(recs: Array, curTime: Date) { - return recs.map(cur => { - let { heroes, batchCode, taskId, taskCode, status, completeTime, position } = cur; - - let getStatusResult = getTaskStatus(status, completeTime, curTime); - return { position, heroes, batchCode, taskId, taskCode, completeTime, ...getStatusResult } - }).sort((a, b) => { - return a.position - b.position; - }); -} - -// 刷新任务,正在进行中的部分保留,没有进行中的刷掉 -export function getDoingOrWaitingTasks(taskList: Array, curTime: Date) { - let doingTaskCode = new Array(), waitingTaskCode = new Array(), doingIds = new Array(); - for (let task of taskList) { - let { status } = getTaskStatus(task.status, task.completeTime, curTime); - if (status == 1 || status == 2) { - doingTaskCode.push(task.taskCode); - doingIds.push(task.taskId); - } else if (status == 0 || status == 3) { - waitingTaskCode.push(task.taskCode); - } - } - return { doingTaskCode, waitingTaskCode, doingIds } -} - -export function getTaskStatus(status: number, completeTime: Date, curTime: Date) { - let remainTime = 0; - if (status == 1) { - // console.log(curTime.getTime(), completeTime.getTime()) - remainTime = Math.floor((completeTime.getTime() - curTime.getTime()) / 1000); - if (remainTime < 0) { - status = 2; remainTime = 0; - } - } - - return { status, remainTime } -} - -export async function getTasksReward(roleId: string, curTime: Date) { - let oldTasks = await TowerTaskRecModel.getCurTasks(roleId); - let goods: ItemInter[] = []; - for (let task of oldTasks) { - let { completeTime, reward, termsForAdd, additionalReward } = gameData.towerTask.get(task.taskId); - if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) { - goods = goods.concat(reward); - if (termsForAdd) { - const result = checkTaskConditions(task.heroes, termsForAdd); - if (result) { - goods.push(...additionalReward); - } - } - } - } - return goods -} - -/** - * 获取随机机器人数据 - * @param cnt 机器人数量 - * @param withAttr 是否返回属性,false: 仅返回阵容 - */ -export function getRandRobot(cnt = 1, withAttr = false) { - let setInfo = getRandExpedition(cnt); - if (!setInfo || setInfo.length !== cnt) return null; - - let robots: ComRoleStatusHero[][] = []; - for (let info of setInfo) { - if (!info || !info.warId) continue; - const warInfo = gameData.warJson.get(info.warId); - if (!warInfo || !warInfo.length) continue; - - let heroes: ComRoleStatusHero[] = []; - for (let hero of warInfo) { - if (hero && hero.relation === 2 && hero.actorId) { - let dicHero = gameData.hero.get(hero.actorId); - heroes.push(new ComRoleStatusHero({ - hid: hero.actorId, - skinId: hero.actorId, - star: hero.star? hero.star: dicHero.initialStar, - colorStar: hero.star? 0: dicHero.initialColorStar, - lv: hero.lv, - quality: dicHero.quality - })); - } - } - robots.push(heroes); - } - return robots; -} - -/** - * 获得下一次刷新派遣的花费 - * @param times 玩家表上的次数 - * @param refTime 玩家表上的刷新时间 - * @returns - */ -export function getTowerTaskCostGold(times: number, refTime: Date) { - if(shouldRefresh(refTime, new Date())) { - times = 0; - } - let cost = (times + 1) * dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_FEE; - if(cost > dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX) cost = dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX; - return cost; -} - -/** - * 多次加速挂机消耗的元宝 - * @param originCnt 玩家表里原来的次数 - * @param count 这次加速几次 - * @returns - */ -export function getManyHangSpdUpCostGold(originCnt: number, count: number) { - let gold = 0; - for(let i = 1; i <= count; i++) { - let num = originCnt + i; - gold += getHangSpdUpCostGold(num); - } - return gold -} - -/** - * 计算加速挂机消耗的元宝 - * @param times 第几次,如果你没有加速过,这里给1 - * @returns - */ -export function getHangSpdUpCostGold(times:number) { - if(times <= dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) { - return 0 - } else { - let cost = (times - dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) * dicParam.TOWER_BOOST.TOWER_BOOSTCAST; - if(cost > dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX) cost = dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX; - return cost; - } -} \ No newline at end of file +import { HeroModel, HeroType } from '@db/Hero'; +import { HangUpRecordModel } from '@db/HangUpRecord'; +import { HANG_UP_CONSTS, REDIS_KEY, TASK_TYPE, TOWER_FORBIDDEN_CHARA_TYPE, TOWER_TASK_STATUS, MAIL_TYPE, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE } from '@consts'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { TowerRecordModel, WarStatus } from '@db/TowerRecord'; +import { RoleModel, RoleType } from '@db/Role'; +import { shouldRefresh, resResult, cal, getRandEelmWithWeight, genCode, } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { HangUpSpdUpRecModel } from '@db/HangUpSpdUpRec'; +import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from '@db/TowerTaskRec'; +import { Rank } from './rankService'; +import { checkTask } from './task/taskService'; +import { getRandExpedition, gameData } from '@pubUtils/data'; +import { ItemInter, RewardInter, pvpEndParamInter } from '@pubUtils/interface'; +import { getTimeFunM } from '@pubUtils/timeUtil'; +import { ComRoleStatusHero } from '@db/ComBattleTeam'; +import { sendMailByContent } from './mailService'; +import { DicTowerTask } from '@pubUtils/dictionary/DicTowerTask'; +import * as dicParam from '@pubUtils/dicParam'; +import { getVipHungupReward } from './activity/monthlyTicketService'; +import { pushTowerMsg } from './sysChatService'; +import { checkPopUpCondition } from './activity/popUpShopService'; + +/** + * 获取当前镇念塔状态 + * @param role + */ +export async function getTowerStatus(role: RoleType) { + let { towerLv, roleId, serverId, towerReceived } = role; + if (!towerLv) { + let role = await RoleModel.towerLvUp(roleId); + towerLv = role.towerLv; + } + let towerRec = await getTowerRecByLv(roleId, towerLv); + + return { + canHungUp: canHungUp(towerLv), + canSendTask: towerLv - 1 >= dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED, + sendTaskEnableLv: dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED, + curLv: towerLv, + usedHeroes: towerRec.heroes, + progress: towerRec.warStatus, + receivedBox: towerReceived||[], + }; +} + +export async function getTowerRecByLv(roleId: string, towerLv: number) { + + let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv); + if (!towerRec) { + const sts = getWarStatusByLv(towerLv); + towerRec = await TowerRecordModel.createRecord({roleId, lv: towerLv, warStatus: sts}); + // return { code: 201, data: '天梯记录异常' }; + } + return towerRec; +} + +export function getTowerStatusByWarId(warId: number, warStatus: WarStatus[] = []) { + let curWarStatus = warStatus.find(cur => cur.warId == warId); + return curWarStatus? curWarStatus.status: false; +} + +export function getWarStatusByLv(towerLv: number) { + let dicWar = gameData.tower.get(towerLv); + if(!dicWar) return []; + + const { warArray } = dicWar; + return warArray.map(id => { + return {warId: id, status: false}; + }); +} + +export function getTowerHeroCe(warId: number, heroes: HeroType[], recHeroes: number[] = []) { + let dicWar = gameData.war.get(warId); + let heroNum = 0, heroesCeSum = 0; + for(let hero of heroes) { + if(recHeroes.indexOf(hero.hid) == -1 && !checkForbiddenChar(hero.skinId, hero.job, dicWar.fobiddenCharactor)) { + heroNum++; + heroesCeSum += hero.ce; + } + if(heroNum >= dicWar.minHeroNum) break; + } + return heroesCeSum; +} + +/** + * 获取镇念塔挂机收益 + * @param roleId + */ +export async function getHungupRewards(roleId: string, role?: RoleType) { + if(!role) role = await RoleModel.findByRoleId(roleId); + const result = await calcuHangUpReward(role); + if(!result) return false; + + let { hangUpSpdUpCnt = 0, lastSpdUpTime } = role; + let {timeReward, startTime, deltaTime} = result; + let curTime = new Date(); + if (shouldRefresh(lastSpdUpTime, curTime)) { + hangUpSpdUpCnt = 0; + } + let nextCostGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, 1); + + return { startTime, hangUpPassTime: Math.floor(deltaTime/1000), hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - hangUpSpdUpCnt, nextCostGold, rewards: timeReward } +} + +/** + * 获取派遣任务列表 + * @param role + */ +export async function getTasks(roleId: string) { + let role = await RoleModel.findByRoleId(roleId, 'roleName towerLv towerTaskRefTime towerTaskReCnt'); + let { roleName, towerLv, towerTaskRefTime, towerTaskReCnt = 0 } = role; + + // towerLv:从1开始,下次打得层数,dicParam内的:从0开始,打过的层数 + if(towerLv - 1 < dicParam.TOWER_SEARCH.TOWER_SEARCH_STARTLIMITED) { + return {curTasks: [], refRemainTime: 0, nextCostGold: 0} + } + + let curTime = new Date(); + const needRefresh = shouldRefresh(towerTaskRefTime, curTime); + let curTasks: TowerTaskRecType[] = [] + if(needRefresh) { + role = await RoleModel.resetTowerCnt(roleId, curTime); + const batchCode = genCode(8); + let tasksData = await TowerTaskRecModel.getPreTasks(roleId); + let preTasksMap = treatPreTasks(tasksData); + for(let [batchCode, preTasks] of preTasksMap) { + if(preTasks && preTasks.length) { + let checkResult = checkTaskRewards(batchCode, preTasks ); + if(checkResult) { + await sendMailByContent(MAIL_TYPE.TOWER_TASK_REWARD, roleId, { goods: checkResult.rewards }); + await TowerTaskRecModel.finishTask(batchCode, preTasks.map(cur => cur.taskCode)); + }; + } + } + + curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, []); // 新建任务 + + // 重置派遣次数 + towerTaskReCnt = role.towerTaskReCnt; + } + if(curTasks.length <=0 ) { + curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务 + } + + let refRemainTime = getRemainTime(curTime); + let nextCostGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime); + + return { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold, towerTaskReCnt } +} + +function treatPreTasks(tasks: TowerTaskRecType[]) { + let map = new Map(); + for(let task of tasks) { + if(!map.has(task.batchCode)) { + map.set(task.batchCode, []); + } + map.get(task.batchCode).push(task); + } + return map +} + +export function checkTaskRewards(batchCode: string, tasks: TowerTaskRecType[]) { + const curTime = new Date(); + let compTasks: string[] = []; + let rewards: RewardInter[] = []; + for (let task of tasks) { + if ( task.batchCode == batchCode && task.status === TOWER_TASK_STATUS.DOINING) { + let {completeTime, reward, termsForAdd, additionalReward} = gameData.towerTask.get(task.taskId); + if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) { + compTasks.push(task.taskCode); + rewards.push(...reward); + if(termsForAdd) { + const result = checkTaskConditions(task.heroes, termsForAdd); + if(result) { + rewards.push(...additionalReward); + } + } + } + } + } + return { compTasks, rewards }; +} + +export async function checkTowerWar(roleId: string, battleId: number, seqIds: number[], heroes: HeroType[]) { + let { towerLv } = await RoleModel.findByRoleId(roleId); + const towerInfo = gameData.tower.get(towerLv); + if (!towerInfo) { + console.error(`天梯层数异常,lv ${towerLv} by ${roleId}`); + return { status: -1, resResult: resResult(STATUS.TOWER_INFO_NOT_FOUND) }; + } + const warIds = towerInfo.warArray; + + if (warIds.indexOf(battleId) === -1) { + return { status: -1, resResult: resResult(STATUS.TOWER_WRONG_BATTLE_ID) }; + } + + const tower = await TowerRecordModel.getRecordByLv(roleId, towerLv); + if (!tower) { + return { status: -1, resResult: resResult(STATUS.TOWER_NOT_FOUND) }; + } + let { heroes: recHeroes = [], warStatus = [] } = tower; + let dicWar = gameData.war.get(battleId); + let { fobiddenCharactor } = dicWar; + for (let hid of seqIds) { + if (recHeroes.indexOf(hid) !== -1) { + return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) }; + } + } + for(let {skinId, job} of heroes) { + if(checkForbiddenChar(skinId, job, fobiddenCharactor)) { + return { status: -1, resResult: resResult(STATUS.TOWER_HERO_FORBIDDEN) }; + } + } + const curWarStatus = warStatus.find(elem => elem.warId == battleId); + if (curWarStatus && curWarStatus.status) { + return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_CHALLENGE) }; + } + + return { + status: 0, data: { + heroes: recHeroes, warStatus: curWarStatus + } + }; +} + +export function checkForbiddenChar(hid: number, job: number, fobiddenCharactor: {type: number, id: number}[]) { + let dicHero = gameData.hero.get(hid); + let dicJob = gameData.job.get(job); + let flag = false; + for(let { type, id } of fobiddenCharactor) { + switch(type) { + case TOWER_FORBIDDEN_CHARA_TYPE.CHAR: + if(id == hid) flag = true; + break; + case TOWER_FORBIDDEN_CHARA_TYPE.JOB: + if(id == dicJob.job_class) flag = true; + break; + case TOWER_FORBIDDEN_CHARA_TYPE.CAMP: + if(id == dicHero.camp) flag = true; + break; + } + if(flag) break; + } + return flag; +} + +export async function towerBattleEnd(sid: string, roleId: string, serverId: number, battleCode: string, battleId: number, succeed: boolean, dbHeroes: number[], dbSeqIds: number[], damageRecords: pvpEndParamInter[]) { + if (succeed) { + let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode); + if (battleRec.battleId != battleId) { + return { status: -1, resResult: resResult(STATUS.BATTLE_ID_NOT_MATCH) }; + } + + let { towerLv, roleName } = await RoleModel.findByRoleId(roleId); + let { warStatus, heroes: recHeroes } = await TowerRecordModel.getRecordByLv(roleId, towerLv); + // console.log('*******', towerLv, heroes.join(), recHeroes.join()) + for (let hid of dbSeqIds) { + if (recHeroes.indexOf(hid) !== -1) { + return { status: -1, resResult: resResult(STATUS.TOWER_DUPLICATE_HERO) }; + } + } + + let inc = 0; + let dicTower = gameData.tower.get(towerLv); + // console.log('towerBattleEnd', towerLv, dicTower?.warArray, warStatus) + if(dicTower && dicTower.warArray) { + let wars = dicTower.warArray.filter(warId => { + let ws = warStatus.find(cur => cur.warId == warId); + let isPass = warId == battleId || (ws && ws.status == true); + return isPass; + }); + inc = wars.length == dicTower.warArray.length? 1: 0; + } + + let subHids: number[] = []; + for (let hid of dbHeroes) { + let damageRecord = damageRecords.find(cur => cur.hid == hid); + if (damageRecord && damageRecord.subHid > 0) subHids.push(damageRecord.subHid); + } + + const dbDamageSub = await HeroModel.findByHidsAndRole(roleId, subHids); + let newRec = await TowerRecordModel.updateRecord(roleId, towerLv, battleCode, battleId, [...dbSeqIds, ...dbDamageSub.map(cur => cur.seqId)], inc); + let towerReward: RewardInter[] = []; + if (inc === 1) { + let role = await RoleModel.towerLvUp(roleId); + // 更新redis + let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role); + + await createNewTowerRecord(roleId, role.towerLv); + const { reward } = gameData.tower.get(role.towerLv - 1); + if (reward) towerReward = [...reward]; + await checkAndStartHungUp(roleId, roleName, role.towerLv); + // 任务 + await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_TOWER_LV, { towerLv: role.towerLv - 1 }); + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: towerLv - 1, newLv: role.towerLv - 1 }) + + pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1); + } + return { + status: 0, + data: { + newRec, + towerReward, + towerStatus: !!inc + } + }; + } +} + +/** + * 创建下一层记录 + * @param roleId + * @param nextTowerLv 下一层塔 + */ +export async function createNewTowerRecord(roleId: string, nextTowerLv: number) { + const nextTowerInfo = gameData.tower.get(nextTowerLv); + if (nextTowerInfo) { + const { warArray } = nextTowerInfo; + const sts = warArray.map(id => { + return { warId: id, status: false }; + }); + + await TowerRecordModel.createRecord({ roleId, lv: nextTowerLv, warStatus: sts }); + } +} + +/** + * 当可以挂机的时候开始挂机 + * @param roleId + * @param roleName + * @param towerLv 当前楼层,升过级之后的层 + */ +export async function checkAndStartHungUp(roleId: string, roleName: string, towerLv: number) { + if (towerLv - 1 == dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV) { + await HangUpRecordModel.initRecord(roleId, roleName, towerLv); + } +} + +/** + * 是否可以挂机,如果是10,那么要打过10层,即11层时可以开始挂机 + * @param towerLv + * @returns + */ +export function canHungUp(towerLv: number) { + return towerLv - 1 >= dicParam.TOWER_HANG_UP.TOWER_HANG_UP_ENABLE_LV +} + +export async function calcuHangUpReward(role: RoleType, speedUp = false, speedUpCnt = 1, curTime = new Date()) { + let { roleId, towerLv = 1, hangUpSpdUpCnt = 0, lastSpdUpTime, vipStartTime } = role; + if (!canHungUp(towerLv)) { + return false + } + + let towerInfo = gameData.tower.get(towerLv - 1); // towerLv 是当前层,奖励计算按照已经通过的层,即上一层 + let baseReward = towerInfo.rewardOfcollect; + + if (speedUp) { // 加速,直接收取2小时收益,小数的累积和普通收取独立 + if (hangUpSpdUpCnt + speedUpCnt <= dicParam.TOWER_BOOST.TOWER_BOOSTTIME || !lastSpdUpTime || shouldRefresh(lastSpdUpTime, new Date)) { // 可加速 + let startTime = curTime; + let endTime = new Date(curTime.getTime() + HANG_UP_CONSTS.SPD_UP_REC_TIME); + let deltaTime = endTime.getTime() - startTime.getTime(); // 累计的挂机时间,受最大时间限制 + + let goods: {gid: number, count: number}[] = []; + let spdUpRec = await HangUpSpdUpRecModel.getLatestSpdUpRec(roleId); + if (spdUpRec) { + let { notReceivedGoodsList = [], cnt } = spdUpRec; + let notReceivedGoods = notReceivedGoodsList.find(cur => cur.cnt == cnt); + goods = notReceivedGoods ? notReceivedGoods.goods : []; + } + + let { timeReward, needReceiveGoods } = getVipHungupReward(startTime.getTime(), endTime.getTime(), baseReward, goods, vipStartTime); + + return { + endLv: towerLv, startTime, deltaTime, endTime, timeReward, needReceiveGoods + }; + } else { + return false + } + } else { + let { startTime } = await HangUpRecordModel.getCurRec(roleId); + let endTime = curTime; // 挂机结束时间,现在到开始时间,经历了10的倍数的时间 + let deltaTime = curTime.getTime() - startTime.getTime(); // 累计的挂机时间,受最大时间限制 + if (deltaTime > HANG_UP_CONSTS.MAX_TIME) { + deltaTime = HANG_UP_CONSTS.MAX_TIME; + startTime = new Date(curTime.getTime() - deltaTime); + endTime = curTime; // 累积到超过24小时,那么结束时间和下一次开启时间就取整了 + } else { + let multiReal = Math.floor(deltaTime / HANG_UP_CONSTS.UNIT_TIME);// 距开始挂机实际过去的时间单位 + endTime = new Date(startTime.getTime() + multiReal * HANG_UP_CONSTS.UNIT_TIME) + } + + let lastRec = await HangUpRecordModel.getLastRec(roleId); + let notReceivedGoods = lastRec ? lastRec.notReceivedGoods : []; + + let { timeReward, needReceiveGoods } = getVipHungupReward(startTime.getTime(), endTime.getTime(), baseReward, notReceivedGoods, vipStartTime); + + return { + endLv: towerLv, startTime, deltaTime, endTime, timeReward, needReceiveGoods + }; + } +} + +function checkCond(heroes: TaskHero[], type: number, param: number, cnt: number) { + + let heroCnt = 0; + + switch (type) { + case 1: + for (let { star, colorStar } of heroes) { + if (star + colorStar >= param) { + heroCnt++; + } + } + break; + case 2: + for (let { camp } of heroes) { + if (camp === param) { + heroCnt++; + } + } + break; + case 3: + for (let { jobClass } of heroes) { + if (jobClass === param) { + heroCnt++; + } + } + break; + default: + break; + } + if (heroCnt >= cnt) { + return true; + } + return false; +} + +export function checkTaskConditions(heroes: TaskHero[], condition: { type: number, param: number, count: number }[]) { + + let res = true; + for (let { type, param, count } of condition) { + const checkRes = checkCond(heroes, type, param, count); + if (!checkRes) { + res = false; + break; + } + } + return res; +} + +export async function refreshTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, oldTasks:TowerTaskRecType[]) { + let needFloor = !oldTasks || oldTasks.length <= 0; // 首次刷新需要一个保底 + + let ridTaskIds: number[] = []; + let positions = new Map (); // 需要创建或更新 + for(let i = 1; i <= dicParam.TOWER_SEARCH.TOWER_SEARCH_LIMITED; i++) { + positions.set(i, null); + } + let tasks: TowerTaskRecType[] = []; + for(let task of oldTasks) { + if( task.status == TOWER_TASK_STATUS.WAITING ) { + positions.set(task.position, task); + } else { + positions.delete(task.position); + ridTaskIds.push(task.taskId); + tasks.push(task); + } + } + + for(let [ position, task ] of positions) { + let dicOldTask = task? gameData.towerTask.get(task.taskId): null; + + let dicTask = randomTask(towerLv, dicOldTask?dicOldTask.quality: 0, ridTaskIds); + if(!dicTask) break; // 任务池没有可刷新了 + + let { taskId, quality } = dicTask; + if(quality == 4 || quality == 5) needFloor = false; + if(task) { // 更新 + tasks.push(await TowerTaskRecModel.updateTask(roleId, batchCode, position, taskId)); + } else { + tasks.push(await TowerTaskRecModel.createTask(roleId, roleName, batchCode, taskId, position)); + } + ridTaskIds.push(taskId); + } + + + if(needFloor) { // 塞一个保底 + let dicTask = randomTask(towerLv, 3, ridTaskIds); + if(dicTask) { + let index = Math.floor(Math.random() * tasks.length); + tasks[index] = await TowerTaskRecModel.updateTask(roleId, batchCode, tasks[index].position, dicTask.taskId); + } + } + + return tasks +} + +function randomTask(towerLv: number, oldQuality: number, rids: number[]) { + let qualityRange = oldQuality + 1; + + let randomList: DicTowerTask[] = []; + while(randomList.length <= 0) { // 如果这个品质范围里面没有,就降一品质再找 + for (let [_id, task] of gameData.towerTask) { + if(task.quality >= qualityRange && !rids.includes(task.taskId)) { + let { suitFloor: { min, max } } = task; + let flag = max ? (towerLv >= min && towerLv <= max) : (towerLv >= min); + if (flag) { + randomList.push(task); + } + } + } + if(randomList.length <= 0) qualityRange--; + if(qualityRange == 0) return null; + } + + let { dic } = getRandEelmWithWeight(randomList); + + return dic; +} + +// /** +// * 创建新的派遣任务 +// * @param towerLv 玩家层数 +// * @param roleId 玩家id +// * @param roleName 玩家名 +// * @param hideNum 隐藏的任务数量 +// */ +// export async function createCurTasks(towerLv: number, batchCode: string, roleId: string, roleName: string, hideNum: number, showNum: number, rids: Array) { + +// let returnTasks = new Array(); +// const arr = [{ refreshStatus: 0, num: hideNum }, { refreshStatus: 1, num: showNum }]; +// for (let { refreshStatus, num } of arr) { +// let taskIds = []; +// for (let i = 0; i < num; i++) { +// } +// const curTasks = await TowerTaskRecModel.createTasks(roleId, roleName, batchCode, taskIds, refreshStatus); + +// if (refreshStatus == 1) { +// returnTasks = curTasks; +// } +// } + +// return returnTasks; +// } + +export function getRemainTime(curTime: Date) { + let nextTime = getTimeFunM(curTime).getAfterDayWithHour(); + return Math.floor((nextTime - curTime.getTime()) / 1000); +} + +export function treatTask(recs: Array, curTime: Date) { + return recs.map(cur => { + let { heroes, batchCode, taskId, taskCode, status, completeTime, position } = cur; + + let getStatusResult = getTaskStatus(status, completeTime, curTime); + return { position, heroes, batchCode, taskId, taskCode, completeTime, ...getStatusResult } + }).sort((a, b) => { + return a.position - b.position; + }); +} + +// 刷新任务,正在进行中的部分保留,没有进行中的刷掉 +export function getDoingOrWaitingTasks(taskList: Array, curTime: Date) { + let doingTaskCode = new Array(), waitingTaskCode = new Array(), doingIds = new Array(); + for (let task of taskList) { + let { status } = getTaskStatus(task.status, task.completeTime, curTime); + if (status == 1 || status == 2) { + doingTaskCode.push(task.taskCode); + doingIds.push(task.taskId); + } else if (status == 0 || status == 3) { + waitingTaskCode.push(task.taskCode); + } + } + return { doingTaskCode, waitingTaskCode, doingIds } +} + +export function getTaskStatus(status: number, completeTime: Date, curTime: Date) { + let remainTime = 0; + if (status == 1) { + // console.log(curTime.getTime(), completeTime.getTime()) + remainTime = Math.floor((completeTime.getTime() - curTime.getTime()) / 1000); + if (remainTime < 0) { + status = 2; remainTime = 0; + } + } + + return { status, remainTime } +} + +export async function getTasksReward(roleId: string, curTime: Date) { + let oldTasks = await TowerTaskRecModel.getCurTasks(roleId); + let goods: ItemInter[] = []; + for (let task of oldTasks) { + let { completeTime, reward, termsForAdd, additionalReward } = gameData.towerTask.get(task.taskId); + if (task.sendTime && task.sendTime.getTime() + completeTime * 1000 < curTime.getTime()) { + goods = goods.concat(reward); + if (termsForAdd) { + const result = checkTaskConditions(task.heroes, termsForAdd); + if (result) { + goods.push(...additionalReward); + } + } + } + } + return goods +} + +/** + * 获取随机机器人数据 + * @param cnt 机器人数量 + * @param withAttr 是否返回属性,false: 仅返回阵容 + */ +export function getRandRobot(cnt = 1, withAttr = false) { + let setInfo = getRandExpedition(cnt); + if (!setInfo || setInfo.length !== cnt) return null; + + let robots: ComRoleStatusHero[][] = []; + for (let info of setInfo) { + if (!info || !info.warId) continue; + const warInfo = gameData.warJson.get(info.warId); + if (!warInfo || !warInfo.length) continue; + + let heroes: ComRoleStatusHero[] = []; + for (let hero of warInfo) { + if (hero && hero.relation === 2 && hero.actorId) { + let dicHero = gameData.hero.get(hero.actorId); + heroes.push(new ComRoleStatusHero({ + hid: hero.actorId, + skinId: hero.actorId, + star: hero.star? hero.star: dicHero.initialStar, + colorStar: hero.star? 0: dicHero.initialColorStar, + lv: hero.lv, + quality: dicHero.quality + })); + } + } + robots.push(heroes); + } + return robots; +} + +/** + * 获得下一次刷新派遣的花费 + * @param times 玩家表上的次数 + * @param refTime 玩家表上的刷新时间 + * @returns + */ +export function getTowerTaskCostGold(times: number, refTime: Date) { + if(shouldRefresh(refTime, new Date())) { + times = 0; + } + let cost = (times + 1) * dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_FEE; + if(cost > dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX) cost = dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE_MAX; + return cost; +} + +/** + * 多次加速挂机消耗的元宝 + * @param originCnt 玩家表里原来的次数 + * @param count 这次加速几次 + * @returns + */ +export function getManyHangSpdUpCostGold(originCnt: number, count: number) { + let gold = 0; + for(let i = 1; i <= count; i++) { + let num = originCnt + i; + gold += getHangSpdUpCostGold(num); + } + return gold +} + +/** + * 计算加速挂机消耗的元宝 + * @param times 第几次,如果你没有加速过,这里给1 + * @returns + */ +export function getHangSpdUpCostGold(times:number) { + if(times <= dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) { + return 0 + } else { + let cost = (times - dicParam.TOWER_BOOST.TOWER_BOOSTFREETIME) * dicParam.TOWER_BOOST.TOWER_BOOSTCAST; + if(cost > dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX) cost = dicParam.TOWER_BOOST.TOWER_BOOSTCASTMAX; + return cost; + } +} diff --git a/game-server/app/services/chatChannelService.ts b/game-server/app/services/chatChannelService.ts index 21812d7e1..c1db6571b 100644 --- a/game-server/app/services/chatChannelService.ts +++ b/game-server/app/services/chatChannelService.ts @@ -1,213 +1,213 @@ - -import { addGVGHistoryAreas, addGVGHistoryAreaTeam, addGVGHistoryCityTeam, addRedisChannel, delGVGHistoryAreas, delGVGHistoryAreaTeam, delGVGHistoryCityTeam, getGVGHistoryAreas, getGVGHistoryAreaTeam, getGVGHistoryCityTeam, redisChannelServer } from './redisService'; -import { groupRoomId } from './chatService'; -import { pinus } from 'pinus'; -import { crc32 } from 'crc'; -import { CHANNEL_PREFIX } from '../consts'; - -export async function channelServer(roomId: string) { - const existSid = await redisChannelServer(roomId); - if (existSid) { - return existSid; - } - const servers = pinus.app.getServersByType('chat'); - if (!servers || !servers.length) return null; - - let index = Math.abs(crc32(roomId)) % servers.length; - const newSid = servers[index].id; - const addResult = await addRedisChannel(roomId, newSid); - if (!addResult) return null; - return newSid; -} - -async function addRoleToChannel(roomId: string, roleId: string, sid: string) { - const channelSid = await channelServer(roomId); - await pinus.app.rpc.chat.chatRemote.addChannel.toServer(channelSid, roomId, roleId, sid); -} - -export async function addRoleToSysChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.SYS, serverId); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToWorldChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToGuildChannel(roleId: string, sid: string, guildCode: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToCityChannel(roleId: string, sid: string, serverId: number, cityId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToGuildAuctionChannel(roleId: string, sid: string, guildCode: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToWorldAuctionChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.WORLD_AUCTION, serverId); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToGroupShopChannel(roleId: string, sid: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); - await addRoleToChannel(roomId, roleId, sid); -} - -export async function addRoleToAreaChannel(roleId: string, groupKey: string, areaIds: number[], sid: string) { - for(let areaId of areaIds) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); - await addRoleToChannel(roomId, roleId, sid); - } - await addGVGHistoryAreas(roleId, groupKey, areaIds); -} - -export async function addRoleToAreaTeamChannel(roleId: string, groupKey: string, areaId: number, sid: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); - await addRoleToChannel(roomId, roleId, sid); - await addGVGHistoryAreaTeam(roleId, groupKey, areaId); -} - -export async function addRoleToGVGCityChannel(roleId: string, groupKey: string, cityId: number, sid: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); - await addRoleToChannel(roomId, roleId, sid); - await addGVGHistoryCityTeam(roleId, groupKey, cityId); -} -async function leaveChannel(roomId: string, roleId: string, sid: string) { - const channelSid = await channelServer(roomId); - await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid); -} - -export async function leaveSysChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.SYS, serverId); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveWorldChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveCityChannel(roleId: string, sid: string, serverId: number, cityId: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveGuildAuctionChannel(roleId: string, sid: string, guildCode: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveWorldAuctionChannel(roleId: string, sid: string, serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.WORLD_AUCTION, serverId); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveGroupShopChannel(roleId: string, sid: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveGuildChannel(roleId: string, sid: string, guildCode: string) { - if (!guildCode) return; - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); - await leaveChannel(roomId, roleId, sid); -} - -export async function leaveGVGAreaChannel(roleId: string, sid: string) { - let keys = await getGVGHistoryAreas(roleId)||[]; - for(let key of keys) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, key); - await leaveChannel(roomId, roleId, sid); - } - await delGVGHistoryAreas(roleId); -} - -export async function leaveGVGAreaTeamChannel(roleId: string, sid: string) { - let channelName = await getGVGHistoryAreaTeam(roleId); - if(channelName) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, channelName); - await leaveChannel(roomId, roleId, sid); - } - await delGVGHistoryAreaTeam(roleId); -} - -export async function leaveGVGCityTeamChannel(roleId: string, sid: string) { - let channelName = await getGVGHistoryCityTeam(roleId); - if(channelName) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, channelName); - await leaveChannel(roomId, roleId, sid); - } - await delGVGHistoryCityTeam(roleId); -} - -export async function getWorldChannelSid(serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGuildChannelSid(guildCode: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getCityChannelSid(serverId: number, cityId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGuildAuctionChannelSid(guildCode: string) { - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getWorldAuctionChannelSid(serverId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.CITY, serverId); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGroupShopSid() { - const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGVGAreaChannelSid(groupKey: string, areaId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGVGAreaTeamChannelSid(groupKey: string, areaId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); - const channelSid = await channelServer(roomId); - return channelSid; -} - -export async function getGVGCityTeamChannelSid(groupKey: string, cityId: number) { - const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); - const channelSid = await channelServer(roomId); - return channelSid; -} - -async function delChannel(roomId: string) { - const channelSid = await channelServer(roomId); - await pinus.app.rpc.chat.chatRemote.deleteChannel.toServer(channelSid, roomId); -} - -export async function delGuildChannel(guildCode: string) { - if (!guildCode) return; - const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); - await delChannel(roomId); -} \ No newline at end of file + +import { addGVGHistoryAreas, addGVGHistoryAreaTeam, addGVGHistoryCityTeam, addRedisChannel, delGVGHistoryAreas, delGVGHistoryAreaTeam, delGVGHistoryCityTeam, getGVGHistoryAreas, getGVGHistoryAreaTeam, getGVGHistoryCityTeam, redisChannelServer } from './redisService'; +import { groupRoomId } from './chatService'; +import { pinus } from 'pinus'; +import { crc32 } from 'crc'; +import { CHANNEL_PREFIX } from '@consts'; + +export async function channelServer(roomId: string) { + const existSid = await redisChannelServer(roomId); + if (existSid) { + return existSid; + } + const servers = pinus.app.getServersByType('chat'); + if (!servers || !servers.length) return null; + + let index = Math.abs(crc32(roomId)) % servers.length; + const newSid = servers[index].id; + const addResult = await addRedisChannel(roomId, newSid); + if (!addResult) return null; + return newSid; +} + +async function addRoleToChannel(roomId: string, roleId: string, sid: string) { + const channelSid = await channelServer(roomId); + await pinus.app.rpc.chat.chatRemote.addChannel.toServer(channelSid, roomId, roleId, sid); +} + +export async function addRoleToSysChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.SYS, serverId); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToWorldChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToGuildChannel(roleId: string, sid: string, guildCode: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToCityChannel(roleId: string, sid: string, serverId: number, cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToGuildAuctionChannel(roleId: string, sid: string, guildCode: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToWorldAuctionChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.WORLD_AUCTION, serverId); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToGroupShopChannel(roleId: string, sid: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); + await addRoleToChannel(roomId, roleId, sid); +} + +export async function addRoleToAreaChannel(roleId: string, groupKey: string, areaIds: number[], sid: string) { + for(let areaId of areaIds) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); + await addRoleToChannel(roomId, roleId, sid); + } + await addGVGHistoryAreas(roleId, groupKey, areaIds); +} + +export async function addRoleToAreaTeamChannel(roleId: string, groupKey: string, areaId: number, sid: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); + await addRoleToChannel(roomId, roleId, sid); + await addGVGHistoryAreaTeam(roleId, groupKey, areaId); +} + +export async function addRoleToGVGCityChannel(roleId: string, groupKey: string, cityId: number, sid: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); + await addRoleToChannel(roomId, roleId, sid); + await addGVGHistoryCityTeam(roleId, groupKey, cityId); +} +async function leaveChannel(roomId: string, roleId: string, sid: string) { + const channelSid = await channelServer(roomId); + await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid); +} + +export async function leaveSysChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.SYS, serverId); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveWorldChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveCityChannel(roleId: string, sid: string, serverId: number, cityId: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveGuildAuctionChannel(roleId: string, sid: string, guildCode: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveWorldAuctionChannel(roleId: string, sid: string, serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.WORLD_AUCTION, serverId); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveGroupShopChannel(roleId: string, sid: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveGuildChannel(roleId: string, sid: string, guildCode: string) { + if (!guildCode) return; + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); + await leaveChannel(roomId, roleId, sid); +} + +export async function leaveGVGAreaChannel(roleId: string, sid: string) { + let keys = await getGVGHistoryAreas(roleId)||[]; + for(let key of keys) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, key); + await leaveChannel(roomId, roleId, sid); + } + await delGVGHistoryAreas(roleId); +} + +export async function leaveGVGAreaTeamChannel(roleId: string, sid: string) { + let channelName = await getGVGHistoryAreaTeam(roleId); + if(channelName) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, channelName); + await leaveChannel(roomId, roleId, sid); + } + await delGVGHistoryAreaTeam(roleId); +} + +export async function leaveGVGCityTeamChannel(roleId: string, sid: string) { + let channelName = await getGVGHistoryCityTeam(roleId); + if(channelName) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, channelName); + await leaveChannel(roomId, roleId, sid); + } + await delGVGHistoryCityTeam(roleId); +} + +export async function getWorldChannelSid(serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGuildChannelSid(guildCode: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getCityChannelSid(serverId: number, cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGuildAuctionChannelSid(guildCode: string) { + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD_AUCTION, guildCode); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getWorldAuctionChannelSid(serverId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.CITY, serverId); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGroupShopSid() { + const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGVGAreaChannelSid(groupKey: string, areaId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGVGAreaTeamChannelSid(groupKey: string, areaId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); + const channelSid = await channelServer(roomId); + return channelSid; +} + +export async function getGVGCityTeamChannelSid(groupKey: string, cityId: number) { + const roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); + const channelSid = await channelServer(roomId); + return channelSid; +} + +async function delChannel(roomId: string) { + const channelSid = await channelServer(roomId); + await pinus.app.rpc.chat.chatRemote.deleteChannel.toServer(channelSid, roomId); +} + +export async function delGuildChannel(guildCode: string) { + if (!guildCode) return; + const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); + await delChannel(roomId); +} diff --git a/game-server/app/services/chatService.ts b/game-server/app/services/chatService.ts index c63dc7f15..f3d019184 100644 --- a/game-server/app/services/chatService.ts +++ b/game-server/app/services/chatService.ts @@ -1,504 +1,504 @@ -import { CHAT_SYSTEM } from './../pubUtils/dicParam'; -import { PrivateChatRec } from './../db/ChatInfo'; -import { RoleModel } from './../db/Role'; -import { GroupMessageModel } from './../db/GroupMessage'; -import { CounterModel } from './../db/Counter'; -import { PrivateMessageModel, PrivateMessageParam, PrivateMessageType } from './../db/PrivateMessage'; -import { GroupMessageParam, GroupMessageType } from '../db/GroupMessage'; -import { genCode, resResult } from '../pubUtils/util'; -import { pinus } from 'pinus'; -import { CHANNEL_PREFIX, MSG_CODE_LEN, MSG_STATUS, MSG_TYPE, MSG_SOURCE, PUSH_ROUTE, FRIEND_RELATION_TYPE } from '../consts'; -import { getRoleOnlineInfo } from './redisService'; -import { ChatInfoModel } from '../db/ChatInfo'; -import { AccuseRecModel, AccueseParam } from '../db/AccuseRec'; -import { getSimpleRoleInfo, getSimpleRoleInfos } from './roleService'; -import { sendMessageToAllWithSuc, sendMessageToCityWithSuc, sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToTeam, sendMessageToUserWithSuc } from './pushService'; -import { RegionModel } from '../db/Region'; -import { getAllGroupOfServer, getGVGGroupIdOfServer, getGVGServersByGroupId, getPvpServersByGroupId } from './serverService'; -import { GVGLeagueModel } from '../db/GVGLeague'; -import { uniq } from 'underscore'; - -export * from './chatChannelService'; -export * from './sysChatService'; - -/** - * @description 生成私聊房间号 - * @export - * @param {string[]} roleIds - * @returns - */ -export function privateRoomId(roleId: string, targetRoleId: string) { - return [roleId, targetRoleId].sort().join('_'); -} - -/** - * @description 生成群聊房间号 - * @export - * @param {string} channel - * @param {string} channelId - * @returns - */ -export function groupRoomId(channel: string, channelId?: string | number) { - return channelId?`${channel}_${channelId}`: `${channel}`; -} - -function msgCounterName(roomId: string) { - return `chat_${roomId}`; -} - -/** - * @description 设置群消息和私聊消息的公共字段 - * @param {(PrivateMessageParam | GroupMessageParam)} msg - */ -async function setupBaseMsgParm(msg: PrivateMessageParam | GroupMessageParam ) { - msg.msgCode = genCode(MSG_CODE_LEN); - if(!msg.status) msg.status = MSG_STATUS.NORMAL; - if (!msg.roomId) { - console.error('roomId needed while setup msg parameter'); - return; - } - msg.seqId = await CounterModel.getNewCounter({name: msgCounterName(msg.roomId), def: 1}); -} - -/** - * @description 生成私聊消息数据 - */ -async function createPrivateMsgData(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, relation: number) { - const result: PrivateMessageParam = {roleId, roleName, type, source, content, targetRoleId, targetMsgCode}; - result.roomId = privateRoomId(roleId, targetRoleId); - result.status = relation == FRIEND_RELATION_TYPE.HAS_BLOCKED? MSG_STATUS.BLOCKED: MSG_STATUS.NORMAL; - await setupBaseMsgParm(result); - return result; -} - -/** - * @description 生成群聊消息数据 - */ -async function createGroupMsgData(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, otherInfo = '') { - const result: GroupMessageParam = {roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode, otherInfo }; - result.roomId = groupRoomId(channel, channelId); - await setupBaseMsgParm(result); - return result; -} - -/** - * @description 数据库中创建私聊数据,需要更新聊天双方的聊天时间和未读消息数 - * @export - * @param {string} roleId - * @param {string} roleName - * @param {number} type - * @param {number} source - * @param {string} content - * @param {string} targetRoleId 消息接收者 - * @param {string} targetMsgCode 回复某条消息的唯一标识 - * @returns - */ -export async function createPrivateMsg(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, relation: number) { - const msgData: PrivateMessageParam = await createPrivateMsgData(roleId, roleName, type, source, content, targetRoleId, targetMsgCode, relation); - const result: PrivateMessageType = await PrivateMessageModel.createMsg(msgData); - - const curTime = new Date(); - await updateRecentChats(true, roleId, targetRoleId, curTime); - if(result.status == MSG_STATUS.NORMAL) { - await updateRecentChats(false, targetRoleId, roleId, curTime); - } - return result; -} - -/** - * @description 数据库中创建群聊数据 - * @export - * @param {string} roleId - * @param {string} roleName - * @param {string} channel - * @param {string} channelId - * @param {number} type 消息类型 - * @param {number} source 消息来源,根据配表 - * @param {string} content 富文本的 content 为 JSON.stringfy 的对象 - * @param {string} targetRoleId - * @param {string} targetMsgCode - * @returns - */ -export async function createGroupMsg(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, otherInfo = '') { - const msgData: GroupMessageParam = await createGroupMsgData(roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode, otherInfo); - const result: GroupMessageType = await GroupMessageModel.createMsg(msgData); - return result; -} - -/** - * @description 给某个玩家发送消息 - * @export - * @param {string} targetRoleId - * @param {(PrivateMessageType | GroupMessageType)} msg - */ -export async function pushMsgToRole(msg: PrivateMessageType | GroupMessageType) { - const targetRoleId = msg.targetRoleId!; - if(msg.status == MSG_STATUS.BLOCKED) return; - - const { sid } = await getRoleOnlineInfo(targetRoleId); - if (sid) { - const roleInfo = await getSimpleRoleInfo(msg.roleId); - sendMessageToUserWithSuc(targetRoleId, PUSH_ROUTE.PRIVATE_MSG, { ...msg, roleInfo }, sid); - } -} - -/** - * @description 给某个群组发送消息 - * @export - * @param {GroupMessageType} msg 群消息体 - * @returns - */ -export async function pushGroupMsgToRoom(msg: GroupMessageType) { - if (!msg) return; - const roleInfo = await getSimpleRoleInfo(msg.roleId); - if(msg.channel == CHANNEL_PREFIX.WORLD || msg.channel == CHANNEL_PREFIX.SYS || msg.channel == CHANNEL_PREFIX.WORLD_AUCTION) { - let serverId = parseInt(msg.channelId); - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); - } else if(msg.channel == CHANNEL_PREFIX.GUILD || msg.channel == CHANNEL_PREFIX.GUILD_AUCTION) { - let guildCode = msg.channelId; - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }) - } else if (msg.channel == CHANNEL_PREFIX.TEAM) { - let teamCode = msg.channelId; - await sendMessageToTeam(teamCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); - } else if (msg.channel == CHANNEL_PREFIX.CITY) { - let arr = msg.channelId.split('_'); - await sendMessageToCityWithSuc(parseInt(arr[0]), parseInt(arr[1]), PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); - } else if (msg.channel == CHANNEL_PREFIX.GVG) { - let groupId = parseInt(msg.channelId); - let gvgServerIds = await getGVGServersByGroupId(groupId); - let pvpServerIds = await getPvpServersByGroupId(groupId); - let serverIds = uniq([...gvgServerIds, ...pvpServerIds]); - for(let serverId of serverIds) { - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); - } - } else if (msg.channel == CHANNEL_PREFIX.LEAGUE) { - let guildCodes = msg.otherInfo? msg.otherInfo.split('|'): []; - for(let guildCode of guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); - } - } -} - -export async function pushGroupMsgToAll(msg: GroupMessageType, filterCb?: ({ lv, topLineupCe }) => boolean) { - if (!msg) return; - const roleInfo = await getSimpleRoleInfo(msg.roleId); - await sendMessageToAllWithSuc(PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }, filterCb); -} - -/** - * @description 获取私聊历史消息 - * @export - * @param {string} roleId - * @param {string} targetRoleId - * @param {number} fromSeqId 翻页时已经获取的最新消息标识 - * @param {number} count 期望获取的消息数量 - * @returns - */ -export async function getPrivateMessages(roleId: string, targetRoleId: string, fromSeqId: number, count: number) { - const result = await PrivateMessageModel.getMsgs(privateRoomId(roleId, targetRoleId), fromSeqId, count); - return result; -} - -function sendFromRole(msg: GroupMessageParam) { - return msg.source === MSG_SOURCE.ROLE_SEND_TEXT; -} - -/** - * @description 最近群聊消息 - * @param {string} roomId 群聊房间标识 - * @param {number} [count] 期望获取的消息数 - * @returns - */ -async function recentGroupMsgs(roomIds: string[], count?: number) { - const msgs = await GroupMessageModel.getMsgs(roomIds, Infinity, count || CHAT_SYSTEM.RECENT_GROUP_MSGS_CNT); - const roleIds = msgs - .map(msg => { return sendFromRole(msg) ? msg.roleId : null }) - .filter(roleId => !!roleId); - const roleInfos = await getSimpleRoleInfos(roleIds); - const infos: string[] = []; - const filterMsgs = msgs.filter(msg => { - if(!msg.otherInfo) return true; - if(infos.indexOf(msg.otherInfo) == -1) { - infos.push(msg.otherInfo); - return true - } - return false; - }) - const result = roleInfos ? - filterMsgs.map(msg => { - if (!sendFromRole(msg)) return msg; - for (let roleInfo of roleInfos) { - if (roleInfo.roleId === msg.roleId) { - return { ...msg, roleInfo }; - } - } - }) - : filterMsgs; - return result.filter(cur => cur) || []; -} - -/** - * @description 获取最近的战区聊天消息 - * @export - * @param {number} serverId 用区服编号做房间标识 - * @param {number} [count] - * @returns - */ -export async function recentServerGroupMsgs(serverId: number, count?: number) { - let groupIds = await getAllGroupOfServer(serverId); - let roomIds = groupIds.map(groupId => groupRoomId(CHANNEL_PREFIX.GVG, groupId)); - const result = await recentGroupMsgs(roomIds, count); - return result; -} - -/** - * @description 获取最近的世界聊天消息 - * @export - * @param {number} serverId 用区服编号做房间标识 - * @param {number} [count] - * @returns - */ -export async function recentWorldMsgs(serverId: number, count?: number) { - const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.WORLD, serverId)], count); - return result; -} - -/** - * @description 获取最近的系统聊天消息 - * @export - * @param {number} serverId 用区服编号做房间标识 - * @param {number} [count] - * @returns - */ -export async function recentSysMsgs(serverId: number, count?: number) { - const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.SYS, serverId)], count); - return result; -} - -/** - * @description 获取最近的军团聊天消息 - * @export - * @param {string} guildCode 用军团编号作为房间标识 - * @param {number} [count] - * @returns - */ -export async function recentGuildMsgs(guildCode: string, count?: number) { - if(!guildCode) return []; - const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.GUILD, guildCode)], count); - return result; -} - -/** - * @description 获取最近的联军聊天消息 - * @export - * @param {string} guildCode 用区服编号做房间标识 - * @param {number} [count] - * @returns - */ -export async function recentLeagueMsgs(guildCode: string, count?: number) { - if(!guildCode) return []; - let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - if(!myLeague) return []; - const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode)], count); - return result; -} - -/** - * @description 创建新的私聊记录 - * @param {boolean} sender 给发送者还是接收者创建,发送者发消息的时候也阅读了消息 - * @param {Date} curTime 当前时间 - * @param {*} targetRoleId 聊天对象 - * @returns - */ -function createChatRec(sender: boolean, curTime: Date, targetRoleId) { - const result: PrivateChatRec = { - // 接收者没有阅读时间,发送者未读数为 0 - targetRoleId, lastChatTime: curTime, lastReadTime: sender ? curTime : null, unreadCnt: sender ? 0 : 1, isTop: false, setTopTime: curTime - }; - return result; -} - -/** - * @description 更新最近聊天记录 - * @param {boolean} sender 同 createChatRec 接口参数 - * @param {string} roleId 更新此玩家的聊天记录 - * @param {string} targetRoleId roleId 的聊天对象 - * @param {Date} curTime - */ -async function updateRecentChats(sender: boolean, roleId: string, targetRoleId: string, curTime: Date) { - const chatInfo = await roleChatInfos(roleId); - let recentPrivateChats: PrivateChatRec[] = chatInfo?.recentPrivateChats||[] - const recIdx = recentPrivateChats.findIndex(chat => { return chat.targetRoleId === targetRoleId }); - if (recIdx === -1) { - recentPrivateChats.push(createChatRec(sender, curTime, targetRoleId)); - } else { - recentPrivateChats[recIdx].lastChatTime = curTime; - const { lastReadTime, unreadCnt } = recentPrivateChats[recIdx]; - // 发送者的最后阅读时间也更新,接收者的未读消息数增加 - recentPrivateChats[recIdx].lastReadTime = sender ? curTime : lastReadTime; - recentPrivateChats[recIdx].unreadCnt = sender ? 0 : unreadCnt + 1; - } - await ChatInfoModel.updateInfo({ roleId, recentPrivateChats}); -} - -/** - * @description 获取聊天信息 - */ -export async function roleChatInfos(roleId: string, roleName?: string) { - if(!roleName) { - let role = await RoleModel.findByRoleId(roleId, 'roleName'); - roleName = role.roleName; - } - let result = await ChatInfoModel.findInfo(roleId); - if (!result) { - result = await ChatInfoModel.createInfo({ roleId, roleName }); - } - return result; -} - -/** - * @description 获取最近聊天记录,需要组织最近聊天玩家的信息 - */ -export async function recentPrivateChatInfos(roleId: string, roleName: string) { - const { recentPrivateChats } = await roleChatInfos(roleId, roleName); - recentPrivateChats - .sort((a, b) => { - if(a.isTop || b.isTop) { - if(a.isTop && b.isTop) { - return b.setTopTime.getTime() - a.setTopTime.getTime() - } else { - return (b.isTop?1:0) - (a.isTop?1:0); - } - } else { - return b.lastChatTime.getTime() - a.lastChatTime.getTime() - } - }) - .splice(CHAT_SYSTEM.RECENT_PRIVATE_CHATS_CNT); - if (!recentPrivateChats || !recentPrivateChats.length) return []; - - const roleInfos = await RoleModel.findByRoleIds(recentPrivateChats.map(chat => { return chat.targetRoleId })); - const chatInfos = recentPrivateChats.map( chat => { - for (let { roleId: targetRoleId, quitTime, loginTime, roleName: targetRoleName, title, guildName, head, frame, spine, lv } of roleInfos) { - if (targetRoleId === chat.targetRoleId) { - return { ...chat, quitTime, targetRoleName, title, guildName, head, frame, spine, lv, isOnline: quitTime === loginTime }; - } - } - }); - return chatInfos; -} - -/** - * @description 查看消息时更新查看时间和未读消息数 - */ -export async function updatePrivateMsgReadInfo(roleId: string, targetRoleId: string) { - const time = new Date(); - const chatInfo = await ChatInfoModel.updateReadInfo(roleId, targetRoleId, time); - if (!chatInfo || !chatInfo.recentPrivateChats) { - return null; - } - const chatRec = chatInfo.recentPrivateChats.find(rec => { return rec.targetRoleId === targetRoleId }); - return chatRec; -} - -/** - * @description 查看消息时更新查看时间和未读消息数 - */ -export async function updatePrivateMsgIsTop(roleId: string, targetRoleId: string, isTop: boolean) { - const time = new Date(); - const chatInfo = await ChatInfoModel.setTop(roleId, targetRoleId, isTop, time); - if (!chatInfo || !chatInfo.recentPrivateChats) { - return null; - } - const chatRec = chatInfo.recentPrivateChats.find(rec => { return rec.targetRoleId === targetRoleId }); - return chatRec; -} - -/** - * @description 查看消息时更新查看时间和未读消息数 - */ -export async function delPrivateMsg(roleId: string, targetRoleId: string) { - const chatInfo = await ChatInfoModel.delMsg(roleId, targetRoleId); - if (!chatInfo || !chatInfo.recentPrivateChats) { - return null; - } - return { targetRoleId }; -} - - -/** - * @description 发送组队一键邀请消息 - * @param {string} teamCode 队伍唯一标识 - */ -export async function pushTeamInviteMsg(roleId: string, roleName: string, guildCode: string, teamCode: string, blueprtId: number, blueprtLv: number, ceLimit: number) { - let msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.TEAM_INVITE, JSON.stringify({ roleName, teamCode, blueprtId }), null, null); - await pushGroupMsgToRoom(msgData); - return { msgData }; -} - -/** - * @description 发送组队私人邀请消息 - * @param {string} teamCode 队伍唯一标识 - */ - export async function pushFriendTeamInviteMsg(roleId: string, roleName: string, teamCode: string, blueprtId: number, targetRoleId: string, relation: number) { - const msgData = await createPrivateMsg(roleId, roleName, MSG_TYPE.RICH_TEXT, MSG_SOURCE.TEAM_INVITE, JSON.stringify({ roleName, teamCode, blueprtId}), targetRoleId, null, relation); - await pushMsgToRole(msgData); - return msgData; -} - - -export async function createAccuseData(roleId: string, roleName: string, targetRoleId: string, targetRoleName: string, targetMsgCode: string, reason: number) { - const data: AccueseParam = { - roleId, roleName, targetRoleId, targetRoleName, targetMsgCode, reason - }; - const result = await AccuseRecModel.createRec(data); - return result; -} - -/* -const client = new FCClient('1475752363809339', { - accessKeyID: 'LTAI5tFTwE7vwH5HGL7eV8xr', - accessKeySecret: 'HZznAZfOrmXttBMevhA55jQX3OGw9j', - region: 'cn-zhangjiakou', -}); - -export async function checkFilterWords(word: string) { - const resp = await client.post('/proxy/bantuUtils/filterWords/check',{ - word, - salt: "bantu1filter2word3test" - }, {}); - let hasBlock = true; - try { - let data = JSON.parse(resp.data); - hasBlock = data.status != 0; - } catch (e) { - console.log(e); - } - - return hasBlock; -} -*/ - -export function isApiClose() { - return pinus.app.get('apiIsClose'); -} - -export async function checkAndSetApiIsClose() { - let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); - setApiIsClose(region?.isCloseApi??false); -} - -export function setApiIsClose(isClose: boolean) { - pinus.app.set('apiIsClose', isClose); -} - -export async function setApiIsCloseToRemote(isClose: boolean) { - await pinus.app.rpc.activity.activityRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.battle.battleRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.chat.chatRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.connector.connectorRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.guild.guildRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.order.orderRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.role.roleRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.systimer.systimerRemote.setApiIsClose.broadcast(isClose); - await pinus.app.rpc.comBattle.comBattleRemote.setApiIsClose.broadcast(isClose); -} \ No newline at end of file +import { CHAT_SYSTEM } from '@pubUtils/dicParam'; +import { PrivateChatRec } from '@db/ChatInfo'; +import { RoleModel } from '@db/Role'; +import { GroupMessageModel } from '@db/GroupMessage'; +import { CounterModel } from '@db/Counter'; +import { PrivateMessageModel, PrivateMessageParam, PrivateMessageType } from '@db/PrivateMessage'; +import { GroupMessageParam, GroupMessageType } from '@db/GroupMessage'; +import { genCode, resResult } from '@pubUtils/util'; +import { pinus } from 'pinus'; +import { CHANNEL_PREFIX, MSG_CODE_LEN, MSG_STATUS, MSG_TYPE, MSG_SOURCE, PUSH_ROUTE, FRIEND_RELATION_TYPE } from '@consts'; +import { getRoleOnlineInfo } from './redisService'; +import { ChatInfoModel } from '@db/ChatInfo'; +import { AccuseRecModel, AccueseParam } from '@db/AccuseRec'; +import { getSimpleRoleInfo, getSimpleRoleInfos } from './roleService'; +import { sendMessageToAllWithSuc, sendMessageToCityWithSuc, sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToTeam, sendMessageToUserWithSuc } from './pushService'; +import { RegionModel } from '@db/Region'; +import { getAllGroupOfServer, getGVGGroupIdOfServer, getGVGServersByGroupId, getPvpServersByGroupId } from './serverService'; +import { GVGLeagueModel } from '@db/GVGLeague'; +import { uniq } from 'underscore'; + +export * from './chatChannelService'; +export * from './sysChatService'; + +/** + * @description 生成私聊房间号 + * @export + * @param {string[]} roleIds + * @returns + */ +export function privateRoomId(roleId: string, targetRoleId: string) { + return [roleId, targetRoleId].sort().join('_'); +} + +/** + * @description 生成群聊房间号 + * @export + * @param {string} channel + * @param {string} channelId + * @returns + */ +export function groupRoomId(channel: string, channelId?: string | number) { + return channelId?`${channel}_${channelId}`: `${channel}`; +} + +function msgCounterName(roomId: string) { + return `chat_${roomId}`; +} + +/** + * @description 设置群消息和私聊消息的公共字段 + * @param {(PrivateMessageParam | GroupMessageParam)} msg + */ +async function setupBaseMsgParm(msg: PrivateMessageParam | GroupMessageParam ) { + msg.msgCode = genCode(MSG_CODE_LEN); + if(!msg.status) msg.status = MSG_STATUS.NORMAL; + if (!msg.roomId) { + console.error('roomId needed while setup msg parameter'); + return; + } + msg.seqId = await CounterModel.getNewCounter({name: msgCounterName(msg.roomId), def: 1}); +} + +/** + * @description 生成私聊消息数据 + */ +async function createPrivateMsgData(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, relation: number) { + const result: PrivateMessageParam = {roleId, roleName, type, source, content, targetRoleId, targetMsgCode}; + result.roomId = privateRoomId(roleId, targetRoleId); + result.status = relation == FRIEND_RELATION_TYPE.HAS_BLOCKED? MSG_STATUS.BLOCKED: MSG_STATUS.NORMAL; + await setupBaseMsgParm(result); + return result; +} + +/** + * @description 生成群聊消息数据 + */ +async function createGroupMsgData(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, otherInfo = '') { + const result: GroupMessageParam = {roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode, otherInfo }; + result.roomId = groupRoomId(channel, channelId); + await setupBaseMsgParm(result); + return result; +} + +/** + * @description 数据库中创建私聊数据,需要更新聊天双方的聊天时间和未读消息数 + * @export + * @param {string} roleId + * @param {string} roleName + * @param {number} type + * @param {number} source + * @param {string} content + * @param {string} targetRoleId 消息接收者 + * @param {string} targetMsgCode 回复某条消息的唯一标识 + * @returns + */ +export async function createPrivateMsg(roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, relation: number) { + const msgData: PrivateMessageParam = await createPrivateMsgData(roleId, roleName, type, source, content, targetRoleId, targetMsgCode, relation); + const result: PrivateMessageType = await PrivateMessageModel.createMsg(msgData); + + const curTime = new Date(); + await updateRecentChats(true, roleId, targetRoleId, curTime); + if(result.status == MSG_STATUS.NORMAL) { + await updateRecentChats(false, targetRoleId, roleId, curTime); + } + return result; +} + +/** + * @description 数据库中创建群聊数据 + * @export + * @param {string} roleId + * @param {string} roleName + * @param {string} channel + * @param {string} channelId + * @param {number} type 消息类型 + * @param {number} source 消息来源,根据配表 + * @param {string} content 富文本的 content 为 JSON.stringfy 的对象 + * @param {string} targetRoleId + * @param {string} targetMsgCode + * @returns + */ +export async function createGroupMsg(roleId: string, roleName: string, channel: string, channelId: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string, otherInfo = '') { + const msgData: GroupMessageParam = await createGroupMsgData(roleId, roleName, channel, channelId, type, source, content, targetRoleId, targetMsgCode, otherInfo); + const result: GroupMessageType = await GroupMessageModel.createMsg(msgData); + return result; +} + +/** + * @description 给某个玩家发送消息 + * @export + * @param {string} targetRoleId + * @param {(PrivateMessageType | GroupMessageType)} msg + */ +export async function pushMsgToRole(msg: PrivateMessageType | GroupMessageType) { + const targetRoleId = msg.targetRoleId!; + if(msg.status == MSG_STATUS.BLOCKED) return; + + const { sid } = await getRoleOnlineInfo(targetRoleId); + if (sid) { + const roleInfo = await getSimpleRoleInfo(msg.roleId); + sendMessageToUserWithSuc(targetRoleId, PUSH_ROUTE.PRIVATE_MSG, { ...msg, roleInfo }, sid); + } +} + +/** + * @description 给某个群组发送消息 + * @export + * @param {GroupMessageType} msg 群消息体 + * @returns + */ +export async function pushGroupMsgToRoom(msg: GroupMessageType) { + if (!msg) return; + const roleInfo = await getSimpleRoleInfo(msg.roleId); + if(msg.channel == CHANNEL_PREFIX.WORLD || msg.channel == CHANNEL_PREFIX.SYS || msg.channel == CHANNEL_PREFIX.WORLD_AUCTION) { + let serverId = parseInt(msg.channelId); + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); + } else if(msg.channel == CHANNEL_PREFIX.GUILD || msg.channel == CHANNEL_PREFIX.GUILD_AUCTION) { + let guildCode = msg.channelId; + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }) + } else if (msg.channel == CHANNEL_PREFIX.TEAM) { + let teamCode = msg.channelId; + await sendMessageToTeam(teamCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); + } else if (msg.channel == CHANNEL_PREFIX.CITY) { + let arr = msg.channelId.split('_'); + await sendMessageToCityWithSuc(parseInt(arr[0]), parseInt(arr[1]), PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); + } else if (msg.channel == CHANNEL_PREFIX.GVG) { + let groupId = parseInt(msg.channelId); + let gvgServerIds = await getGVGServersByGroupId(groupId); + let pvpServerIds = await getPvpServersByGroupId(groupId); + let serverIds = uniq([...gvgServerIds, ...pvpServerIds]); + for(let serverId of serverIds) { + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); + } + } else if (msg.channel == CHANNEL_PREFIX.LEAGUE) { + let guildCodes = msg.otherInfo? msg.otherInfo.split('|'): []; + for(let guildCode of guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }); + } + } +} + +export async function pushGroupMsgToAll(msg: GroupMessageType, filterCb?: ({ lv, topLineupCe }) => boolean) { + if (!msg) return; + const roleInfo = await getSimpleRoleInfo(msg.roleId); + await sendMessageToAllWithSuc(PUSH_ROUTE.GROUP_MSG, { ...msg, roleInfo }, filterCb); +} + +/** + * @description 获取私聊历史消息 + * @export + * @param {string} roleId + * @param {string} targetRoleId + * @param {number} fromSeqId 翻页时已经获取的最新消息标识 + * @param {number} count 期望获取的消息数量 + * @returns + */ +export async function getPrivateMessages(roleId: string, targetRoleId: string, fromSeqId: number, count: number) { + const result = await PrivateMessageModel.getMsgs(privateRoomId(roleId, targetRoleId), fromSeqId, count); + return result; +} + +function sendFromRole(msg: GroupMessageParam) { + return msg.source === MSG_SOURCE.ROLE_SEND_TEXT; +} + +/** + * @description 最近群聊消息 + * @param {string} roomId 群聊房间标识 + * @param {number} [count] 期望获取的消息数 + * @returns + */ +async function recentGroupMsgs(roomIds: string[], count?: number) { + const msgs = await GroupMessageModel.getMsgs(roomIds, Infinity, count || CHAT_SYSTEM.RECENT_GROUP_MSGS_CNT); + const roleIds = msgs + .map(msg => { return sendFromRole(msg) ? msg.roleId : null }) + .filter(roleId => !!roleId); + const roleInfos = await getSimpleRoleInfos(roleIds); + const infos: string[] = []; + const filterMsgs = msgs.filter(msg => { + if(!msg.otherInfo) return true; + if(infos.indexOf(msg.otherInfo) == -1) { + infos.push(msg.otherInfo); + return true + } + return false; + }) + const result = roleInfos ? + filterMsgs.map(msg => { + if (!sendFromRole(msg)) return msg; + for (let roleInfo of roleInfos) { + if (roleInfo.roleId === msg.roleId) { + return { ...msg, roleInfo }; + } + } + }) + : filterMsgs; + return result.filter(cur => cur) || []; +} + +/** + * @description 获取最近的战区聊天消息 + * @export + * @param {number} serverId 用区服编号做房间标识 + * @param {number} [count] + * @returns + */ +export async function recentServerGroupMsgs(serverId: number, count?: number) { + let groupIds = await getAllGroupOfServer(serverId); + let roomIds = groupIds.map(groupId => groupRoomId(CHANNEL_PREFIX.GVG, groupId)); + const result = await recentGroupMsgs(roomIds, count); + return result; +} + +/** + * @description 获取最近的世界聊天消息 + * @export + * @param {number} serverId 用区服编号做房间标识 + * @param {number} [count] + * @returns + */ +export async function recentWorldMsgs(serverId: number, count?: number) { + const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.WORLD, serverId)], count); + return result; +} + +/** + * @description 获取最近的系统聊天消息 + * @export + * @param {number} serverId 用区服编号做房间标识 + * @param {number} [count] + * @returns + */ +export async function recentSysMsgs(serverId: number, count?: number) { + const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.SYS, serverId)], count); + return result; +} + +/** + * @description 获取最近的军团聊天消息 + * @export + * @param {string} guildCode 用军团编号作为房间标识 + * @param {number} [count] + * @returns + */ +export async function recentGuildMsgs(guildCode: string, count?: number) { + if(!guildCode) return []; + const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.GUILD, guildCode)], count); + return result; +} + +/** + * @description 获取最近的联军聊天消息 + * @export + * @param {string} guildCode 用区服编号做房间标识 + * @param {number} [count] + * @returns + */ +export async function recentLeagueMsgs(guildCode: string, count?: number) { + if(!guildCode) return []; + let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + if(!myLeague) return []; + const result = await recentGroupMsgs([groupRoomId(CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode)], count); + return result; +} + +/** + * @description 创建新的私聊记录 + * @param {boolean} sender 给发送者还是接收者创建,发送者发消息的时候也阅读了消息 + * @param {Date} curTime 当前时间 + * @param {*} targetRoleId 聊天对象 + * @returns + */ +function createChatRec(sender: boolean, curTime: Date, targetRoleId) { + const result: PrivateChatRec = { + // 接收者没有阅读时间,发送者未读数为 0 + targetRoleId, lastChatTime: curTime, lastReadTime: sender ? curTime : null, unreadCnt: sender ? 0 : 1, isTop: false, setTopTime: curTime + }; + return result; +} + +/** + * @description 更新最近聊天记录 + * @param {boolean} sender 同 createChatRec 接口参数 + * @param {string} roleId 更新此玩家的聊天记录 + * @param {string} targetRoleId roleId 的聊天对象 + * @param {Date} curTime + */ +async function updateRecentChats(sender: boolean, roleId: string, targetRoleId: string, curTime: Date) { + const chatInfo = await roleChatInfos(roleId); + let recentPrivateChats: PrivateChatRec[] = chatInfo?.recentPrivateChats||[] + const recIdx = recentPrivateChats.findIndex(chat => { return chat.targetRoleId === targetRoleId }); + if (recIdx === -1) { + recentPrivateChats.push(createChatRec(sender, curTime, targetRoleId)); + } else { + recentPrivateChats[recIdx].lastChatTime = curTime; + const { lastReadTime, unreadCnt } = recentPrivateChats[recIdx]; + // 发送者的最后阅读时间也更新,接收者的未读消息数增加 + recentPrivateChats[recIdx].lastReadTime = sender ? curTime : lastReadTime; + recentPrivateChats[recIdx].unreadCnt = sender ? 0 : unreadCnt + 1; + } + await ChatInfoModel.updateInfo({ roleId, recentPrivateChats}); +} + +/** + * @description 获取聊天信息 + */ +export async function roleChatInfos(roleId: string, roleName?: string) { + if(!roleName) { + let role = await RoleModel.findByRoleId(roleId, 'roleName'); + roleName = role.roleName; + } + let result = await ChatInfoModel.findInfo(roleId); + if (!result) { + result = await ChatInfoModel.createInfo({ roleId, roleName }); + } + return result; +} + +/** + * @description 获取最近聊天记录,需要组织最近聊天玩家的信息 + */ +export async function recentPrivateChatInfos(roleId: string, roleName: string) { + const { recentPrivateChats } = await roleChatInfos(roleId, roleName); + recentPrivateChats + .sort((a, b) => { + if(a.isTop || b.isTop) { + if(a.isTop && b.isTop) { + return b.setTopTime.getTime() - a.setTopTime.getTime() + } else { + return (b.isTop?1:0) - (a.isTop?1:0); + } + } else { + return b.lastChatTime.getTime() - a.lastChatTime.getTime() + } + }) + .splice(CHAT_SYSTEM.RECENT_PRIVATE_CHATS_CNT); + if (!recentPrivateChats || !recentPrivateChats.length) return []; + + const roleInfos = await RoleModel.findByRoleIds(recentPrivateChats.map(chat => { return chat.targetRoleId })); + const chatInfos = recentPrivateChats.map( chat => { + for (let { roleId: targetRoleId, quitTime, loginTime, roleName: targetRoleName, title, guildName, head, frame, spine, lv } of roleInfos) { + if (targetRoleId === chat.targetRoleId) { + return { ...chat, quitTime, targetRoleName, title, guildName, head, frame, spine, lv, isOnline: quitTime === loginTime }; + } + } + }); + return chatInfos; +} + +/** + * @description 查看消息时更新查看时间和未读消息数 + */ +export async function updatePrivateMsgReadInfo(roleId: string, targetRoleId: string) { + const time = new Date(); + const chatInfo = await ChatInfoModel.updateReadInfo(roleId, targetRoleId, time); + if (!chatInfo || !chatInfo.recentPrivateChats) { + return null; + } + const chatRec = chatInfo.recentPrivateChats.find(rec => { return rec.targetRoleId === targetRoleId }); + return chatRec; +} + +/** + * @description 查看消息时更新查看时间和未读消息数 + */ +export async function updatePrivateMsgIsTop(roleId: string, targetRoleId: string, isTop: boolean) { + const time = new Date(); + const chatInfo = await ChatInfoModel.setTop(roleId, targetRoleId, isTop, time); + if (!chatInfo || !chatInfo.recentPrivateChats) { + return null; + } + const chatRec = chatInfo.recentPrivateChats.find(rec => { return rec.targetRoleId === targetRoleId }); + return chatRec; +} + +/** + * @description 查看消息时更新查看时间和未读消息数 + */ +export async function delPrivateMsg(roleId: string, targetRoleId: string) { + const chatInfo = await ChatInfoModel.delMsg(roleId, targetRoleId); + if (!chatInfo || !chatInfo.recentPrivateChats) { + return null; + } + return { targetRoleId }; +} + + +/** + * @description 发送组队一键邀请消息 + * @param {string} teamCode 队伍唯一标识 + */ +export async function pushTeamInviteMsg(roleId: string, roleName: string, guildCode: string, teamCode: string, blueprtId: number, blueprtLv: number, ceLimit: number) { + let msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.TEAM_INVITE, JSON.stringify({ roleName, teamCode, blueprtId }), null, null); + await pushGroupMsgToRoom(msgData); + return { msgData }; +} + +/** + * @description 发送组队私人邀请消息 + * @param {string} teamCode 队伍唯一标识 + */ + export async function pushFriendTeamInviteMsg(roleId: string, roleName: string, teamCode: string, blueprtId: number, targetRoleId: string, relation: number) { + const msgData = await createPrivateMsg(roleId, roleName, MSG_TYPE.RICH_TEXT, MSG_SOURCE.TEAM_INVITE, JSON.stringify({ roleName, teamCode, blueprtId}), targetRoleId, null, relation); + await pushMsgToRole(msgData); + return msgData; +} + + +export async function createAccuseData(roleId: string, roleName: string, targetRoleId: string, targetRoleName: string, targetMsgCode: string, reason: number) { + const data: AccueseParam = { + roleId, roleName, targetRoleId, targetRoleName, targetMsgCode, reason + }; + const result = await AccuseRecModel.createRec(data); + return result; +} + +/* +const client = new FCClient('1475752363809339', { + accessKeyID: 'LTAI5tFTwE7vwH5HGL7eV8xr', + accessKeySecret: 'HZznAZfOrmXttBMevhA55jQX3OGw9j', + region: 'cn-zhangjiakou', +}); + +export async function checkFilterWords(word: string) { + const resp = await client.post('/proxy/bantuUtils/filterWords/check',{ + word, + salt: "bantu1filter2word3test" + }, {}); + let hasBlock = true; + try { + let data = JSON.parse(resp.data); + hasBlock = data.status != 0; + } catch (e) { + console.log(e); + } + + return hasBlock; +} +*/ + +export function isApiClose() { + return pinus.app.get('apiIsClose'); +} + +export async function checkAndSetApiIsClose() { + let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); + setApiIsClose(region?.isCloseApi??false); +} + +export function setApiIsClose(isClose: boolean) { + pinus.app.set('apiIsClose', isClose); +} + +export async function setApiIsCloseToRemote(isClose: boolean) { + await pinus.app.rpc.activity.activityRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.battle.battleRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.chat.chatRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.connector.connectorRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.guild.guildRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.order.orderRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.role.roleRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.systimer.systimerRemote.setApiIsClose.broadcast(isClose); + await pinus.app.rpc.comBattle.comBattleRemote.setApiIsClose.broadcast(isClose); +} diff --git a/game-server/app/services/checkParam.ts b/game-server/app/services/checkParam.ts index 5d1641917..a9bfb89d1 100644 --- a/game-server/app/services/checkParam.ts +++ b/game-server/app/services/checkParam.ts @@ -1,2694 +1,2694 @@ -import { isArray, isBoolean, isNumber, isString } from "underscore"; -import { BLOCK_OPEATE, DEBUG_MAGIC_WORD, GM_MAIL_TYPE, GUILD_AUTH, GUILD_STRUCTURE, GVG_RESOURCE_TYPE, GVG_SEED_TYPE, LEAGUE_JOB, LINEUP_NUM, MSG_TYPE } from "../consts"; -import { gvgEndParamInter, pvpEndParamInter } from "../pubUtils/interface"; -import { isDevelopEnv } from "./utilService"; - -export function checkRouteParam(route: string, msg: any) { - switch (route) { - case 'activity.activityHandler.getAllOpenActivity': - case 'activity.gachaHandler.getGachaList': - case 'activity.gachaHandler.getVisitedHero': - case 'activity.gachaHandler.getGuideGachaData': - case 'activity.selfServiceShopHandler.getSelfServiceShopActivity': - case "comBattle.comBattleHandler.cancelSearch": - case "comBattle.comBattleHandler.getTeamRec": - case "comBattle.comBattleHandler.getAssistCnt": - case "comBattle.comBattleHandler.getComBtlCnt": - case "comBattle.comBattleHandler.getRecentTeammates": - case "comBattle.comBattleHandler.getTeamInvitation": - case "battle.dailyBattleHandler.getData": - case "battle.dungeonBattleHandler.getData": - case "battle.eventBattleHandler.getEvents": - case "battle.expeditionBattleHandler.getStatus": - case "battle.expeditionBattleHandler.resetStatus": - case "battle.normalBattleHandler.getMainStarBox": - case "battle.pvpHandler.getData": - case "battle.pvpHandler.refreshOppPlayer": - case "battle.pvpHandler.getRank": - case "battle.pvpHandler.getRec": - case "battle.ladderHandler.getData": - case "battle.ladderHandler.refreshOppPlayers": - case "battle.ladderHandler.getRec": - - case "battle.towerBattleHandler.getStatus": - case "battle.towerBattleHandler.checkHangUpRewards": - case "battle.towerBattleHandler.recHangUpRewards": - case "battle.towerBattleHandler.getTasks": - case "battle.towerBattleHandler.refreshTasks": - case "chat.chatHandler.getRecentPrivateChats": - case "chat.chatHandler.getGroupMessages": - case "connector.entryHandler.getData": - case "connector.entryHandler.refresh": - case "gate.gateHandler.queryEntry": - case "guild.auctionHandler.checkDividend": - case "guild.auctionHandler.myWatching": - case "guild.cityActivityHandler.getCityActivity": - case "guild.cityActivityHandler.resetChallengeTime": - case "guild.donateHandler.getDonation": - case "guild.gateActivityHandler.getGateActivity": - case "guild.guildBossHandler.getBossInstance": - case "guild.guildBossHandler.openBossInstance": - case "guild.guildBossHandler.battleBoss": - case "guild.guildHandler.getMyGuildInfo": - case "guild.guildHandler.getInviteMemberList": - case "guild.guildHandler.getActiveRank": - case "guild.guildRefineHandler.getRefine": - case "guild.guildTrainHandler.getTrainInstance": - case "guild.guildTrainHandler.getTrainReports": - case "guild.guildTrainHandler.getTrainBoxs": - case "guild.raceActivityHandler.getRaceActivity": - case "guild.raceActivityHandler.join": - case "guild.raceActivityHandler.getRace": - case "guild.wishPoolHandler.getWishPool": - case "guild.wishPoolHandler.getReports": - case "role.friendHandler.getRecommend": - case "role.friendHandler.getApplyList": - case "role.friendHandler.getFriendList": - case "role.friendHandler.getBlackList": - case "role.itemHandler.getAp": - case "role.mailHandler.getMails": - case "role.rankHandler.getGeneralRank": - case "role.rankHandler.getRankReward": - case "role.roleHandler.roleTitleLevelUp": - case "role.roleHandler.getSchoolList": - case "role.taskHandler.getPvpTaskList": - case "role.taskHandler.getTaskList": - case "role.taskHandler.receiveActiveReward": - case "role.artifactHandler.composeAll": - case "guild.gvgHandler.getData": - case "guild.gvgHandler.getMap": - case "guild.gvgHandler.getRec": - case "guild.gvgHandler.getContribute": - case "guild.gvgHandler.getTech": - case "guild.gvgManageHandler.getApplies": - case "guild.gvgManageHandler.getLeagueInvitations": - case "guild.gvgFightHandler.getLeagueRank": - case "guild.gvgFightHandler.getLeagueDetailRank": - case "guild.gvgFightHandler.receiveBox": - { - break; - } - case 'activity.activityMonopolyHandler.getMonopolyActivity': - case 'activity.dailyChallengeHandler.getDailyChallengesActivity': - case 'activity.dailyCoinHandler.getDailyCoinActivity': - case 'activity.dailyGiftsHandler.getDailyGiftsActivity': - case 'activity.dailyGKHandler.getDailyGKActivity': - case 'activity.dailyMealHandler.getDailyMealActivity': - case 'activity.dailyRMBGiftsHandler.getDailyRMBGiftsActivity': - case 'activity.firstGiftHandler.getFirstGiftActivity': - case 'activity.growthFundHandler.getGrowthFundActivity': - case 'activity.growthHandler.getGrowthActivity': - case 'activity.guildPayHandler.getGuildPayData': - case 'activity.limitPackageHandler.getNewPlayerLimitPackageActivity': - case 'activity.luckyTurntableHandler.getTurntableData': - case 'activity.luckyHandler.getTurntableData': - case 'activity.monthlyTicketHandler.getMonthlyTicketActivity': - case 'activity.newHeroGachaHandler.getNewHeroGachaActivity': - case 'activity.newHeroGiftsHandler.getNewHeroGiftsActivity': - case 'activity.newHeroGKHandler.getNewHeroGKActivity': - case 'activity.newHeroGachaHandler.getData': - case 'activity.popUpShopHandler.getPopUpShopActivity': - case 'activity.rechargeMoneyHandler.getRechargeMoneyActivity': - case 'activity.refreshShopHandler.getRefreshShopActivity': - case 'activity.refreshTaskHandler.getRefreshTaskActivity': - case 'activity.sevenDaysHandler.getSevenDaysActivity': - case 'activity.signInHandler.getSignInActivity': - case 'activity.taskPassHandler.getTaskPassData': - case 'activity.thirtyDaysHandler.getThirtyDaysActivity': - case 'activity.timeLimitRankHandler.getTimeLimitRankData': - case 'activity.treasureHuntHandler.getTreasureHuntActivity': - case 'activity.vipRechargeMoneyHandler.getVipRechargeMoneyActivity': - case 'activity.yuanbaoShopHandler.getShopActivity': - case 'activity.groupShopHandler.getGroupShopPage': - case 'activity.groupShopHandler.leaveGroupShopPage': - case 'activity.forgeHandler.getForgeActivity': - case 'activity.miniGameHandler.getMiniGameActivity': - case 'activity.weeklyFundHandler.getData': - case 'activity.monthlyFundHandler.getData': - case 'activity.bindPhoneHandler.bind': - case 'activity.bindPhoneHandler.receiveReward': - case 'activity.bindPhoneHandler.receiveGiftCode': - case 'activity.bindPhoneHandler.skipOutSide': - case 'activity.dragonBoatHandler.getData': - case 'activity.qixiHandler.getData': - case 'activity.midAutumnHandler.getData': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.activityMonopolyHandler.move': - { - if (!checkNaturalNumbers(msg.activityId, msg.step)) return false; - if (msg.step < 0 || msg.step > 7) return false; - break; - } - case 'activity.activityMonopolyHandler.bank': - { - if (!checkNaturalNumbers(msg.activityId, msg.addCount)) return false; - break; - } - case 'activity.activityMonopolyHandler.getRefreshShopActivity': - { - if (!checkNaturalNumbers(msg.activityId, msg.shopActivityId)) return false; - break; - } - case 'activity.activityMonopolyHandler.buyGood': - { - let { monopolyActivityId, shopActivityId, roundIndex, id, pageIndex } = msg; - if (!checkNaturalNumbers(monopolyActivityId, shopActivityId, roundIndex, id, pageIndex)) return false; - break; - } - case 'activity.dailyChallengeHandler.getDailyChallengeReward': - case 'activity.sevenDaysHandler.getDailyChallengeReward': - { - let { activityId, dayIndex, cellIndex, type } = msg; - if (!checkNaturalNumbers(activityId, dayIndex, cellIndex, type)) return false; - break; - } - case 'activity.dailyCoinHandler.exchangeCoin': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.dailyCoinHandler.receiveExtraReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; - break; - } - case 'activity.dailyGiftsHandler.buyDailyGiftsCell': - case 'activity.sevenDaysHandler.buyDailyGiftsCell': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.cellIndex)) return false; - break; - } - case 'activity.dailyGKHandler.getGK': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; - break; - } - case 'activity.dailyMealHandler.getDailyMealReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.type)) return false; - break; - } - case 'activity.dailyRMBGiftsHandler.getDailyRMBGiftsReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - break; - } - case 'activity.firstGiftHandler.getFirstGiftReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.pageIndex)) return false; - break; - } - case 'activity.gachaHandler.pull': - { - if (!checkNaturalNumbers(msg.activityId, msg.gachaId, msg.count)) return false; - break; - } - case 'activity.gachaHandler.setHope': - { - if (!checkNaturalNumbers(msg.gachaId)) return false; - if (!checkNaturalArray(msg.hope)) return false; - for (let { id, hid } of msg.hope) { - if (!checkNaturalNumbers(id, hid)) return false; - } - break; - } - case 'activity.gachaHandler.drawTurnTable': - { - if (!checkNaturalNumbers(msg.gachaId)) return false; - break; - } - case 'activity.gachaHandler.setPickHero': - { - if (!checkNaturalNumbers(msg.gachaId, msg.activityId, msg.pickHero)) return false; - break; - } - case 'activity.gachaHandler.visitHero': - { - if (!checkNaturalNumbers(msg.hid)) return false - break; - } - case 'activity.gachaHandler.guidePull': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.gachaHandler.saveToCandidates': - case 'activity.gachaHandler.decide': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - break; - } - case 'activity.growthFundHandler.getGrowthFundCellReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.cellIndex)) return false; - break; - } - case 'activity.growthHandler.getGrowthCellReward': - case 'activity.sevenDaysHandler.getGrowthCellReward': - { - let { activityId, dayIndex, cellIndex, type } = msg; - if (!checkNaturalNumbers(activityId, dayIndex, cellIndex, type)) return false; - break; - } - case 'activity.growthHandler.getGrowthDayReward': - case 'activity.sevenDaysHandler.getGrowthDayReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - break; - } - case 'activity.guildPayHandler.receiveItems': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; - break; - } - case 'activity.limitPackageHandler.getLimitPackageActivity': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.limitPackageHandler.buyGood': - { - if (!checkNaturalNumbers(msg.activityId, msg.roundIndex, msg.id)) return false; - break; - } - case 'activity.luckyTurntableHandler.pull': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.luckyTurntableHandler.receiveBox': - { - if (!checkNaturalNumbers(msg.activityId, msg.boxCount)) return false; - break; - } - case 'activity.luckyHandler.pull': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.luckyHandler.receiveBox': - { - if (!checkNaturalNumbers(msg.activityId, msg.boxCount)) return false; - break; - } - case 'activity.monthlyTicketHandler.getMonthlyTicketReward': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.newHeroGachaHandler.selectedHero': - { - if (!checkNaturalNumbers(msg.activityId, msg.hid)) return false; - break; - } - case 'activity.newHeroGachaHandler.pull': - { - if (!checkNaturalNumbers(msg.activityId, msg.hid, msg.count)) return false; - break; - } - case 'activity.newHeroGiftsHandler.exchangePoint': - { - if (!checkNaturalNumbers(msg.activityId, msg.index)) return false; - break; - } - case 'activity.newHeroGKHandler.getGK': - { - if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.index)) return false; - break; - } - case 'activity.popUpShopHandler.checkPopUpCondition': - { - if (!checkNaturalNumbers(msg.conditionType)) return false; - break; - } - case 'activity.popUpShopHandler.buyGift': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - if (!checkNaturalStrings(msg.code)) return false; - break; - } - case 'activity.rechargeMoneyHandler.pull': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.refreshShopHandler.buyGood': - { - let { activityId, roundIndex, id, pageIndex, count } = msg; - if (!checkNaturalNumbers(activityId, roundIndex, id, pageIndex, count)) return false; - break; - } - case 'activity.refreshTaskHandler.getReward': - { - let { activityId, roundIndex, pageIndex, id, type } = msg; - if (!checkNaturalNumbers(activityId, roundIndex, id, pageIndex, type)) return false; - break; - } - case 'activity.refreshTaskHandler.exchangePoint': - { - if (!checkNaturalNumbers(msg.activityId, msg.roundIndex)) return false; - break; - } - case 'activity.selfServiceShopHandler.buyGift': - { - if (!checkNaturalNumbers(msg.activityId, msg.roundIndex, msg.index)) return false; - break; - } - case 'activity.selfServiceShopHandler.saveGood': - { - let { data = [] } = msg; - for (let { activityId, roundIndex, index, cellIndex, rewardIndex } of data) { - if (!checkNaturalNumbers(activityId, roundIndex, index, cellIndex, rewardIndex)) return false; - } - break; - } - case 'activity.selfServiceShopHandler.buyRecources': - { - if (!checkNaturalNumbers(msg.activityId, msg.roundIndex)) return false; - break; - } - case 'activity.selfServiceShopHandler.getWarId': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.signInHandler.getSignInReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; - break; - } - case 'activity.taskPassHandler.receiveItems': - { - if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.lv)) return false; - break; - } - case 'activity.taskPassHandler.speedUp': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.thirtyDaysHandler.getThirtyDaysCellReward': - { - let { activityId, pageIndex, cellIndex, tab } = msg; - if (!checkNaturalNumbers(activityId, pageIndex, cellIndex, tab)) return false; - break; - } - case 'activity.thirtyDaysHandler.getThirtyDaysPointReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; - break; - } - case 'activity.timeLimitRankHandler.getRank': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.treasureHuntHandler.getFirstPageReward': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.treasureHuntHandler.buyGoods': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex, msg.count)) return false; - break; - } - case 'activity.treasureHuntHandler.getTaskReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; - break; - } - case 'activity.treasureHuntHandler.challenge': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.treasureHuntHandler.buyTreasureShopGoods': - { - if (!checkNaturalNumbers(msg.activityId, msg.cellIndex, msg.count)) return false; - break; - } - case 'activity.vipRechargeMoneyHandler.getVipRechargeMoneyReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - break; - } - case 'activity.vipRechargeMoneyHandler.getOrderList': - { - if (!checkNaturalNumbers(msg.begin, msg.count)) return false; - if (msg.count < 0 && msg.count > 100) return false - break; - } - case 'activity.groupShopHandler.buy': - { - let { activityId, price, itemId, buyCnt } = msg; - if (!checkNaturalNumbers(activityId, price, itemId, buyCnt)) return false; - break; - } - case 'activity.forgeHandler.build': - { - let { activityId, id, material } = msg; - if (!checkNaturalNumbers(activityId, id)) return false; - if (!checkNaturalArray(material)) return false; - for (let { id, count } of material) { - if (!checkNaturalNumbers(id, count)) return false - } - break; - } - case 'activity.forgeHandler.buyCnt': - { - let { activityId, id, count } = msg; - if (!checkNaturalNumbers(activityId, id, count)) return false; - break; - } - case 'activity.miniGameHandler.gameStart': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.miniGameHandler.gameEnd': - { - let { activityId, gameCode, score } = msg; - if (!checkNaturalNumbers(activityId, score)) return false; - if (!checkNaturalStrings(gameCode)) return false; - break; - } - case 'activity.miniGameHandler.buyCnt': - { - let { activityId, count } = msg; - if (!checkNaturalNumbers(activityId, count)) return false; - break; - } - case 'activity.miniGameHandler.receiveBox': - { - let { activityId, boxId } = msg; - if (!checkNaturalNumbers(activityId, boxId)) return false; - break; - } - case 'activity.miniGameHandler.getRanks': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.weeklyFundHandler.sign': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; - break; - } - case 'activity.monthlyFundHandler.sign': - { - if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.dayIndex)) return false; - break; - } - case 'activity.rebateHandler.receiveReward': - { - if (!checkNaturalNumbers(msg.activityId, msg.day)) return false; - break; - } - case "battle.barrageHandler.getBarrageList": - { - if (!checkNaturalStrings(msg.rid)) return false; - break; - } - case "battle.barrageHandler.sendBarrage": - { - let { warId, rid, index, content } = msg; - if (!checkNaturalNumbers(warId)) return false; - if (!checkNaturalStrings(rid, index, content)) return false; - break; - } - case "comBattle.comBattleHandler.createTeam": - { - let { blueprtId, pub, ceLimit } = msg; - if (!checkNaturalNumbers(blueprtId, ceLimit)) return false; - if (!checkBoolean(pub)) return false; - break; - } - case "comBattle.comBattleHandler.searchTeam": - { - let { lv, magicWord } = msg; - if (!checkNumberArray(lv)) return false; - if (!!magicWord && magicWord != DEBUG_MAGIC_WORD) return false; - break; - } - case "comBattle.comBattleHandler.joinTeam": - { - if (!checkNaturalStrings(msg.teamCode)) return false; - if (!checkBoolean(msg.isFrd)) return false; - break; - } - case "comBattle.comBattleHandler.setFrdAssistance": - { - if (!checkNaturalStrings(msg.teamCode)) return false; - if (!checkBoolean(msg.isFrd)) return false; - break; - } - case "comBattle.comBattleHandler.setupHeroes": - { - let { teamCode, heroes, battleCode } = msg; - if (!checkNaturalStrings(teamCode, battleCode)) return false; - if (!checkNumberArray(heroes)) return false; - break; - } - case "comBattle.comBattleHandler.rmTeammate": - { - if (!checkNaturalStrings(msg.teamCode, msg.roleIdToRm)) return false; - break; - } - case "comBattle.comBattleHandler.dismiss": - case "comBattle.comBattleHandler.startBattle": - case "comBattle.comBattleHandler.autoInvite": - case "comBattle.comBattleHandler.comBattleEnd": - case "comBattle.comBattleHandler.getComBtlStatus": - { - if (!checkNaturalStrings(msg.teamCode)) return false; - break; - } - case "comBattle.comBattleHandler.action": - { - let { teamCode, bossHurts, killed, curRnd, timegap = 0, roundTime = 0 } = msg; - if (!checkNaturalStrings(teamCode)) return false; - if (!checkNumberArray(killed)) return false; - if (!checkNaturalNumbers(curRnd, timegap, roundTime)) return false; - if (!checkArrayCanEmpty(bossHurts)) return false; - for (let { hid, dataId, hurtHp } of bossHurts) { - if (hid && !checkNaturalNumbers(hid)) return false; - if (!checkNaturalNumbers(dataId)) return false; - if (!isNumber(hurtHp)) return false - } - break; - } - case "comBattle.comBattleHandler.getBlueprtCount": - { - if (!checkNumberArray(msg.ids)) return false; - break; - } - case "comBattle.comBattleHandler.sendTeamMsg": - { - let { teamCode, type, content, targetRoleId, targetMsgCode } = msg; - if (!checkNaturalStrings(teamCode, content)) return false; - if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; - if (!checkNaturalNumbers(type)) return false; - break; - } - case "comBattle.comBattleHandler.inviteTeammate": - { - if (!checkNaturalStrings(msg.teamCode, msg.targetRoleId)) return false; - break; - } - case "battle.dailyBattleHandler.buyNum": - { - if (!checkNaturalNumbers(msg.type, msg.count)) return false; - break; - } - case "battle.dungeonBattleHandler.buyNum": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "battle.dungeonBattleHandler.getFirstInfo": - { - if (!checkNaturalNumbers(msg.movePoint)) return false; - break; - } - case "battle.eventBattleHandler.checkAnswer": - { - let { eventId, eventCode, questionId, answer } = msg; - if (!checkNaturalNumbers(eventId, questionId, answer)) return false; - if (!checkNaturalStrings(eventCode)) return false; - break; - } - case "battle.eventBattleHandler.receiveEventReward": - { - if (!checkNaturalNumbers(msg.eventId)) return false; - if (!checkNaturalStrings(msg.eventCode)) return false; - break; - } - case "battle.expeditionBattleHandler.getEnemies": - { - if (!checkNaturalNumbers(msg.expeditionId)) return false; - if (!checkNaturalStrings(msg.expeditionCode)) return false; - break; - } - case "battle.expeditionBattleHandler.checkBattle": - { - let { expeditionCode, expeditionId, battleId, heroes } = msg; - if (!checkNaturalStrings(expeditionCode)) return false; - if (!checkNaturalNumbers(expeditionId, battleId)) return false; - if (!checkNumberArray(heroes)) return false - break; - } - case "battle.expeditionBattleHandler.battleEnd": - { - let { expeditionCode, expeditionId, battleCode, battleId, isSuccess, heroes, enemies, star, stars } = msg; - if (!checkNaturalStrings(expeditionCode, battleCode)) return false; - if (!checkNaturalNumbers(expeditionId, battleId)) return false; - if (!checkBoolean(isSuccess)) return false; - if (!checkExpeditionBattleHeroFormat(heroes, enemies)) return false; - if (!checkNumberArray(stars)) return false; - break; - } - case "battle.expeditionBattleHandler.pointReward": - { - if (!checkNaturalNumbers(msg.point)) return false; - break; - } - case "battle.expeditionBattleHandler.skipExpedition": - { - if (!checkNaturalStrings(msg.expeditionCode)) return false; - if (!checkNaturalNumbers(msg.expeditionId, msg.battleId)) return false; - break; - } - case "battle.normalBattleHandler.checkBattle": - { - let { battleId, heroes } = msg; - if (!checkNaturalNumbers(battleId)) return false; - if (!checkNumberArray(heroes)) return false - break; - } - case "battle.normalBattleHandler.getBattleList": - { - if (!checkNumberArray(msg.types)) return false; - break; - } - case "battle.normalBattleHandler.battleEnd": - { - let { battleCode, battleId, isSuccess, heroes, stars, activityId = 0, pageIndex = 0 } = msg; - if (!checkNaturalStrings(battleCode)) return false; - if (!checkNaturalNumbers(battleId, activityId, pageIndex)) return false; - if (!checkBoolean(isSuccess)) return false; - if (!checkNumberArray(heroes, stars)) return false; - break; - } - case "battle.normalBattleHandler.battleSweep": - { - if (!checkNaturalNumbers(msg.battleId, msg.count)) return false; - break; - } - case "battle.normalBattleHandler.saveScript": - { - if (!checkNaturalNumbers(msg.battleId, msg.type)) return false; - if (!checkNaturalStrings(msg.script)) return false; - break; - } - case "battle.normalBattleHandler.getScriptByBattle": - { - if (!checkNumberArray(msg.battleIds)) return false; - break; - } - case "battle.normalBattleHandler.getRegretCnt": - { - if (!checkNaturalNumbers(msg.warId)) return false; - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "battle.normalBattleHandler.incRegretCnt": - { - if (!checkNaturalNumbers(msg.warId, msg.count)) return false; - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "battle.normalBattleHandler.receiveChapterBox": - { - if (!checkNaturalNumbers(msg.chapter, msg.id, msg.warType)) return false; - break; - } - case "battle.normalBattleHandler.receiveWarReward": - { - if (!checkNaturalNumbers(msg.chapter, msg.warType)) return false; - break; - } - case "battle.normalBattleHandler.checkSkip": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "battle.pvpHandler.getOppPlayer": - case "battle.pvpHandler.getPlayerDetail": - { - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "battle.pvpHandler.pvpStart": - { - if (!checkNaturalNumbers(msg.warId)) return false; - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "battle.pvpHandler.pvpEnd": - { - let { battleCode, isSuccess, myHeroes, oppHeroes } = msg; - if (!checkNaturalStrings(battleCode)) return false; - if (!checkBoolean(isSuccess)) return false; - if (!checkPvpEndHeroFormat(myHeroes, oppHeroes)) return false - break; - } - case "battle.pvpHandler.buyAttackCnt": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "battle.pvpHandler.saveAttack": - case "battle.pvpHandler.saveAttackSub": - { - let { heroes } = msg; - if (!checkNaturalArray(heroes)) return false; - if (heroes.length > LINEUP_NUM) return false; - for (let { actorId, order } of heroes) { - if (!checkNaturalNumbers(actorId)) return false; - if (!checkNumberIfExist(order)) return false; - } - break; - } - case "battle.pvpHandler.saveDefense": - { - let { heroes, warId, buff, combo } = msg; - if (!checkNaturalArray(heroes)) return false; - if (!checkNaturalNumbers(warId, buff)) return false; - if (heroes.length > LINEUP_NUM) return false; - for (let { actorId, dataId, order, ai } of heroes) { - if (!checkNaturalNumbers(actorId, dataId, order, ai)) return false; - } - if (!checkCombo(combo)) return false - break; - } - case "battle.pvpHandler.receiveBox": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "battle.pvpHandler.buyChallengeCnt": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "battle.pvpHandler.sweep": - { - if (!checkNaturalNumbers(msg.warId)) return false; - if (!checkNaturalStrings(msg.oppRoleId)) return false; - break; - } - case "battle.ladderHandler.getOppLineup": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.rank)) return false; - break; - } - case "battle.ladderHandler.chooseOpp": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.rank, msg.myRank)) return false; - break; - } - case "battle.ladderHandler.chooseOpp": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.rank, msg.myRank)) return false; - break; - } - case "battle.ladderHandler.giveupCheck": - case "battle.ladderHandler.getOppData": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "battle.ladderHandler.checkBattle": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - if (!checkNaturalNumbers(msg.battleId)) return false; - if (!checkArrayCanEmpty(msg.heroes)) return false; - for (let { actorId, order } of msg.heroes) { - if (!checkNaturalNumbers(actorId, order)) return false; - } - break; - } - case "battle.ladderHandler.battleEnd": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case "battle.ladderHandler.battleSweep": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.rank, msg.count)) return false; - break; - } - case "battle.ladderHandler.saveDefense": - { - if (!checkNaturalNumbers(msg.warId)) return false; - if (!checkArrayCanEmpty(msg.heroes)) return false; - for (let { actorId, dataId, order } of msg.heroes) { - if (!checkNaturalNumbers(actorId, dataId, order)) return false; - } - if (!checkCombo(msg.combo)) return false - break; - } - case "battle.ladderHandler.buyCnt": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "battle.towerBattleHandler.resetLv": - { - if (!checkNaturalNumbers(msg.towerLv)) return false; - break; - } - case "battle.towerBattleHandler.skipTower": - { - if (!checkNaturalNumbers(msg.toLv)) return false; - break; - } - case "battle.towerBattleHandler.hangUpSpeedUp": - { - if (!checkNaturalNumbers(msg.speedUpCnt)) return false; - break; - } - case "battle.towerBattleHandler.sendTaskHero": - { - let { batchCode, tasks } = msg; - if (!checkStringIfExist(batchCode)) return false; - if (!checkNaturalArray(tasks)) return false; - for (let { taskCode, heroes } of tasks) { - if (!checkNaturalStrings(taskCode)) return false; - if (!checkNumberArray(heroes)) return false; - } - break; - } - case "battle.towerBattleHandler.settleTask": - { - if (!checkStringIfExist(msg.batchCode, msg.taskCode)) return false; - break; - } - case "battle.towerBattleHandler.receiveBox": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - - case "battle.rougeHandler.getData": - break; - case "battle.rougeHandler.getGame": - break; - - case "battle.rougeHandler.getInitCharaCard": - { - let { type, grade } = msg - if (!checkNaturalNumbers(type, grade)) return false; - break; - } - case "battle.rougeHandler.refreshInitCharaCard": - { - let { gameCode } = msg - if (!checkNaturalStrings(gameCode)) return false; - break; - } - case "battle.rougeHandler.startGame": - { - let { gameCode, authorType } = msg; - if (!checkNaturalStrings(gameCode)) return false; - if (!checkNaturalNumbers(authorType)) return false; - break; - } - - case "battle.rougeHandler.gameEnd": - { - let { gameCode } = msg; - if (!checkNaturalStrings(gameCode)) return false; - break; - } - - case "battle.rougeHandler.chooseNode": - { - let { gameCode, layer, detailCode } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkNaturalNumbers(layer)) return false; - break; - } - - case "battle.rougeHandler.checkBattle": - { - let { gameCode, detailCode, warId, charaCodes } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkNaturalNumbers(warId)) return false; - if (!checkIsDuplicateStrings(charaCodes)) return false; - break; - } - - case "battle.rougeHandler.battleEnd": - { - let { gameCode, detailCode, battleCode, warId, status, round, rougeDamage } = msg; - if (!checkNaturalStrings(gameCode, detailCode, battleCode)) return false; - if (!checkNaturalNumbers(warId, round, status)) return false; - // if (!checkBooleanIfExist(isAp, isRound)) return false; - if (!isArray(rougeDamage) || rougeDamage.length == 0) return false; - let charaCodes: string[] = []; - for (let { charaCode } of rougeDamage) { - if (!charaCode) return false; - charaCodes.push(charaCode); - } - if (!checkIsDuplicateStrings(charaCodes)) return false; - break; - } - - case "battle.rougeHandler.chooseReward": - { - let { gameCode, detailCode, groupIndex, optionIndexs } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkNaturalNumbers(groupIndex)) return false; - if (!checkIsDuplicateNumbers(optionIndexs)) return false; - break; - } - case "battle.rougeHandler.reRandomReward": - { - let { gameCode, detailCode, rewardType } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkNaturalNumbers(rewardType)) return false; - break; - } - case "battle.rougeHandler.shopBuy": - { - let { gameCode, detailCode, optionIndex } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkNaturalNumbers(optionIndex)) return false; - break; - } - - case "battle.rougeHandler.chooseOption": - { - let { gameCode, detailCode, eventOptions } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - if (!checkIsDuplicateNumbers(eventOptions)) return false; - break; - } - - case "battle.rougeHandler.recovery": - { - let { gameCode, detailCode } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - break; - } - - case "battle.rougeHandler.trainCard": - { - let { gameCode, detailCode, cardCode } = msg; - if (!checkNaturalStrings(gameCode, detailCode, cardCode)) return false; - break; - } - case "battle.rougeHandler.nodeEnd": - { - let { gameCode, detailCode, } = msg; - if (!checkNaturalStrings(gameCode, detailCode)) return false; - break; - } - - case "battle.rougeHandler.putOnOrOffCard": - { - let { gameCode, charaCode, cards } = msg; - if (!checkNaturalStrings(gameCode, charaCode)) return false; - let cardCodes: string[] = [], indexs: number[] = []; - for (let { index, cardCode } of cards) { - indexs.push(index); - if (cardCode) cardCodes.push(cardCode); - } - if (!checkIsDuplicateNumbers(indexs)) return false; - if (!checkIsDuplicateStrings(cardCodes)) return false; - - break; - } - - case "battle.rougeHandler.exchangeChara": - { - let { gameCode, oldCharaCode, newCharaCode } = msg; - if (!checkNaturalStrings(gameCode, oldCharaCode, newCharaCode)) return false; - break; - } - case "battle.rougeHandler.challengeRandom": - { - let { detailCode } = msg; - if (!checkNaturalStrings(detailCode)) return false; - break; - } - case "battle.rougeHandler.unlockTech": - { - if (!checkNaturalNumbers(msg.techId)) return false; - break; - } - - case "battle.rougeHandler.putOnCircle": - { - if (!checkNaturalNumbers(msg.circleId, msg.hid)) return false; - break; - } - case "battle.rougeHandler.chooseSkillCard": - { - if (!checkNaturalStrings(msg.gameCode, msg.charaCode)) return false; - if (!checkNaturalNumbers(msg.skillType, msg.id)) return false; - break; - } - case "battle.rougeHandler.receiveCollectionReward": - { - if (!checkNaturalNumbers(msg.type, msg.id)) return false; - break; - } - case "battle.rougeHandler.receiveScore": - { - if (!checkNaturalNumbers(msg.index)) return false; - break; - } - case "battle.friendBattleHandler.getFriendOpp": - { - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "chat.chatHandler.sendGroupMessage": - { - let { channel, type, content, targetRoleId, targetMsgCode } = msg; - if (!checkNaturalNumbers(type) || !checkIsInEnum(MSG_TYPE, type)) return false; - if (!checkNaturalStrings(channel)) return false; - if (type == MSG_TYPE.IMG) { - if (!checkNaturalNumbers(content)) return false; - } else { - if (!checkNaturalStrings(content)) return false; - } - if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; - break; - } - case "chat.chatHandler.sendPrivateMessage": - { - let { type, content, targetRoleId, targetMsgCode } = msg; - if (!checkNaturalNumbers(type) || !checkIsInEnum(MSG_TYPE, type)) return false; - if (type == MSG_TYPE.IMG) { - if (!checkNaturalNumbers(content)) return false; - } else { - if (!checkNaturalStrings(content)) return false; - } - if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; - break; - } - case "chat.chatHandler.getPrivateMessage": - { - let { targetRoleId, fromSeqId, count } = msg; - if (!checkNaturalStrings(targetRoleId)) return false; - if (!checkNumberIfExist(fromSeqId)) return false; - if (!checkNaturalNumbers(count)) return false; - if (count < 0 || count > 1000) return false; - break; - } - case "chat.chatHandler.readPrivateMessage": - case "chat.chatHandler.delPrivateMessage": - { - if (!checkNaturalStrings(msg.targetRoleId)) return false; - break; - } - case "chat.chatHandler.setPrivateMessageTop": - { - if (!checkNaturalStrings(msg.targetRoleId)) return false; - if (!checkBoolean(msg.isTop)) return false; - break; - } - case "chat.chatHandler.accuse": - { - if (!checkStringIfExist(msg.targetRoleId, msg.targetMsgCode)) return false; - if (!checkNumberIfExist(msg.reason)) return false; - break; - } - case "connector.entryHanddler.enter": - { - if (!checkNaturalStrings(msg.token)) return false; - if (!checkNaturalNumbers(msg.serverId)) return false; - break; - } - case "connector.entryHandler.gmEnter": - { - if (!checkNaturalStrings(msg.token)) return false; - break; - } - case "gm.gmHandler.sendSingleMail": - case "gm.gmHandler.sendSingleMailTxt": - case "gm.gmHandler.sendServerMail": - case "gm.gmHandler.sendServerMailTxt": - { - if (!checkNaturalStrings(msg.id)) return false; - if (!checkBoolean(msg.isPass)) return false; - break; - } - case "gm.gmHandler.reloadResource": - { - break; - } - case "gm.gmHandler.updateActivity": - { - let { groupId, beginTime, endTime, type, data, timeType, days, delayDay, interval, name, hideDayByServer, effectDay } = msg; - if (!checkNumberIfExist(groupId, beginTime, endTime, type, timeType, days, delayDay, interval, hideDayByServer, effectDay)) return false - if (!checkStringIfExist(data, name)) return false; - break; - } - case "gm.gmHandler.switchActivity": - { - let { activityId, isEnable } = msg; - if (!checkNaturalNumbers(activityId)) return false; - if (!checkBoolean(isEnable)) return false; - break; - } - case "gm.gmHandler.deleteActivity": - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case "gm.gmHandler.updateActivityGroup": - { - let { groupId, groupName, serverIds, activityIds, groupType } = msg; - if (!checkNaturalNumbers(groupId, groupType)) return false; - if (!checkNaturalStrings(groupName)) return false; - if (!checkNumberArray(serverIds, activityIds)) return false; - break; - } - case "gm.gmHandler.saveSingleActivityToGroup": - { - let { groupId, index, activityId } = msg; - if (!checkNaturalNumbers(groupId, index, activityId)) return false; - break; - } - case "gm.gmHandler.setGuildActivityDebug": - { - let { aid, day, startActivity = 0, endActivity = 0, startGuildAuction = 0, endGuildAuction = 0, startWorldAuction = 0, endWorldAuction = 0, startNextDay = 0 } = msg; - if (!checkNaturalNumbers(aid, day, startActivity, endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction, startNextDay)) return false; - break; - } - case "gm.gmHandler.cancelGuildActivityDebug": - case "gm.gmHandler.taflus": - { - break; - } - case "gm.gmHandler.updateSurvey": - { - let { code, surveyId, beginTime, endTime, isEnable, surveyLink, surveyName, roleIndex, goods, mailContent } = msg; - if (!checkNaturalStrings(code, surveyId, surveyLink, surveyName, goods, mailContent)) return false; - if (!checkStringIfExist(surveyName)) return false - if (!checkNaturalNumbers(beginTime, endTime, roleIndex)) return false; - if (!checkBoolean(isEnable)) return false; - break; - } - case "gm.gmHandler.deleteSurvey": - { - if (!checkNaturalStrings(msg.code)) return false; - break; - } - case "gm.gmOrderHandler.getActivitiesCanBuy": - { - if (!checkNaturalNumbers(msg.serverId)) return false; - break; - } - case "gm.gmOrderHandler.applyOrder": - { - let { serverId, activityId, receiver } = msg; - if (!checkNaturalNumbers(serverId)) return false; - if (!checkNaturalArray(activityId)) return false; - if (!checkNaturalNumbers(activityId[1])) return false; - if (!checkNaturalStrings(activityId[2])) return false; - if (!checkNaturalArray(receiver)) return false; - for (let { env, serverId, roleId, roleName } of receiver) { - if (!checkNaturalStrings(env)) return false; - if (!checkNaturalNumbers(serverId)) return false; - if (!checkStringIfExist(roleId, roleName)) return false; - } - break; - } - case "gm.gmRoleHandler.addItems": - case "gm.gmRoleHandler.deleteHero": - case "gm.gmRoleHandler.dismissGuild": - case "gm.gmRoleHandler.handleBlock": - case "gm.gmRoleHandler.setGuildLeader": - case "gm.gmRoleHandler.setHero": - case "gm.gmRoleHandler.skipEpilogue": - case "gm.gmRoleHandler.updateGuild": - case "gm.gmServerHandler.cancelMarquee": - case "gm.gmServerHandler.createNewServer": - case "gm.gmServerHandler.saveRegionConf": - case "gm.gmServerHandler.sendMarquee": - case "gm.gmServerHandler.startMaintenance": - case "gm.gmServerHandler.startRegionMaintenance": - case "gm.gmServerHandler.stopMaintenance": - case "gm.gmServerHandler.stopRegionMaintenance": - { - break; - } - case "guild.auctionHandler.getAuction": - case "guild.auctionHandler.leaveAuction": - { - if (!!msg.magicWord && msg.magicWord != DEBUG_MAGIC_WORD) return false; - break; - } - case "guild.auctionHandler.offer": - { - const { code, max, auctionStage, magicWord } = msg; - if (!checkNaturalStrings(code)) return false; - if (!checkBoolean(max)) return false; - if (!checkNaturalNumbers(auctionStage)) return false; - if (!!magicWord && magicWord != DEBUG_MAGIC_WORD) return false; - break; - } - case "guild.auctionHandler.unWatchLot": - case "guild.auctionHandler.watchLot": - case "guild.auctionHandler.getDividend": - { - if (!checkNaturalStrings(msg.code)) return false; - break; - } - case "guild.auctionHandler.offerRecs": - case "guild.auctionHandler.guildLotRecs": - { - if (!checkNaturalNumbers(msg.count)) return false; - if (msg.count < 0 || msg.count > 1000) return false; - break; - } - case "guild.cityActivityHandler.getCityStatus": - case "guild.cityActivityHandler.declareCity": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - break; - } - case "guild.cityActivityHandler.checkBattle": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - if (!checkNumberArray(msg.heroes)) return false; - break; - } - case "guild.cityActivityHandler.hitGate": - { - let { cityId, code, damage, hid, round, timegap = 0, roundTime = 0 } = msg; - if (!checkNaturalNumbers(cityId, damage, hid, round, timegap, roundTime)) return false; - if (!checkNaturalStrings(code)) return false; - break; - } - case "guild.cityActivityHandler.battleEnd": - { - let { cityId, code, isSuccess } = msg; - if (!checkNaturalNumbers(cityId)) return false; - if (!checkNaturalStrings(code)) return false; - if (!checkBoolean(isSuccess)) return false; - break; - } - case "guild.donateHandler.donate": - case "guild.donateHandler.receiveBox": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "guild.gateActivityHandler.checkBattle": - { - if (!checkNumberArray(msg.heroes)) return false; - break; - } - case "guild.gateActivityHandler.action": - { - let { code, round, record } = msg; - if (!checkNaturalStrings(code)) return false; - if (!checkNaturalNumbers(round)) return false; - if (!checkArrayCanEmpty(record)) return false; - for (let { round, dataId } of record) { - if (!checkNaturalNumbers(round, dataId)) return false; - } - break; - } - case "guild.gateActivityHandler.battleEnd": - { - let { code, isSuccess } = msg; - if (!checkNaturalStrings(code)) return false; - if (!checkBoolean(isSuccess)) return false; - break; - } - case "guild.guildBossHandler.getBossInstanceByBattleCode": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "guild.guildBossHandler.action": - { - if (!checkNaturalStrings(msg.bossCode, msg.battleCode)) return false; - if (!checkNaturalNumbers(msg.damage)) return false; - break; - } - case "guild.guildBossHandler.battleBossEnd": - { - if (!checkNaturalStrings(msg.bossCode, msg.battleCode)) return false; - break; - } - case "guild.guildBossHandler.encourage": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "guild.guildHandler.createGuild": - { - let { name, icon, notice } = msg; - if (!checkNaturalStrings(name)) return false; - if (!checkNaturalNumbers(icon)) return false; - if (!checkStringIfExist(notice)) return false; - break; - } - case "guild.guildHandler.getGuildList": - { - let { page = 1, showPeopleMax, name } = msg; - if (!checkStringIfExist(name)) return false; - if (!checkNaturalNumbers(page)) return false; - if (!checkBoolean(showPeopleMax)) return false; - break; - } - case "guild.guildHandler.setGuildInfo": - { - let { code, name, notice, introduce, ceLimit, isAuto, icon } = msg; - if (!checkNaturalStrings(code)) return false; - if (!checkStringIfExist(name, notice, introduce)) return false; - if (!checkNumberIfExist(ceLimit, icon)) return false; - if (!checkBooleanIfExist(isAuto)) return false; - break; - } - case "guild.guildHandler.getGuildInfo": - case "guild.guildHandler.applyGuild": - case "guild.guildHandler.dismiss": - case "guild.guildHandler.quit": - case "guild.guildHandler.getRec": - { - if (!checkNaturalStrings(msg.code)) return false; - break; - } - case "guild.guildHandler.setAuth": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.auth)) return false; - if (!checkIsInEnum(GUILD_AUTH, msg.auth)) return false; - break; - } - case "guild.guildHandler.getApplyList": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkStringIfExist(msg.lastApplyCode)) return false; - break; - } - case "guild.guildHandler.receiveApply": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkStringArray(msg.applyCodeList)) return false; - if (!checkBoolean(msg.isReceived)) return false; - break; - } - case "guild.guildHandler.inviteMember": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkStringArray(msg.roleIds)) return false; - break; - } - case "guild.guildHandler.getInvitationList": - { - if (!checkStringIfExist(msg.lastApplyCode)) return false; - break; - } - case "guild.guildHandler.receiveInvitation": - { - if (!checkStringIfExist(msg.lastApplyCode)) return false; - if (!checkBoolean(msg.isReceived)) return false; - break; - } - case "guild.guildHandler.getGuildMember": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkStringIfExist(msg.sort)) return false; - break; - } - case "guild.guildHandler.kick": - case "guild.guildHandler.impeach": - { - if (!checkNaturalStrings(msg.code, msg.roleId)) return false; - break; - } - case "guild.guildHandler.upStructure": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkNaturalNumbers(msg.id)) return false; - if (!checkIsInEnum(GUILD_STRUCTURE, msg.id)) return false; - break; - } - case "guild.guildHandler.sendMail": - case "guild.guildHandler.recruit": - { - if (!checkNaturalStrings(msg.code, msg.info)) return false; - break; - } - case "guild.guildHandler.receiveActiveBox": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "guild.guildRefineHandler.refine": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "guild.guildRefineHandler.lightUpTree": - case "guild.guildRefineHandler.assistRefine": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "guild.guildTrainHandler.trainBattleStart": - { - let { hid, difficulty, trainId, battleId } = msg; - if (!checkNaturalNumbers(hid, difficulty, trainId, battleId)) return false; - break; - } - case "guild.guildTrainHandler.trainBattleEnd": - { - let { battleCode, isSuccess } = msg; - if (!checkNaturalStrings(battleCode)) return false; - if (!checkBoolean(isSuccess)) return false; - break; - } - case "guild.guildTrainHandler.trainBattleSweep": - { - let { hid, difficulty, trainId, battleId } = msg; - if (!checkNaturalNumbers(hid, difficulty, trainId, battleId)) return false; - break; - } - case "guild.guildTrainHandler.getTrainInstanceBox": - { - let { trainId, hid, index } = msg; - if (!checkNaturalNumbers(trainId, hid, index)) return false; - break; - } - case "guild.guildTrainHandler.getTrainLvUpRewards": - { - if (!checkNaturalNumbers(msg.trainId)) return false; - break; - } - case "guild.guildTrainHandler.purchaseTrainCount": - { - if (!checkNaturalNumbers(msg.count)) return false; - break; - } - case "guild.raceActivityHandler.useItem": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - if (!checkNaturalStrings(msg.toGuild)) return false; - break; - } - case "guild.raceActivityHandler.battleEnd": - { - if (!checkNaturalStrings(msg.code)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case "guild.wishPoolHandler.wishGoods": - { - if (!checkNaturalNumbers(msg.goodId, msg.type)) return false; - break; - } - case "guild.wishPoolHandler.donateGoods": - { - if (!checkNaturalStrings(msg.wishRoleId, msg.id)) return false; - break; - } - case "guild.wishPoolHandler.receiveGoods": - { - if (!checkNaturalStrings(msg.id)) return false; - break; - } - case "guild.gvgHandler.chooseJob": - { - if (msg.job != LEAGUE_JOB.FIGHTER && msg.job != LEAGUE_JOB.PRODUCER) return false; - break; - } - case "guild.gvgHandler.receiveBox": - { - if (!checkNaturalNumbers(msg.boxId)) return false; - break; - } - case "guild.gvgHandler.receiveLvReward": - { - if (!checkNaturalNumbers(msg.lv)) return false; - break; - } - case "guild.gvgHandler.receiveLvReward": - { - if (!checkNaturalNumbers(msg.receiveTask)) return false; - break; - } - case "guild.gvgHandler.unlockTech": - { - if (!checkNaturalNumbers(msg.techId)) return false; - break; - } - case "guild.gvgHandler.activate": - { - if (!checkNaturalNumbers(msg.techId, msg.battleFeats)) return false; - break; - } - case "guild.gvgManageHandler.createLeague": - { - let { name, icon, notice } = msg; - if (!checkNaturalStrings(name)) return false; - if (!checkStringIfExist(notice)) return false; - if (!checkNaturalNumbers(icon)) return false; - break; - } - case "guild.gvgManageHandler.getLeagues": - case "guild.gvgManageHandler.getInviteGuilds": - { - let { name, page } = msg; - if (!checkStringIfExist(name)) return false; - if (!checkNumberIfExist(page)) return false; - break; - } - case "guild.gvgManageHandler.getLeagueInfo": - case "guild.gvgManageHandler.getGuilds": - case "guild.gvgManageHandler.getMembers": - case "guild.gvgManageHandler.dismiss": - case "guild.gvgManageHandler.getCandidate": - { - if (!checkNaturalStrings(msg.leagueCode)) return false; - break; - } - case "guild.gvgManageHandler.applyLeague": - { - if (!checkStringArray(msg.leagueCodes)) return false; - break; - } - case "guild.gvgManageHandler.handleApply": - { - if (!checkNaturalStrings(msg.guildCode)) return false; - if (!checkBoolean(msg.isReceive)) return false; - break; - } - case "guild.gvgManageHandler.inviteGuild": - { - if (!checkStringArray(msg.guildCodes)) return false; - break; - } - case "guild.gvgManageHandler.handleInvitation": - { - if (!checkNaturalStrings(msg.leagueCode)) return false; - if (!checkBoolean(msg.isReceive)) return false; - break; - } - case "guild.gvgManageHandler.kick": - case "guild.gvgManageHandler.quit": - { - if (!checkNaturalStrings(msg.guildCode)) return false; - break; - } - case "guild.gvgManageHandler.abdicate": - { - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "guild.gvgManageHandler.setLeagueInfo": - { - if (!checkNaturalStrings(msg.leagueCode)) return false; - if (!checkStringIfExist(msg.name, msg.notice)) return false; - if (!checkNumberIfExist(msg.icon)) return false; - break; - } - case "guild.gvgManageHandler.sendMail": - case "guild.gvgManageHandler.recruit": - { - if (!checkNaturalStrings(msg.content)) return false; - break; - } - case "guild.gvgProduceHandler.exchangeItem": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "guild.gvgProduceHandler.getProduceList": - { - if (!checkIsInEnum(GVG_RESOURCE_TYPE, msg.type)) return false; - break; - } - case "guild.gvgProduceHandler.getOtherFarms": - case "guild.gvgProduceHandler.getMyFarm": - case "guild.gvgProduceHandler.getOtherMines": - { - if (!checkNaturalNumbers(msg.farmId)) return false; - break; - } - case "guild.gvgProduceHandler.plant": - { - if (!checkNaturalNumbers(msg.farmId)) return false; - if (!checkArrayCanEmpty(msg.seeds)) return false; - for (let { fieldId, seedType, index } of msg.seeds) { - if (!checkNaturalNumbers(fieldId, seedType, index)) return false; - if (!checkIsInEnum(GVG_SEED_TYPE, seedType)) return false; - } - break; - } - case "guild.gvgProduceHandler.harvest": - { - if (!checkNaturalNumbers(msg.farmId)) return false; - if (!checkNumberArray(msg.fieldIds)) return false; - break; - } - case "guild.gvgProduceHandler.plantEnd": - { - if (!checkNaturalNumbers(msg.farmId)) return false; - break; - } - case "guild.gvgProduceHandler.helpHarvest": - { - if (!checkNaturalNumbers(msg.farmId)) return false; - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "guild.gvgProduceHandler.mineStart": - case "guild.gvgProduceHandler.forestryStart": - { - if (!checkNaturalNumbers(msg.farmId, msg.itemId)) return false; - break; - } - case "guild.gvgProduceHandler.mineEnd": - { - if (!checkNaturalNumbers(msg.farmId, msg.fieldId)) return false; - if (!checkArrayCanEmpty(msg.result)) return false; - for (let { type, count } of msg.result) { - if (!checkNaturalNumbers(type, count)) return false; - } - break; - } - case "guild.gvgProduceHandler.forestryEnd": - { - if (!checkNaturalNumbers(msg.farmId, msg.fieldId, msg.result)) return false; - break; - } - case "guild.gvgFightHandler.getVestige": - case "guild.gvgFightHandler.refreshOpp": - case "guild.gvgFightHandler.getRec": - case "guild.gvgFightHandler.getPlayerRank": - - - { - if (!checkNaturalNumbers(msg.vestigeId)) return false; - break; - } - case "guild.gvgFightHandler.saveLineup": - { - if (!checkNaturalNumbers(msg.vestigeId)) return false; - if (!checkArrayCanEmpty(msg.lineup)) return false; - for (let { actorId, dataId, order } of msg.lineup) { - if (!checkNaturalNumbers(actorId, dataId, order)) return false; - } - break; - } - case "guild.gvgFightHandler.getOppLineup": - { - if (!checkNaturalNumbers(msg.vestigeId, msg.rank)) return false; - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "guild.gvgFightHandler.chooseOpp": - { - if (!checkNaturalNumbers(msg.vestigeId, msg.rank, msg.myRank)) return false; - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "guild.gvgFightHandler.giveupCheck": - case "guild.gvgFightHandler.getOppData": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - break; - } - case "guild.gvgFightHandler.checkBattle": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - if (!checkArrayCanEmpty(msg.heroes)) return false; - for (let { actorId, dataId, order } of msg.heroes) { - if (!checkNaturalNumbers(actorId, dataId, order)) return false; - } - break; - } - case "guild.gvgFightHandler.battleEnd": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case "guild.gvgBattleHandler.saveTeam": - { - if (!checkNaturalNumbers(msg.index, msg.head, msg.frame, msg.spine)) return false; - if (msg.lineup) { - for (let { actorId, dataId, order } of msg.lineup) { - if (!checkNaturalNumbers(actorId, dataId, order)) return false; - } - } - break; - } - case "guild.gvgBattleHandler.getCity": - case "guild.gvgBattleHandler.enterCity": - case "guild.gvgBattleHandler.leaveCity": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - break; - } - case "guild.gvgBattleHandler.startMove": - case "guild.gvgBattleHandler.stopMove": - { - if (!checkNaturalNumbers(msg.cityId, msg.areaId)) return false; - if (!checkNaturalStrings(msg.teamCode)) return false; - break; - } - case "guild.gvgBattleHandler.teamSettle": - { - if (!checkNaturalNumbers(msg.cityId, msg.areaId, msg.pointId)) return false; - if (!checkNaturalStrings(msg.teamCode)) return false; - break; - } - case "guild.gvgBattleHandler.teamLeave": - { - //TODO - break; - } - case "guild.gvgBattleHandler.battleStart": - { - if (!checkNaturalStrings(msg.teamCode, msg.oppoTeamCode)) return false; - break; - } - case "guild.gvgBattleHandler.battleEnd": - { - if (!checkNaturalStrings(msg.battleCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - if (!checkGvgEndHeroFormat(msg.myHeroes)) return false; - if (!checkGvgEndHeroFormat(msg.oppHeroes)) return false; - break; - } - case "guild.gvgBattleHandler.useItem": - { - if (!checkNaturalNumbers(msg.cityId, msg.itemId)) return false; - if (!checkNaturalStrings(msg.teamCode, msg.oppoTeamCode)) return false; - break; - } - case "guild.gvgBattleHandler.reviveTeam": - { - if (!checkNaturalStrings(msg.teamCode)) return false; - break; - } - case "guild.gvgBattleHandler.getRecs": - { - if (!checkNaturalNumbers(msg.type)) return false; - break; - } - case "guild.gvgBattleHandler.getOverview": - { - break; - } - case "guild.gvgBattleHandler.getAreaTeams": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - if (!checkNumberArray(msg.areaIds)) return false; - break; - } - case "guild.gvgBattleHandler.setTargetCity": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - if (!checkBoolean(msg.isTarget)) return false; - break; - } - case "guild.gvgBattleHandler.getAreaTeams": - { - if (!checkStringIfExist(msg.notice)) return false; - break; - } - case "guild.gvgBattleHandler.getOppTeam": - { - if (!checkNaturalNumbers(msg.cityId)) return false; - if (!checkNaturalStrings(msg.teamCode)) return false; - break; - } - case "order.orderHandler.applyOrder": - { - let { productID, payType, activityId, paramStr, useVoucher } = msg; - if (!checkNaturalNumbers(payType, activityId, useVoucher)) return false; - if (!checkNaturalStrings(productID)) return false; - if (!checkStringIfExist(paramStr)) return false; - break; - } - case "order.orderHandler.checkOrder": - { - if (!checkNaturalStrings(msg.localOrderID)) return false; - break; - } - case "role.equipHandler.composeEquip": - case "role.equipHandler.putOffJewel": - { - if (!checkNaturalNumbers(msg.hid, msg.ePlaceId)) return false; - break; - } - case "role.equipHandler.strengthen": - case "role.equipHandler.qualityUp": - case "role.equipHandler.starUp": - { - if (!checkNaturalNumbers(msg.hid, msg.ePlaceId)) return false; - if (!checkBoolean(msg.isOneClick)) return false; - break; - } - case "role.equipHandler.strengthenAll": - { - if (!checkNaturalNumbers(msg.hid, msg.lv)) return false; - break; - } - case "role.equipHandler.putOnJewel": - { - if (!checkNaturalNumbers(msg.hid, msg.ePlaceId, msg.jewel)) return false; - break; - } - case "role.equipHandler.putOnOrOffStone": - { - if (!checkNaturalNumbers(msg.hid, msg.ePlaceId, msg.stonesId, msg.gid)) return false; - break; - } - case "role.equipHandler.lockRandSe": - { - if (!checkNaturalNumbers(msg.seqId, msg.randSeId, msg.type)) return false; - if (msg.type != 0 && msg.type != 1) return false; - break; - } - case "role.equipHandler.previewRandSe": - case "role.equipHandler.resetRandSe": - case "role.equipHandler.giveupPreview": - case "role.equipHandler.quench": - { - if (!checkNaturalNumbers(msg.seqId)) return false; - break; - } - case "role.equipHandler.chooseQuench": - { - if (!checkNaturalNumbers(msg.seqId, msg.randSeId)) return false; - break; - } - case "role.equipHandler.decomposeItem": - { - if (!checkNaturalArray(msg.origin)) return false; - for (let { id, count } of msg.origin) { - if (!checkNaturalNumbers(id, count)) return false; - } - break; - } - case "role.equipHandler.decomposeJewel": - { - if (!checkNumberArray(msg.origin)) return false; - break; - } - case "role.equipHandler.composeStone": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "role.equipHandler.composeStoneByItId": - { - if (!checkNaturalNumbers(msg.itId)) return false; - break; - } - case "role.equipHandler.inheritJewel": - { - if (!checkNaturalNumbers(msg.originJewel, msg.targetJewel)) return false; - break; - } - case "role.artifactHandler.putOn": - { - if (!checkSeqId(msg.seqId)) return false; - if (!checkNaturalNumbers(msg.hid)) return false; - break; - } - case "role.artifactHandler.putOff": - { - if (!checkSeqId(msg.seqId)) return false; - break; - } - case "role.artifactHandler.lvUp": - { - if (!checkSeqId(msg.seqId)) return false; - if (!checkBoolean(msg.isOneClick)) return false; - break; - } - case "role.artifactHandler.compose": - { - if (!checkSeqId(msg.seqId)) return false; - if (!checkSeqId(...msg.material)) return false; - if (!checkArrayCanEmpty(msg.generalItems)) return false; - for (let { id, count } of msg.generalItems) { - if (!checkNaturalNumbers(id, count)) return false; - } - break; - } - case "role.artifactHandler.transfer": - { - if (!checkSeqId(msg.seqId)) return false; - if (!checkNaturalNumbers(msg.type)) return false; - break; - } - case "role.artifactHandler.previewRebuild": - case "role.artifactHandler.rebuild": - case "role.artifactHandler.decompose": - { - if (!checkSeqId(...msg.seqIds)) return false; - break; - } - case "role.friendHandler.searchUser": - { - if (!checkNaturalStrings(msg.value)) return false; - break; - } - case "role.friendHandler.applyFriend": - { - if (!checkStringArray(msg.roleIds)) return false; - break; - } - case "role.friendHandler.handleApply": - { - if (!checkStringArray(msg.applyCodeList)) return false; - if (!checkBoolean(msg.isPass)) return false; - break; - } - case "role.friendHandler.setBlackList": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalNumbers(msg.type)) return false; - if (!checkIsInEnum(BLOCK_OPEATE, msg.type)) return false; - break; - } - case "role.friendHandler.sendHeart": - case "role.friendHandler.receiveHeart": - { - if (!checkStringIfExist(msg.roleId)) return false; - break; - } - case "role.friendHandler.getPlayerSimpleInfo": - case "role.friendHandler.getPlayerDetail": - { - if (!checkNaturalStrings(msg.roleId)) return false; - break; - } - case "role.friendHandler.sendPresent": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNaturalArray(msg.items)) return false; - for (let { id, count } of msg.items) { - if (!checkNaturalNumbers(id, count)) return false; - } - break; - } - case "role.friendHandler.getHeroDetail": - { - if (!checkNaturalStrings(msg.roleId)) return false; - if (!checkNumberArray(msg.hids)) return false; - break; - } - case "role.heroHandler.compose": - { - if (!checkNaturalNumbers(msg.hid)) return false; - break; - } - case "role.heroHandler.lvUp": - { - if (!checkNaturalNumbers(msg.hid, msg.type)) return false; - break; - } - case "role.heroHandler.starUp": - { - let { hid, star, starStage, isOneClick } = msg; - if (!checkNaturalNumbers(hid, star, starStage)) return false; - if (!checkBoolean(isOneClick)) return false; - break; - } - case "role.heroHandler.qualityUp": - { - let { hid, quality } = msg; - if (!checkNaturalNumbers(hid, quality)) return false; - break; - } - case "role.heroHandler.wakeUp": - { - let { hid, colorStar, colorStarStage, isOneClick } = msg; - if (!checkNaturalNumbers(hid, colorStar, colorStarStage)) return false; - if (!checkBoolean(isOneClick)) return false; - break; - } - case "role.heroHandler.heroJobTrain": - { - let { hid, isOneClick, canReplace } = msg; - if (!checkNaturalNumbers(hid)) return false; - if (!checkBoolean(isOneClick, canReplace)) return false; - break; - } - case "role.heroHandler.heroJobStageUp": - { - if (!checkNaturalNumbers(msg.hid)) return false; - break; - } - case "role.heroHandler.heroGiveFavor": - { - if (!checkNaturalNumbers(msg.hid, msg.shipId, msg.type)) return false; - break; - } - case "role.heroHandler.heroWearSkin": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "role.heroHandler.previewRebirth": - case "role.heroHandler.rebirth": - case "role.heroHandler.resetTalent": - { - if (!checkNaturalNumbers(msg.hid)) return false; - break; - } - case "role.heroHandler.unlockTalent": - case "role.heroHandler.upgradeTalent": - { - if (!checkNaturalNumbers(msg.hid, msg.id)) return false; - break; - } - case "role.heroHandler.heroReborn": - { - const { originHid, targetHid } = msg; - if (originHid == targetHid) return false; - if (!checkNaturalNumbers(originHid, targetHid)) return false; - break; - } - case "role.itemHandler.useItem": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - if (!checkNumberArray(msg.selected)) return false; - break; - } - case "role.itemHandler.useApItem": - case "role.itemHandler.buyApItem": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "role.itemHandler.useGiftCode": - { - if (!checkNaturalStrings(msg.code)) return false; - break; - } - case "role.itemHandler.getApByLv": - { - if (!checkNaturalNumbers(msg.lv)) return false; - break; - } - case "role.itemHandler.exchangeSpirit": - { - if (!checkNaturalArray(msg.origin)) return false; - for (let { id, count } of msg.origin) { - if (!checkNaturalNumbers(id, count)) return false; - } - break; - } - case "role.mailHandler.readMail": - { - if (!checkNaturalStrings(msg.id)) return false; - if (!checkMailType(msg.mailType)) return false; - break; - } - case "role.mailHandler.delMails": - case "role.mailHandler.getMailRewards": - { - if (!checkStringIfExist(msg.id)) return false; - if (!checkMailType(msg.mailType)) return false; - if (msg.type != 1 && msg.type != 2) return false; - break; - } - case "role.rankHandler.getRank": - case "role.rankHandler.getGuildRank": - { - if (!checkNaturalNumbers(msg.type)) return false; - break; - } - case "role.rankHandler.getHeroRank": - { - if (!checkNaturalNumbers(msg.type, msg.hid)) return false; - break; - } - case "role.rankHandler.receiveReward": - { - if (!checkNaturalNumbers(msg.type, msg.id)) return false; - break; - } - case "role.roleHandler.initRole": - case "role.roleHandler.rename": - { - if (!checkNaturalStrings(msg.roleName)) return false; - break; - } - case "role.roleHandler.getRoleInfo": - { - if (!checkNaturalStrings(msg.targetRoleId)) return false; - break; - } - case "role.roleHandler.roleTeraphStrengthen": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "role.roleHandler.roleTeraphQualityUp": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "role.roleHandler.changeSchoolHero": - { - let { schoolId, positionId, hid } = msg; - if (!checkNaturalNumbers(schoolId, positionId, hid)) return false; - break; - } - case "role.roleHandler.unlockSchoolPosition": - { - if (!checkNaturalNumbers(msg.schoolId, msg.positionId)) return false; - break; - } - case "role.roleHandler.activeHeroScroll": - { - if (!checkNaturalNumbers(msg.hid)) return false; - break; - } - case "role.roleHandler.saveShowLineup": - { - if (!checkArrayCanEmpty(msg.showLineup)) return false; - for (let hid of msg.showLineup) { - if (!checkNaturalNumbers(hid)) return false; - } - break; - } - case "role.roleHandler.setHead": - case "role.roleHandler.setFrame": - case "role.roleHandler.setSpine": - { - if (!checkNaturalNumbers(msg.id)) return false; - break; - } - case "role.roleHandler.saveGuide": - { - if (!checkNumberArray(msg.ids)) return false; - break; - } - case "role.shopHandler.getShopList": - case "role.shopHandler.readShop": - { - if (!checkNaturalNumbers(msg.shop, msg.type)) return false; - break; - } - case "role.shopHandler.purchase": - { - if (!checkNaturalNumbers(msg.shopItemId, msg.count)) return false; - break; - } - case "role.shopHandler.recycleSoul": - { - if (!checkNaturalNumbers(msg.goodsId, msg.count)) return false; - break; - } - case "role.shopHandler.recycleSoulFast": - { - if (!checkNaturalArray(msg.recycleSoulFastPara)) return false; - for (let { hid, count } of msg.recycleSoulFastPara) { - if (!checkNaturalNumbers(hid, count)) return false; - } - break; - } - case "role.taskHandler.receiveTask": - { - if (!checkNaturalNumbers(msg.type, msg.id)) return false; - break; - } - case "role.taskHandler.receiveBox": - { - if (!checkNaturalNumbers(msg.type, msg.id)) return false; - break; - } - case "role.taskHandler.receiveMainStage": - { - if (!checkNaturalNumbers(msg.stage)) return false; - break; - } - case "battle.ladderHandler.getRec": - { - if (!checkNaturalStrings(msg.name)) return false; - if (!checkStringIfExist(msg.notice)) return false; - if (!checkNaturalNumbers(msg.icon)) return false; - break; - } - case "role.heroHandler.addItem": - { - if (!isDevelopEnv()) return false; - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "role.roleHandler.setPushMsgTrigger": - { - if (!isBoolean(msg.isClosePush)) return false; - break; - } - case "role.roleHandler.setHasComment": - { - if (!isBoolean(msg.hasComment)) return false; - break; - } - case "role.authorBookHandler.starUp": - { - if (!checkNaturalNumbers(msg.bookId, msg.subId, msg.star)) return false; - if (!isBoolean(msg.useItem)) return false; - break; - } - case "role.authorBookHandler.resetAuthor": - { - if (!checkNaturalNumbers(msg.bookId, msg.subId, msg.star)) return false; - break; - } - case "role.authorBookHandler.buySpirit": - { - if (!checkNaturalNumbers(msg.id, msg.count)) return false; - break; - } - case "role.authorBookHandler.decomposeSpirit": - { - if (!checkNaturalArray(msg.spirits)) return false; - for (let { id, count } of msg.spirits) { - if (!checkNaturalNumbers(id, count)) return false; - } - break; - } - case "role.resonanceHandler.getData": - { - break; - } - case "role.resonanceHandler.unlockPosition": - { - if (!checkNaturalNumbers(msg.position)) return false; - break; - } - case "role.resonanceHandler.heroPutPosition": - { - if (!checkNaturalNumbers(msg.position, msg.hid)) return false; - break; - } - case "role.resonanceHandler.heroOffPosition": - { - if (!checkNaturalNumbers(msg.position, msg.hid)) return false; - break; - } - case 'activity.dragonBoatHandler.gameStart': - case 'activity.dragonBoatHandler.gameEnd': - { - if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; - break; - } - case 'activity.dragonBoatHandler.buyCnt': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.qixiHandler.gameStart': - { - if (!checkNaturalNumbers(msg.activityId, msg.progress)) return false; - break; - } - case 'activity.qixiHandler.gameEnd': - { - if (!checkNaturalNumbers(msg.activityId, msg.progress, msg.addProgress)) return false; - if (!checkNaturalStrings(msg.gameCode)) return false; - break; - } - case 'activity.qixiHandler.buyCnt': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.midAutumnHandler.gameStart': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.midAutumnHandler.gameEnd': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - if (!checkNaturalStrings(msg.gameCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case 'activity.midAutumnHandler.buyCnt': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.midAutumnHandler.gameSweep': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.authorGachaHandler.getData': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.authorGachaHandler.receiveBox': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.chongyangHandler.getData': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.chongyangHandler.gameStart': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; - break; - } - case 'activity.chongyangHandler.gameEnd': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; - if (!checkNaturalStrings(msg.gameCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case 'activity.chongyangHandler.buyCnt': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.count)) return false; - break; - } - case 'activity.chongyangHandler.gameSweep': - { - if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.count)) return false; - break; - } - case 'activity.novemberHandler.getData': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.novemberHandler.gameStart': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - break; - } - case 'activity.novemberHandler.gameEnd': - { - if (!checkNaturalNumbers(msg.activityId)) return false; - if (!checkNaturalStrings(msg.gameCode)) return false; - if (!checkBoolean(msg.isSuccess)) return false; - break; - } - case 'activity.novemberHandler.buyCnt': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.novemberHandler.gameSweep': - { - if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; - break; - } - case 'activity.activityHandler.debugActivityMemory': - case 'activity.popUpShopHandler.debugPushPopUpShop': - case 'activity.popUpShopHandler.debugPushPopUpInterval': - case 'activity.popUpShopHandler.debugStopPupUpInterval': - case 'activity.popUpShopHandler.debugSendMail': - case 'activity.popUpShopHandler.debugTakeSnapshot': - case "battle.dailyBattleHandler.debugResetNum": - case "battle.dungeonBattleHandler.debugResetRefTime": - case "battle.eventBattleHandler.debugRefEvent": - case "battle.expeditionBattleHandler.debugResetResetNum": - case "battle.pvpHandler.addRoleScore": - case "battle.pvpHandler.debugAddChallengeCnt": - case "battle.pvpHandler.debugPvpSeasonResetTime": - case "battle.pvpHandler.debugResetAttackCnt": - case "battle.pvpHandler.debugResetBox": - case "battle.pvpHandler.debugResetRefOppCnt": - case "connector.entryHandler.debugGetRole": - case "connector.entryHandler.debugPushRefToOnlineUsers": - case "connector.entryHandler.debugQueryToken": - case "connector.entryHandler.debugQueryTokenById": - case "connector.entryHandler.debugQueryTokenByTel": - case "guild.auctionHandler.debugAddLots": - case "guild.auctionHandler.debugScheduleSendUngotDividend": - case "guild.auctionHandler.debugScheduleStartGuild": - case "guild.auctionHandler.debugScheduleStartWorld": - case "guild.auctionHandler.debugScheduleStopAuction": - case "guild.auctionHandler.debugSetDividendStatus": - case "guild.auctionHandler.debugSetLotStage": - case "guild.auctionHandler.debugSetPlayTime": - case "guild.cityActivityHandler.debugResetCity": - case "guild.gateActivityHandler.debugAddParticipants": - case "guild.gateActivityHandler.debugDelRedis": - case "guild.gateActivityHandler.debugEndActivity": - case "guild.gateActivityHandler.debugGetPrivate": - case "guild.gateActivityHandler.debugIncChallengeCnt": - case "guild.gateActivityHandler.debugSetDay": - case "guild.gateActivityHandler.debugStartActivity": - case "guild.gateActivityHandler.test": - case "guild.guildHandler.debugAddActive": - case "guild.guildHandler.debugAdddFund": - case "guild.guildHandler.debugClearQuitGuildTime": - case "guild.guildHandler.debugJoinGuild": - case "guild.guildBossHandler.debugAddBattleTimes": - case "guild.guildBossHandler.debugAddOpenTimes": - case "guild.guildHandler.debugLeaderLeaveTime": - case "guild.guildHandler.debugWeeklyRask": - case "order.orderHandler.debugOrder": - case "role.heroHandler.debugGetAllHeroes": - case "role.heroHandler.debugSetHero": - case "guild.guildTrainHandler.debugAddTrainCount": - case "guild.guildTrainHandler.debugResetTrainInstance": - case "role.heroHandler.testCleanUp": - case "role.itemHandler.debugIncAp": - case "role.itemHandler.debugResetBuyTimes": - case "role.roleHandler.debugClearRole": - case "role.roleHandler.debugPlayerTime": - case "role.roleHandler.debugRoleLvUp": - case "role.roleHandler.debugSetRole": - case "role.roleHandler.debugTreatRoleName": - case "role.roleHandler.test": - case "role.taskHandler.test": - case "role.taskHandler.debugCompleteMainStage": - case "role.taskHandler.debugCompleteRandTask": - case "role.taskHandler.debugGetDicTask": - case "role.taskHandler.debugIncPoint": - case "role.taskHandler.debugRefTask": - case "role.shopHandler.debugClearPurchaseLimit": - case "guild.raceActivityHandler.settleReward": - case "battle.ladderHandler.resetCnt": - case "battle.ladderHandler.setMyRank": - case "battle.ladderHandler.setMyOpp": - case "guild.raceActivityHandler.debugAddHorse": - case "activity.gachaHandler.debugClearGachaRecord": - case "battle.eventBattleHandler.debugRefEvent": - // case "guild.raceActivityHandler.debugResetJoin": - case "guild.cityActivityHandler.debugStartHitGate": - case "guild.cityActivityHandler.debugStopHitGate": - case "guild.cityActivityHandler.debugTestAutoDeclare": - case "activity.groupShopHandler.debugRefund": - case "activity.groupShopHandler.debugSetSum": - case "activity.groupShopHandler.debugClearCnt": - case "activity.groupShopHandler.debugAddLeagueItem": - case "activity.groupShopHandler.debugHandleCost": - case "guild.gvgProduceHandler.debugAddResource": - case "guild.gvgFightHandler.debugCalRec": - case "guild.gvgFightHandler.debugSaveScore": - case "guild.gvgBattleHandler.createCity": - case "guild.gvgProduceHandler.debugAdjustHarvest": - case "guild.gvgFightHandler.debugSetMyRank": - case "guild.gvgFightHandler.debugSetMyOpp": - case "guild.gvgBattleHandler.debugAddRobots": - case "guild.gvgBattleHandler.debugMoveRobots": - case "guild.gvgBattleHandler.debugStopMoveRobot": - case "chat.chatHandler.debugPushMessage": - case "activity.monthlyFundHandler.debugSendMonthlyFundReward": - case "activity.bindPhoneHandler.debugSetGiftCodeStatus": - case 'activity.rebateHandler.debugSetRebate': - case 'activity.newHeroGKHandler.debugResetGK': - case 'battle.rougeHandler.debugClearTech': - case "battle.rougeHandler.debugAddCard": - case "battle.rougeHandler.debugAddScore": - case "battle.rougeHandler.debugRepaireScoreReward": - case "battle.rougeHandler.debugAddCollection": - { - if (msg.magicWord !== DEBUG_MAGIC_WORD || !isDevelopEnv()) return false; - break; - } - case "battle.rougeHandler.debugAddLimitId": - - case "comBattle.comBattleHandler.getTeams": - case "comBattle.comBattleHandler.teammateReady": - case "comBattle.comBattleHandler.battleEnd": - case "connector.entryHandler.addSession": - case "connector.entryHandler.getIp": - case "chat.chatHandler.getInitMessage": - case "connector.entryHandler.onGmUserLeave": - case "connector.entryHandler.onUserLeave": - case "gm.gmHandler.sendMail": - case "gm.gmHandler.saveGroupToServer": - case "gm.gmHandler.saveActivitiesToGroup": - case "role.mailHandler.refrshMails": - { - return false - } - } - return true; -} - -function checkNaturalNumbers(...params: number[]) { - for (let param of params) { - if (param == undefined || !isNumber(param) || param < 0) return false; - } - return true -} - -function checkNaturalArray(array: T[]) { - return isArray(array) && array.length > 0; -} - -function checkArrayCanEmpty(array: T[]) { - return isArray(array); -} - -function checkNaturalStrings(...params: string[]) { - for (let param of params) { - if (param == undefined || !isString(param) || param == '') return false; - } - return true; -} - -function checkStringIfExist(...params: string[]) { - for (let param of params) { - if (!!param && !isString(param)) return false; - } - return true; -} - -function checkNumberIfExist(...params: number[]) { - for (let param of params) { - if (!!param && !isNumber(param)) return false; - } - return true; -} - -function checkNumberArray(...params: number[][]) { - for (let array of params) { - if (array == undefined || !isArray(array)) return false; - if (!checkNaturalNumbers(...array)) return false; - } - return true; -} - -function checkStringArray(...params: string[][]) { - for (let array of params) { - if (array == undefined || !isArray(array)) return false; - if (!checkNaturalStrings(...array)) return false; - } - return true; -} - -function checkBoolean(...params: boolean[]) { - for (let param of params) { - if (!isBoolean(param)) return false; - } - return true; -} - -function checkBooleanIfExist(...params: boolean[]) { - for (let param of params) { - if (param != undefined && !isBoolean(param)) return false; - } - return true; -} - -function checkExpeditionBattleHeroFormat(...params: { dataId: number, hp: number, ap: number }[][]) { - for (let param of params) { - if (!checkArrayCanEmpty(param)) return false; - for (let { dataId, hp, ap } of param) { - if (!checkNaturalNumbers(dataId, ap)) return false; - if (!isNumber(hp)) return false; - } - } - return true; -} - -function checkPvpEndHeroFormat(...params: pvpEndParamInter[][]) { - for (let param of params) { - if (!checkArrayCanEmpty(param)) return false; - for (let { hid, damage, heal, underDamage } of param) { - if (!checkNaturalNumbers(hid, damage, heal, underDamage)) return false; - } - } - return true; -} - -function checkGvgEndHeroFormat(...params: gvgEndParamInter[][]) { - for (let param of params) { - if (!checkArrayCanEmpty(param)) return false; - for (let { actorId, hp, others } of param) { - if (!checkNaturalNumbers(actorId, hp)) return false; - if (!checkStringIfExist(others)) return false; - } - } - return true; -} - -function checkIsInEnum(someEnum: T, value: T) { - return Object.values(someEnum).includes(value) -} - -function checkMailType(mailType: any) { - if (!checkNaturalNumbers(mailType)) return false; - if (!checkIsInEnum(GM_MAIL_TYPE, mailType)) return false; - return true; -} - -function checkSeqId(...seqIds: (number | string)[]) { - for (let seqId of seqIds) { - if (!checkNaturalNumbers(seqId) && !checkNaturalStrings(seqId)) return false - } - return true; -} - -function checkCombo(combo: { groupId: number, levelList: number[] }[]) { - if (combo) { - if (!isArray(combo)) return false; - for (let { groupId, levelList } of combo) { - if (!isNumber(groupId)) return false; - if (!isArray(levelList)) return false; - for (let lv of levelList) { - if (!isNumber(lv)) return false; - } - } - } - return true; -} - -function checkIsDuplicateNumbers(array: number[]) { - const seen = new Set(); - for (const item of array) { - if (!isNumber(item)) return false; - if (seen.has(item)) { - return false; // 发现重复元素 - } - seen.add(item); - } - return true; // 没有重复元素 -} - -function checkIsDuplicateStrings(array: string[]) { - const seen = new Set(); - for (const item of array) { - if (!isString(item)) return false; - if (seen.has(item)) { - return false; // 发现重复元素 - } - seen.add(item); - } - return true; // 没有重复元素 -} \ No newline at end of file +import { isArray, isBoolean, isNumber, isString } from "underscore"; +import { BLOCK_OPEATE, DEBUG_MAGIC_WORD, GM_MAIL_TYPE, GUILD_AUTH, GUILD_STRUCTURE, GVG_RESOURCE_TYPE, GVG_SEED_TYPE, LEAGUE_JOB, LINEUP_NUM, MSG_TYPE } from "@consts"; +import { gvgEndParamInter, pvpEndParamInter } from "@pubUtils/interface"; +import { isDevelopEnv } from "./utilService"; + +export function checkRouteParam(route: string, msg: any) { + switch (route) { + case 'activity.activityHandler.getAllOpenActivity': + case 'activity.gachaHandler.getGachaList': + case 'activity.gachaHandler.getVisitedHero': + case 'activity.gachaHandler.getGuideGachaData': + case 'activity.selfServiceShopHandler.getSelfServiceShopActivity': + case "comBattle.comBattleHandler.cancelSearch": + case "comBattle.comBattleHandler.getTeamRec": + case "comBattle.comBattleHandler.getAssistCnt": + case "comBattle.comBattleHandler.getComBtlCnt": + case "comBattle.comBattleHandler.getRecentTeammates": + case "comBattle.comBattleHandler.getTeamInvitation": + case "battle.dailyBattleHandler.getData": + case "battle.dungeonBattleHandler.getData": + case "battle.eventBattleHandler.getEvents": + case "battle.expeditionBattleHandler.getStatus": + case "battle.expeditionBattleHandler.resetStatus": + case "battle.normalBattleHandler.getMainStarBox": + case "battle.pvpHandler.getData": + case "battle.pvpHandler.refreshOppPlayer": + case "battle.pvpHandler.getRank": + case "battle.pvpHandler.getRec": + case "battle.ladderHandler.getData": + case "battle.ladderHandler.refreshOppPlayers": + case "battle.ladderHandler.getRec": + + case "battle.towerBattleHandler.getStatus": + case "battle.towerBattleHandler.checkHangUpRewards": + case "battle.towerBattleHandler.recHangUpRewards": + case "battle.towerBattleHandler.getTasks": + case "battle.towerBattleHandler.refreshTasks": + case "chat.chatHandler.getRecentPrivateChats": + case "chat.chatHandler.getGroupMessages": + case "connector.entryHandler.getData": + case "connector.entryHandler.refresh": + case "gate.gateHandler.queryEntry": + case "guild.auctionHandler.checkDividend": + case "guild.auctionHandler.myWatching": + case "guild.cityActivityHandler.getCityActivity": + case "guild.cityActivityHandler.resetChallengeTime": + case "guild.donateHandler.getDonation": + case "guild.gateActivityHandler.getGateActivity": + case "guild.guildBossHandler.getBossInstance": + case "guild.guildBossHandler.openBossInstance": + case "guild.guildBossHandler.battleBoss": + case "guild.guildHandler.getMyGuildInfo": + case "guild.guildHandler.getInviteMemberList": + case "guild.guildHandler.getActiveRank": + case "guild.guildRefineHandler.getRefine": + case "guild.guildTrainHandler.getTrainInstance": + case "guild.guildTrainHandler.getTrainReports": + case "guild.guildTrainHandler.getTrainBoxs": + case "guild.raceActivityHandler.getRaceActivity": + case "guild.raceActivityHandler.join": + case "guild.raceActivityHandler.getRace": + case "guild.wishPoolHandler.getWishPool": + case "guild.wishPoolHandler.getReports": + case "role.friendHandler.getRecommend": + case "role.friendHandler.getApplyList": + case "role.friendHandler.getFriendList": + case "role.friendHandler.getBlackList": + case "role.itemHandler.getAp": + case "role.mailHandler.getMails": + case "role.rankHandler.getGeneralRank": + case "role.rankHandler.getRankReward": + case "role.roleHandler.roleTitleLevelUp": + case "role.roleHandler.getSchoolList": + case "role.taskHandler.getPvpTaskList": + case "role.taskHandler.getTaskList": + case "role.taskHandler.receiveActiveReward": + case "role.artifactHandler.composeAll": + case "guild.gvgHandler.getData": + case "guild.gvgHandler.getMap": + case "guild.gvgHandler.getRec": + case "guild.gvgHandler.getContribute": + case "guild.gvgHandler.getTech": + case "guild.gvgManageHandler.getApplies": + case "guild.gvgManageHandler.getLeagueInvitations": + case "guild.gvgFightHandler.getLeagueRank": + case "guild.gvgFightHandler.getLeagueDetailRank": + case "guild.gvgFightHandler.receiveBox": + { + break; + } + case 'activity.activityMonopolyHandler.getMonopolyActivity': + case 'activity.dailyChallengeHandler.getDailyChallengesActivity': + case 'activity.dailyCoinHandler.getDailyCoinActivity': + case 'activity.dailyGiftsHandler.getDailyGiftsActivity': + case 'activity.dailyGKHandler.getDailyGKActivity': + case 'activity.dailyMealHandler.getDailyMealActivity': + case 'activity.dailyRMBGiftsHandler.getDailyRMBGiftsActivity': + case 'activity.firstGiftHandler.getFirstGiftActivity': + case 'activity.growthFundHandler.getGrowthFundActivity': + case 'activity.growthHandler.getGrowthActivity': + case 'activity.guildPayHandler.getGuildPayData': + case 'activity.limitPackageHandler.getNewPlayerLimitPackageActivity': + case 'activity.luckyTurntableHandler.getTurntableData': + case 'activity.luckyHandler.getTurntableData': + case 'activity.monthlyTicketHandler.getMonthlyTicketActivity': + case 'activity.newHeroGachaHandler.getNewHeroGachaActivity': + case 'activity.newHeroGiftsHandler.getNewHeroGiftsActivity': + case 'activity.newHeroGKHandler.getNewHeroGKActivity': + case 'activity.newHeroGachaHandler.getData': + case 'activity.popUpShopHandler.getPopUpShopActivity': + case 'activity.rechargeMoneyHandler.getRechargeMoneyActivity': + case 'activity.refreshShopHandler.getRefreshShopActivity': + case 'activity.refreshTaskHandler.getRefreshTaskActivity': + case 'activity.sevenDaysHandler.getSevenDaysActivity': + case 'activity.signInHandler.getSignInActivity': + case 'activity.taskPassHandler.getTaskPassData': + case 'activity.thirtyDaysHandler.getThirtyDaysActivity': + case 'activity.timeLimitRankHandler.getTimeLimitRankData': + case 'activity.treasureHuntHandler.getTreasureHuntActivity': + case 'activity.vipRechargeMoneyHandler.getVipRechargeMoneyActivity': + case 'activity.yuanbaoShopHandler.getShopActivity': + case 'activity.groupShopHandler.getGroupShopPage': + case 'activity.groupShopHandler.leaveGroupShopPage': + case 'activity.forgeHandler.getForgeActivity': + case 'activity.miniGameHandler.getMiniGameActivity': + case 'activity.weeklyFundHandler.getData': + case 'activity.monthlyFundHandler.getData': + case 'activity.bindPhoneHandler.bind': + case 'activity.bindPhoneHandler.receiveReward': + case 'activity.bindPhoneHandler.receiveGiftCode': + case 'activity.bindPhoneHandler.skipOutSide': + case 'activity.dragonBoatHandler.getData': + case 'activity.qixiHandler.getData': + case 'activity.midAutumnHandler.getData': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.activityMonopolyHandler.move': + { + if (!checkNaturalNumbers(msg.activityId, msg.step)) return false; + if (msg.step < 0 || msg.step > 7) return false; + break; + } + case 'activity.activityMonopolyHandler.bank': + { + if (!checkNaturalNumbers(msg.activityId, msg.addCount)) return false; + break; + } + case 'activity.activityMonopolyHandler.getRefreshShopActivity': + { + if (!checkNaturalNumbers(msg.activityId, msg.shopActivityId)) return false; + break; + } + case 'activity.activityMonopolyHandler.buyGood': + { + let { monopolyActivityId, shopActivityId, roundIndex, id, pageIndex } = msg; + if (!checkNaturalNumbers(monopolyActivityId, shopActivityId, roundIndex, id, pageIndex)) return false; + break; + } + case 'activity.dailyChallengeHandler.getDailyChallengeReward': + case 'activity.sevenDaysHandler.getDailyChallengeReward': + { + let { activityId, dayIndex, cellIndex, type } = msg; + if (!checkNaturalNumbers(activityId, dayIndex, cellIndex, type)) return false; + break; + } + case 'activity.dailyCoinHandler.exchangeCoin': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.dailyCoinHandler.receiveExtraReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; + break; + } + case 'activity.dailyGiftsHandler.buyDailyGiftsCell': + case 'activity.sevenDaysHandler.buyDailyGiftsCell': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.cellIndex)) return false; + break; + } + case 'activity.dailyGKHandler.getGK': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; + break; + } + case 'activity.dailyMealHandler.getDailyMealReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.type)) return false; + break; + } + case 'activity.dailyRMBGiftsHandler.getDailyRMBGiftsReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + break; + } + case 'activity.firstGiftHandler.getFirstGiftReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.pageIndex)) return false; + break; + } + case 'activity.gachaHandler.pull': + { + if (!checkNaturalNumbers(msg.activityId, msg.gachaId, msg.count)) return false; + break; + } + case 'activity.gachaHandler.setHope': + { + if (!checkNaturalNumbers(msg.gachaId)) return false; + if (!checkNaturalArray(msg.hope)) return false; + for (let { id, hid } of msg.hope) { + if (!checkNaturalNumbers(id, hid)) return false; + } + break; + } + case 'activity.gachaHandler.drawTurnTable': + { + if (!checkNaturalNumbers(msg.gachaId)) return false; + break; + } + case 'activity.gachaHandler.setPickHero': + { + if (!checkNaturalNumbers(msg.gachaId, msg.activityId, msg.pickHero)) return false; + break; + } + case 'activity.gachaHandler.visitHero': + { + if (!checkNaturalNumbers(msg.hid)) return false + break; + } + case 'activity.gachaHandler.guidePull': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.gachaHandler.saveToCandidates': + case 'activity.gachaHandler.decide': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + break; + } + case 'activity.growthFundHandler.getGrowthFundCellReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.cellIndex)) return false; + break; + } + case 'activity.growthHandler.getGrowthCellReward': + case 'activity.sevenDaysHandler.getGrowthCellReward': + { + let { activityId, dayIndex, cellIndex, type } = msg; + if (!checkNaturalNumbers(activityId, dayIndex, cellIndex, type)) return false; + break; + } + case 'activity.growthHandler.getGrowthDayReward': + case 'activity.sevenDaysHandler.getGrowthDayReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + break; + } + case 'activity.guildPayHandler.receiveItems': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; + break; + } + case 'activity.limitPackageHandler.getLimitPackageActivity': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.limitPackageHandler.buyGood': + { + if (!checkNaturalNumbers(msg.activityId, msg.roundIndex, msg.id)) return false; + break; + } + case 'activity.luckyTurntableHandler.pull': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.luckyTurntableHandler.receiveBox': + { + if (!checkNaturalNumbers(msg.activityId, msg.boxCount)) return false; + break; + } + case 'activity.luckyHandler.pull': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.luckyHandler.receiveBox': + { + if (!checkNaturalNumbers(msg.activityId, msg.boxCount)) return false; + break; + } + case 'activity.monthlyTicketHandler.getMonthlyTicketReward': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.newHeroGachaHandler.selectedHero': + { + if (!checkNaturalNumbers(msg.activityId, msg.hid)) return false; + break; + } + case 'activity.newHeroGachaHandler.pull': + { + if (!checkNaturalNumbers(msg.activityId, msg.hid, msg.count)) return false; + break; + } + case 'activity.newHeroGiftsHandler.exchangePoint': + { + if (!checkNaturalNumbers(msg.activityId, msg.index)) return false; + break; + } + case 'activity.newHeroGKHandler.getGK': + { + if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.index)) return false; + break; + } + case 'activity.popUpShopHandler.checkPopUpCondition': + { + if (!checkNaturalNumbers(msg.conditionType)) return false; + break; + } + case 'activity.popUpShopHandler.buyGift': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + if (!checkNaturalStrings(msg.code)) return false; + break; + } + case 'activity.rechargeMoneyHandler.pull': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.refreshShopHandler.buyGood': + { + let { activityId, roundIndex, id, pageIndex, count } = msg; + if (!checkNaturalNumbers(activityId, roundIndex, id, pageIndex, count)) return false; + break; + } + case 'activity.refreshTaskHandler.getReward': + { + let { activityId, roundIndex, pageIndex, id, type } = msg; + if (!checkNaturalNumbers(activityId, roundIndex, id, pageIndex, type)) return false; + break; + } + case 'activity.refreshTaskHandler.exchangePoint': + { + if (!checkNaturalNumbers(msg.activityId, msg.roundIndex)) return false; + break; + } + case 'activity.selfServiceShopHandler.buyGift': + { + if (!checkNaturalNumbers(msg.activityId, msg.roundIndex, msg.index)) return false; + break; + } + case 'activity.selfServiceShopHandler.saveGood': + { + let { data = [] } = msg; + for (let { activityId, roundIndex, index, cellIndex, rewardIndex } of data) { + if (!checkNaturalNumbers(activityId, roundIndex, index, cellIndex, rewardIndex)) return false; + } + break; + } + case 'activity.selfServiceShopHandler.buyRecources': + { + if (!checkNaturalNumbers(msg.activityId, msg.roundIndex)) return false; + break; + } + case 'activity.selfServiceShopHandler.getWarId': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.signInHandler.getSignInReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; + break; + } + case 'activity.taskPassHandler.receiveItems': + { + if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.lv)) return false; + break; + } + case 'activity.taskPassHandler.speedUp': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.thirtyDaysHandler.getThirtyDaysCellReward': + { + let { activityId, pageIndex, cellIndex, tab } = msg; + if (!checkNaturalNumbers(activityId, pageIndex, cellIndex, tab)) return false; + break; + } + case 'activity.thirtyDaysHandler.getThirtyDaysPointReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; + break; + } + case 'activity.timeLimitRankHandler.getRank': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.treasureHuntHandler.getFirstPageReward': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.treasureHuntHandler.buyGoods': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex, msg.count)) return false; + break; + } + case 'activity.treasureHuntHandler.getTaskReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex)) return false; + break; + } + case 'activity.treasureHuntHandler.challenge': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.treasureHuntHandler.buyTreasureShopGoods': + { + if (!checkNaturalNumbers(msg.activityId, msg.cellIndex, msg.count)) return false; + break; + } + case 'activity.vipRechargeMoneyHandler.getVipRechargeMoneyReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + break; + } + case 'activity.vipRechargeMoneyHandler.getOrderList': + { + if (!checkNaturalNumbers(msg.begin, msg.count)) return false; + if (msg.count < 0 && msg.count > 100) return false + break; + } + case 'activity.groupShopHandler.buy': + { + let { activityId, price, itemId, buyCnt } = msg; + if (!checkNaturalNumbers(activityId, price, itemId, buyCnt)) return false; + break; + } + case 'activity.forgeHandler.build': + { + let { activityId, id, material } = msg; + if (!checkNaturalNumbers(activityId, id)) return false; + if (!checkNaturalArray(material)) return false; + for (let { id, count } of material) { + if (!checkNaturalNumbers(id, count)) return false + } + break; + } + case 'activity.forgeHandler.buyCnt': + { + let { activityId, id, count } = msg; + if (!checkNaturalNumbers(activityId, id, count)) return false; + break; + } + case 'activity.miniGameHandler.gameStart': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.miniGameHandler.gameEnd': + { + let { activityId, gameCode, score } = msg; + if (!checkNaturalNumbers(activityId, score)) return false; + if (!checkNaturalStrings(gameCode)) return false; + break; + } + case 'activity.miniGameHandler.buyCnt': + { + let { activityId, count } = msg; + if (!checkNaturalNumbers(activityId, count)) return false; + break; + } + case 'activity.miniGameHandler.receiveBox': + { + let { activityId, boxId } = msg; + if (!checkNaturalNumbers(activityId, boxId)) return false; + break; + } + case 'activity.miniGameHandler.getRanks': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.weeklyFundHandler.sign': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; + break; + } + case 'activity.monthlyFundHandler.sign': + { + if (!checkNaturalNumbers(msg.activityId, msg.pageIndex, msg.dayIndex)) return false; + break; + } + case 'activity.rebateHandler.receiveReward': + { + if (!checkNaturalNumbers(msg.activityId, msg.day)) return false; + break; + } + case "battle.barrageHandler.getBarrageList": + { + if (!checkNaturalStrings(msg.rid)) return false; + break; + } + case "battle.barrageHandler.sendBarrage": + { + let { warId, rid, index, content } = msg; + if (!checkNaturalNumbers(warId)) return false; + if (!checkNaturalStrings(rid, index, content)) return false; + break; + } + case "comBattle.comBattleHandler.createTeam": + { + let { blueprtId, pub, ceLimit } = msg; + if (!checkNaturalNumbers(blueprtId, ceLimit)) return false; + if (!checkBoolean(pub)) return false; + break; + } + case "comBattle.comBattleHandler.searchTeam": + { + let { lv, magicWord } = msg; + if (!checkNumberArray(lv)) return false; + if (!!magicWord && magicWord != DEBUG_MAGIC_WORD) return false; + break; + } + case "comBattle.comBattleHandler.joinTeam": + { + if (!checkNaturalStrings(msg.teamCode)) return false; + if (!checkBoolean(msg.isFrd)) return false; + break; + } + case "comBattle.comBattleHandler.setFrdAssistance": + { + if (!checkNaturalStrings(msg.teamCode)) return false; + if (!checkBoolean(msg.isFrd)) return false; + break; + } + case "comBattle.comBattleHandler.setupHeroes": + { + let { teamCode, heroes, battleCode } = msg; + if (!checkNaturalStrings(teamCode, battleCode)) return false; + if (!checkNumberArray(heroes)) return false; + break; + } + case "comBattle.comBattleHandler.rmTeammate": + { + if (!checkNaturalStrings(msg.teamCode, msg.roleIdToRm)) return false; + break; + } + case "comBattle.comBattleHandler.dismiss": + case "comBattle.comBattleHandler.startBattle": + case "comBattle.comBattleHandler.autoInvite": + case "comBattle.comBattleHandler.comBattleEnd": + case "comBattle.comBattleHandler.getComBtlStatus": + { + if (!checkNaturalStrings(msg.teamCode)) return false; + break; + } + case "comBattle.comBattleHandler.action": + { + let { teamCode, bossHurts, killed, curRnd, timegap = 0, roundTime = 0 } = msg; + if (!checkNaturalStrings(teamCode)) return false; + if (!checkNumberArray(killed)) return false; + if (!checkNaturalNumbers(curRnd, timegap, roundTime)) return false; + if (!checkArrayCanEmpty(bossHurts)) return false; + for (let { hid, dataId, hurtHp } of bossHurts) { + if (hid && !checkNaturalNumbers(hid)) return false; + if (!checkNaturalNumbers(dataId)) return false; + if (!isNumber(hurtHp)) return false + } + break; + } + case "comBattle.comBattleHandler.getBlueprtCount": + { + if (!checkNumberArray(msg.ids)) return false; + break; + } + case "comBattle.comBattleHandler.sendTeamMsg": + { + let { teamCode, type, content, targetRoleId, targetMsgCode } = msg; + if (!checkNaturalStrings(teamCode, content)) return false; + if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; + if (!checkNaturalNumbers(type)) return false; + break; + } + case "comBattle.comBattleHandler.inviteTeammate": + { + if (!checkNaturalStrings(msg.teamCode, msg.targetRoleId)) return false; + break; + } + case "battle.dailyBattleHandler.buyNum": + { + if (!checkNaturalNumbers(msg.type, msg.count)) return false; + break; + } + case "battle.dungeonBattleHandler.buyNum": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "battle.dungeonBattleHandler.getFirstInfo": + { + if (!checkNaturalNumbers(msg.movePoint)) return false; + break; + } + case "battle.eventBattleHandler.checkAnswer": + { + let { eventId, eventCode, questionId, answer } = msg; + if (!checkNaturalNumbers(eventId, questionId, answer)) return false; + if (!checkNaturalStrings(eventCode)) return false; + break; + } + case "battle.eventBattleHandler.receiveEventReward": + { + if (!checkNaturalNumbers(msg.eventId)) return false; + if (!checkNaturalStrings(msg.eventCode)) return false; + break; + } + case "battle.expeditionBattleHandler.getEnemies": + { + if (!checkNaturalNumbers(msg.expeditionId)) return false; + if (!checkNaturalStrings(msg.expeditionCode)) return false; + break; + } + case "battle.expeditionBattleHandler.checkBattle": + { + let { expeditionCode, expeditionId, battleId, heroes } = msg; + if (!checkNaturalStrings(expeditionCode)) return false; + if (!checkNaturalNumbers(expeditionId, battleId)) return false; + if (!checkNumberArray(heroes)) return false + break; + } + case "battle.expeditionBattleHandler.battleEnd": + { + let { expeditionCode, expeditionId, battleCode, battleId, isSuccess, heroes, enemies, star, stars } = msg; + if (!checkNaturalStrings(expeditionCode, battleCode)) return false; + if (!checkNaturalNumbers(expeditionId, battleId)) return false; + if (!checkBoolean(isSuccess)) return false; + if (!checkExpeditionBattleHeroFormat(heroes, enemies)) return false; + if (!checkNumberArray(stars)) return false; + break; + } + case "battle.expeditionBattleHandler.pointReward": + { + if (!checkNaturalNumbers(msg.point)) return false; + break; + } + case "battle.expeditionBattleHandler.skipExpedition": + { + if (!checkNaturalStrings(msg.expeditionCode)) return false; + if (!checkNaturalNumbers(msg.expeditionId, msg.battleId)) return false; + break; + } + case "battle.normalBattleHandler.checkBattle": + { + let { battleId, heroes } = msg; + if (!checkNaturalNumbers(battleId)) return false; + if (!checkNumberArray(heroes)) return false + break; + } + case "battle.normalBattleHandler.getBattleList": + { + if (!checkNumberArray(msg.types)) return false; + break; + } + case "battle.normalBattleHandler.battleEnd": + { + let { battleCode, battleId, isSuccess, heroes, stars, activityId = 0, pageIndex = 0 } = msg; + if (!checkNaturalStrings(battleCode)) return false; + if (!checkNaturalNumbers(battleId, activityId, pageIndex)) return false; + if (!checkBoolean(isSuccess)) return false; + if (!checkNumberArray(heroes, stars)) return false; + break; + } + case "battle.normalBattleHandler.battleSweep": + { + if (!checkNaturalNumbers(msg.battleId, msg.count)) return false; + break; + } + case "battle.normalBattleHandler.saveScript": + { + if (!checkNaturalNumbers(msg.battleId, msg.type)) return false; + if (!checkNaturalStrings(msg.script)) return false; + break; + } + case "battle.normalBattleHandler.getScriptByBattle": + { + if (!checkNumberArray(msg.battleIds)) return false; + break; + } + case "battle.normalBattleHandler.getRegretCnt": + { + if (!checkNaturalNumbers(msg.warId)) return false; + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "battle.normalBattleHandler.incRegretCnt": + { + if (!checkNaturalNumbers(msg.warId, msg.count)) return false; + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "battle.normalBattleHandler.receiveChapterBox": + { + if (!checkNaturalNumbers(msg.chapter, msg.id, msg.warType)) return false; + break; + } + case "battle.normalBattleHandler.receiveWarReward": + { + if (!checkNaturalNumbers(msg.chapter, msg.warType)) return false; + break; + } + case "battle.normalBattleHandler.checkSkip": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "battle.pvpHandler.getOppPlayer": + case "battle.pvpHandler.getPlayerDetail": + { + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "battle.pvpHandler.pvpStart": + { + if (!checkNaturalNumbers(msg.warId)) return false; + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "battle.pvpHandler.pvpEnd": + { + let { battleCode, isSuccess, myHeroes, oppHeroes } = msg; + if (!checkNaturalStrings(battleCode)) return false; + if (!checkBoolean(isSuccess)) return false; + if (!checkPvpEndHeroFormat(myHeroes, oppHeroes)) return false + break; + } + case "battle.pvpHandler.buyAttackCnt": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "battle.pvpHandler.saveAttack": + case "battle.pvpHandler.saveAttackSub": + { + let { heroes } = msg; + if (!checkNaturalArray(heroes)) return false; + if (heroes.length > LINEUP_NUM) return false; + for (let { actorId, order } of heroes) { + if (!checkNaturalNumbers(actorId)) return false; + if (!checkNumberIfExist(order)) return false; + } + break; + } + case "battle.pvpHandler.saveDefense": + { + let { heroes, warId, buff, combo } = msg; + if (!checkNaturalArray(heroes)) return false; + if (!checkNaturalNumbers(warId, buff)) return false; + if (heroes.length > LINEUP_NUM) return false; + for (let { actorId, dataId, order, ai } of heroes) { + if (!checkNaturalNumbers(actorId, dataId, order, ai)) return false; + } + if (!checkCombo(combo)) return false + break; + } + case "battle.pvpHandler.receiveBox": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "battle.pvpHandler.buyChallengeCnt": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "battle.pvpHandler.sweep": + { + if (!checkNaturalNumbers(msg.warId)) return false; + if (!checkNaturalStrings(msg.oppRoleId)) return false; + break; + } + case "battle.ladderHandler.getOppLineup": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.rank)) return false; + break; + } + case "battle.ladderHandler.chooseOpp": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.rank, msg.myRank)) return false; + break; + } + case "battle.ladderHandler.chooseOpp": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.rank, msg.myRank)) return false; + break; + } + case "battle.ladderHandler.giveupCheck": + case "battle.ladderHandler.getOppData": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "battle.ladderHandler.checkBattle": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + if (!checkNaturalNumbers(msg.battleId)) return false; + if (!checkArrayCanEmpty(msg.heroes)) return false; + for (let { actorId, order } of msg.heroes) { + if (!checkNaturalNumbers(actorId, order)) return false; + } + break; + } + case "battle.ladderHandler.battleEnd": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case "battle.ladderHandler.battleSweep": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.rank, msg.count)) return false; + break; + } + case "battle.ladderHandler.saveDefense": + { + if (!checkNaturalNumbers(msg.warId)) return false; + if (!checkArrayCanEmpty(msg.heroes)) return false; + for (let { actorId, dataId, order } of msg.heroes) { + if (!checkNaturalNumbers(actorId, dataId, order)) return false; + } + if (!checkCombo(msg.combo)) return false + break; + } + case "battle.ladderHandler.buyCnt": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "battle.towerBattleHandler.resetLv": + { + if (!checkNaturalNumbers(msg.towerLv)) return false; + break; + } + case "battle.towerBattleHandler.skipTower": + { + if (!checkNaturalNumbers(msg.toLv)) return false; + break; + } + case "battle.towerBattleHandler.hangUpSpeedUp": + { + if (!checkNaturalNumbers(msg.speedUpCnt)) return false; + break; + } + case "battle.towerBattleHandler.sendTaskHero": + { + let { batchCode, tasks } = msg; + if (!checkStringIfExist(batchCode)) return false; + if (!checkNaturalArray(tasks)) return false; + for (let { taskCode, heroes } of tasks) { + if (!checkNaturalStrings(taskCode)) return false; + if (!checkNumberArray(heroes)) return false; + } + break; + } + case "battle.towerBattleHandler.settleTask": + { + if (!checkStringIfExist(msg.batchCode, msg.taskCode)) return false; + break; + } + case "battle.towerBattleHandler.receiveBox": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + + case "battle.rougeHandler.getData": + break; + case "battle.rougeHandler.getGame": + break; + + case "battle.rougeHandler.getInitCharaCard": + { + let { type, grade } = msg + if (!checkNaturalNumbers(type, grade)) return false; + break; + } + case "battle.rougeHandler.refreshInitCharaCard": + { + let { gameCode } = msg + if (!checkNaturalStrings(gameCode)) return false; + break; + } + case "battle.rougeHandler.startGame": + { + let { gameCode, authorType } = msg; + if (!checkNaturalStrings(gameCode)) return false; + if (!checkNaturalNumbers(authorType)) return false; + break; + } + + case "battle.rougeHandler.gameEnd": + { + let { gameCode } = msg; + if (!checkNaturalStrings(gameCode)) return false; + break; + } + + case "battle.rougeHandler.chooseNode": + { + let { gameCode, layer, detailCode } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkNaturalNumbers(layer)) return false; + break; + } + + case "battle.rougeHandler.checkBattle": + { + let { gameCode, detailCode, warId, charaCodes } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkNaturalNumbers(warId)) return false; + if (!checkIsDuplicateStrings(charaCodes)) return false; + break; + } + + case "battle.rougeHandler.battleEnd": + { + let { gameCode, detailCode, battleCode, warId, status, round, rougeDamage } = msg; + if (!checkNaturalStrings(gameCode, detailCode, battleCode)) return false; + if (!checkNaturalNumbers(warId, round, status)) return false; + // if (!checkBooleanIfExist(isAp, isRound)) return false; + if (!isArray(rougeDamage) || rougeDamage.length == 0) return false; + let charaCodes: string[] = []; + for (let { charaCode } of rougeDamage) { + if (!charaCode) return false; + charaCodes.push(charaCode); + } + if (!checkIsDuplicateStrings(charaCodes)) return false; + break; + } + + case "battle.rougeHandler.chooseReward": + { + let { gameCode, detailCode, groupIndex, optionIndexs } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkNaturalNumbers(groupIndex)) return false; + if (!checkIsDuplicateNumbers(optionIndexs)) return false; + break; + } + case "battle.rougeHandler.reRandomReward": + { + let { gameCode, detailCode, rewardType } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkNaturalNumbers(rewardType)) return false; + break; + } + case "battle.rougeHandler.shopBuy": + { + let { gameCode, detailCode, optionIndex } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkNaturalNumbers(optionIndex)) return false; + break; + } + + case "battle.rougeHandler.chooseOption": + { + let { gameCode, detailCode, eventOptions } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + if (!checkIsDuplicateNumbers(eventOptions)) return false; + break; + } + + case "battle.rougeHandler.recovery": + { + let { gameCode, detailCode } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + break; + } + + case "battle.rougeHandler.trainCard": + { + let { gameCode, detailCode, cardCode } = msg; + if (!checkNaturalStrings(gameCode, detailCode, cardCode)) return false; + break; + } + case "battle.rougeHandler.nodeEnd": + { + let { gameCode, detailCode, } = msg; + if (!checkNaturalStrings(gameCode, detailCode)) return false; + break; + } + + case "battle.rougeHandler.putOnOrOffCard": + { + let { gameCode, charaCode, cards } = msg; + if (!checkNaturalStrings(gameCode, charaCode)) return false; + let cardCodes: string[] = [], indexs: number[] = []; + for (let { index, cardCode } of cards) { + indexs.push(index); + if (cardCode) cardCodes.push(cardCode); + } + if (!checkIsDuplicateNumbers(indexs)) return false; + if (!checkIsDuplicateStrings(cardCodes)) return false; + + break; + } + + case "battle.rougeHandler.exchangeChara": + { + let { gameCode, oldCharaCode, newCharaCode } = msg; + if (!checkNaturalStrings(gameCode, oldCharaCode, newCharaCode)) return false; + break; + } + case "battle.rougeHandler.challengeRandom": + { + let { detailCode } = msg; + if (!checkNaturalStrings(detailCode)) return false; + break; + } + case "battle.rougeHandler.unlockTech": + { + if (!checkNaturalNumbers(msg.techId)) return false; + break; + } + + case "battle.rougeHandler.putOnCircle": + { + if (!checkNaturalNumbers(msg.circleId, msg.hid)) return false; + break; + } + case "battle.rougeHandler.chooseSkillCard": + { + if (!checkNaturalStrings(msg.gameCode, msg.charaCode)) return false; + if (!checkNaturalNumbers(msg.skillType, msg.id)) return false; + break; + } + case "battle.rougeHandler.receiveCollectionReward": + { + if (!checkNaturalNumbers(msg.type, msg.id)) return false; + break; + } + case "battle.rougeHandler.receiveScore": + { + if (!checkNaturalNumbers(msg.index)) return false; + break; + } + case "battle.friendBattleHandler.getFriendOpp": + { + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "chat.chatHandler.sendGroupMessage": + { + let { channel, type, content, targetRoleId, targetMsgCode } = msg; + if (!checkNaturalNumbers(type) || !checkIsInEnum(MSG_TYPE, type)) return false; + if (!checkNaturalStrings(channel)) return false; + if (type == MSG_TYPE.IMG) { + if (!checkNaturalNumbers(content)) return false; + } else { + if (!checkNaturalStrings(content)) return false; + } + if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; + break; + } + case "chat.chatHandler.sendPrivateMessage": + { + let { type, content, targetRoleId, targetMsgCode } = msg; + if (!checkNaturalNumbers(type) || !checkIsInEnum(MSG_TYPE, type)) return false; + if (type == MSG_TYPE.IMG) { + if (!checkNaturalNumbers(content)) return false; + } else { + if (!checkNaturalStrings(content)) return false; + } + if (!checkStringIfExist(targetRoleId, targetMsgCode)) return false; + break; + } + case "chat.chatHandler.getPrivateMessage": + { + let { targetRoleId, fromSeqId, count } = msg; + if (!checkNaturalStrings(targetRoleId)) return false; + if (!checkNumberIfExist(fromSeqId)) return false; + if (!checkNaturalNumbers(count)) return false; + if (count < 0 || count > 1000) return false; + break; + } + case "chat.chatHandler.readPrivateMessage": + case "chat.chatHandler.delPrivateMessage": + { + if (!checkNaturalStrings(msg.targetRoleId)) return false; + break; + } + case "chat.chatHandler.setPrivateMessageTop": + { + if (!checkNaturalStrings(msg.targetRoleId)) return false; + if (!checkBoolean(msg.isTop)) return false; + break; + } + case "chat.chatHandler.accuse": + { + if (!checkStringIfExist(msg.targetRoleId, msg.targetMsgCode)) return false; + if (!checkNumberIfExist(msg.reason)) return false; + break; + } + case "connector.entryHanddler.enter": + { + if (!checkNaturalStrings(msg.token)) return false; + if (!checkNaturalNumbers(msg.serverId)) return false; + break; + } + case "connector.entryHandler.gmEnter": + { + if (!checkNaturalStrings(msg.token)) return false; + break; + } + case "gm.gmHandler.sendSingleMail": + case "gm.gmHandler.sendSingleMailTxt": + case "gm.gmHandler.sendServerMail": + case "gm.gmHandler.sendServerMailTxt": + { + if (!checkNaturalStrings(msg.id)) return false; + if (!checkBoolean(msg.isPass)) return false; + break; + } + case "gm.gmHandler.reloadResource": + { + break; + } + case "gm.gmHandler.updateActivity": + { + let { groupId, beginTime, endTime, type, data, timeType, days, delayDay, interval, name, hideDayByServer, effectDay } = msg; + if (!checkNumberIfExist(groupId, beginTime, endTime, type, timeType, days, delayDay, interval, hideDayByServer, effectDay)) return false + if (!checkStringIfExist(data, name)) return false; + break; + } + case "gm.gmHandler.switchActivity": + { + let { activityId, isEnable } = msg; + if (!checkNaturalNumbers(activityId)) return false; + if (!checkBoolean(isEnable)) return false; + break; + } + case "gm.gmHandler.deleteActivity": + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case "gm.gmHandler.updateActivityGroup": + { + let { groupId, groupName, serverIds, activityIds, groupType } = msg; + if (!checkNaturalNumbers(groupId, groupType)) return false; + if (!checkNaturalStrings(groupName)) return false; + if (!checkNumberArray(serverIds, activityIds)) return false; + break; + } + case "gm.gmHandler.saveSingleActivityToGroup": + { + let { groupId, index, activityId } = msg; + if (!checkNaturalNumbers(groupId, index, activityId)) return false; + break; + } + case "gm.gmHandler.setGuildActivityDebug": + { + let { aid, day, startActivity = 0, endActivity = 0, startGuildAuction = 0, endGuildAuction = 0, startWorldAuction = 0, endWorldAuction = 0, startNextDay = 0 } = msg; + if (!checkNaturalNumbers(aid, day, startActivity, endActivity, startGuildAuction, endGuildAuction, startWorldAuction, endWorldAuction, startNextDay)) return false; + break; + } + case "gm.gmHandler.cancelGuildActivityDebug": + case "gm.gmHandler.taflus": + { + break; + } + case "gm.gmHandler.updateSurvey": + { + let { code, surveyId, beginTime, endTime, isEnable, surveyLink, surveyName, roleIndex, goods, mailContent } = msg; + if (!checkNaturalStrings(code, surveyId, surveyLink, surveyName, goods, mailContent)) return false; + if (!checkStringIfExist(surveyName)) return false + if (!checkNaturalNumbers(beginTime, endTime, roleIndex)) return false; + if (!checkBoolean(isEnable)) return false; + break; + } + case "gm.gmHandler.deleteSurvey": + { + if (!checkNaturalStrings(msg.code)) return false; + break; + } + case "gm.gmOrderHandler.getActivitiesCanBuy": + { + if (!checkNaturalNumbers(msg.serverId)) return false; + break; + } + case "gm.gmOrderHandler.applyOrder": + { + let { serverId, activityId, receiver } = msg; + if (!checkNaturalNumbers(serverId)) return false; + if (!checkNaturalArray(activityId)) return false; + if (!checkNaturalNumbers(activityId[1])) return false; + if (!checkNaturalStrings(activityId[2])) return false; + if (!checkNaturalArray(receiver)) return false; + for (let { env, serverId, roleId, roleName } of receiver) { + if (!checkNaturalStrings(env)) return false; + if (!checkNaturalNumbers(serverId)) return false; + if (!checkStringIfExist(roleId, roleName)) return false; + } + break; + } + case "gm.gmRoleHandler.addItems": + case "gm.gmRoleHandler.deleteHero": + case "gm.gmRoleHandler.dismissGuild": + case "gm.gmRoleHandler.handleBlock": + case "gm.gmRoleHandler.setGuildLeader": + case "gm.gmRoleHandler.setHero": + case "gm.gmRoleHandler.skipEpilogue": + case "gm.gmRoleHandler.updateGuild": + case "gm.gmServerHandler.cancelMarquee": + case "gm.gmServerHandler.createNewServer": + case "gm.gmServerHandler.saveRegionConf": + case "gm.gmServerHandler.sendMarquee": + case "gm.gmServerHandler.startMaintenance": + case "gm.gmServerHandler.startRegionMaintenance": + case "gm.gmServerHandler.stopMaintenance": + case "gm.gmServerHandler.stopRegionMaintenance": + { + break; + } + case "guild.auctionHandler.getAuction": + case "guild.auctionHandler.leaveAuction": + { + if (!!msg.magicWord && msg.magicWord != DEBUG_MAGIC_WORD) return false; + break; + } + case "guild.auctionHandler.offer": + { + const { code, max, auctionStage, magicWord } = msg; + if (!checkNaturalStrings(code)) return false; + if (!checkBoolean(max)) return false; + if (!checkNaturalNumbers(auctionStage)) return false; + if (!!magicWord && magicWord != DEBUG_MAGIC_WORD) return false; + break; + } + case "guild.auctionHandler.unWatchLot": + case "guild.auctionHandler.watchLot": + case "guild.auctionHandler.getDividend": + { + if (!checkNaturalStrings(msg.code)) return false; + break; + } + case "guild.auctionHandler.offerRecs": + case "guild.auctionHandler.guildLotRecs": + { + if (!checkNaturalNumbers(msg.count)) return false; + if (msg.count < 0 || msg.count > 1000) return false; + break; + } + case "guild.cityActivityHandler.getCityStatus": + case "guild.cityActivityHandler.declareCity": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + break; + } + case "guild.cityActivityHandler.checkBattle": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + if (!checkNumberArray(msg.heroes)) return false; + break; + } + case "guild.cityActivityHandler.hitGate": + { + let { cityId, code, damage, hid, round, timegap = 0, roundTime = 0 } = msg; + if (!checkNaturalNumbers(cityId, damage, hid, round, timegap, roundTime)) return false; + if (!checkNaturalStrings(code)) return false; + break; + } + case "guild.cityActivityHandler.battleEnd": + { + let { cityId, code, isSuccess } = msg; + if (!checkNaturalNumbers(cityId)) return false; + if (!checkNaturalStrings(code)) return false; + if (!checkBoolean(isSuccess)) return false; + break; + } + case "guild.donateHandler.donate": + case "guild.donateHandler.receiveBox": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "guild.gateActivityHandler.checkBattle": + { + if (!checkNumberArray(msg.heroes)) return false; + break; + } + case "guild.gateActivityHandler.action": + { + let { code, round, record } = msg; + if (!checkNaturalStrings(code)) return false; + if (!checkNaturalNumbers(round)) return false; + if (!checkArrayCanEmpty(record)) return false; + for (let { round, dataId } of record) { + if (!checkNaturalNumbers(round, dataId)) return false; + } + break; + } + case "guild.gateActivityHandler.battleEnd": + { + let { code, isSuccess } = msg; + if (!checkNaturalStrings(code)) return false; + if (!checkBoolean(isSuccess)) return false; + break; + } + case "guild.guildBossHandler.getBossInstanceByBattleCode": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "guild.guildBossHandler.action": + { + if (!checkNaturalStrings(msg.bossCode, msg.battleCode)) return false; + if (!checkNaturalNumbers(msg.damage)) return false; + break; + } + case "guild.guildBossHandler.battleBossEnd": + { + if (!checkNaturalStrings(msg.bossCode, msg.battleCode)) return false; + break; + } + case "guild.guildBossHandler.encourage": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "guild.guildHandler.createGuild": + { + let { name, icon, notice } = msg; + if (!checkNaturalStrings(name)) return false; + if (!checkNaturalNumbers(icon)) return false; + if (!checkStringIfExist(notice)) return false; + break; + } + case "guild.guildHandler.getGuildList": + { + let { page = 1, showPeopleMax, name } = msg; + if (!checkStringIfExist(name)) return false; + if (!checkNaturalNumbers(page)) return false; + if (!checkBoolean(showPeopleMax)) return false; + break; + } + case "guild.guildHandler.setGuildInfo": + { + let { code, name, notice, introduce, ceLimit, isAuto, icon } = msg; + if (!checkNaturalStrings(code)) return false; + if (!checkStringIfExist(name, notice, introduce)) return false; + if (!checkNumberIfExist(ceLimit, icon)) return false; + if (!checkBooleanIfExist(isAuto)) return false; + break; + } + case "guild.guildHandler.getGuildInfo": + case "guild.guildHandler.applyGuild": + case "guild.guildHandler.dismiss": + case "guild.guildHandler.quit": + case "guild.guildHandler.getRec": + { + if (!checkNaturalStrings(msg.code)) return false; + break; + } + case "guild.guildHandler.setAuth": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.auth)) return false; + if (!checkIsInEnum(GUILD_AUTH, msg.auth)) return false; + break; + } + case "guild.guildHandler.getApplyList": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkStringIfExist(msg.lastApplyCode)) return false; + break; + } + case "guild.guildHandler.receiveApply": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkStringArray(msg.applyCodeList)) return false; + if (!checkBoolean(msg.isReceived)) return false; + break; + } + case "guild.guildHandler.inviteMember": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkStringArray(msg.roleIds)) return false; + break; + } + case "guild.guildHandler.getInvitationList": + { + if (!checkStringIfExist(msg.lastApplyCode)) return false; + break; + } + case "guild.guildHandler.receiveInvitation": + { + if (!checkStringIfExist(msg.lastApplyCode)) return false; + if (!checkBoolean(msg.isReceived)) return false; + break; + } + case "guild.guildHandler.getGuildMember": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkStringIfExist(msg.sort)) return false; + break; + } + case "guild.guildHandler.kick": + case "guild.guildHandler.impeach": + { + if (!checkNaturalStrings(msg.code, msg.roleId)) return false; + break; + } + case "guild.guildHandler.upStructure": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkNaturalNumbers(msg.id)) return false; + if (!checkIsInEnum(GUILD_STRUCTURE, msg.id)) return false; + break; + } + case "guild.guildHandler.sendMail": + case "guild.guildHandler.recruit": + { + if (!checkNaturalStrings(msg.code, msg.info)) return false; + break; + } + case "guild.guildHandler.receiveActiveBox": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "guild.guildRefineHandler.refine": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "guild.guildRefineHandler.lightUpTree": + case "guild.guildRefineHandler.assistRefine": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "guild.guildTrainHandler.trainBattleStart": + { + let { hid, difficulty, trainId, battleId } = msg; + if (!checkNaturalNumbers(hid, difficulty, trainId, battleId)) return false; + break; + } + case "guild.guildTrainHandler.trainBattleEnd": + { + let { battleCode, isSuccess } = msg; + if (!checkNaturalStrings(battleCode)) return false; + if (!checkBoolean(isSuccess)) return false; + break; + } + case "guild.guildTrainHandler.trainBattleSweep": + { + let { hid, difficulty, trainId, battleId } = msg; + if (!checkNaturalNumbers(hid, difficulty, trainId, battleId)) return false; + break; + } + case "guild.guildTrainHandler.getTrainInstanceBox": + { + let { trainId, hid, index } = msg; + if (!checkNaturalNumbers(trainId, hid, index)) return false; + break; + } + case "guild.guildTrainHandler.getTrainLvUpRewards": + { + if (!checkNaturalNumbers(msg.trainId)) return false; + break; + } + case "guild.guildTrainHandler.purchaseTrainCount": + { + if (!checkNaturalNumbers(msg.count)) return false; + break; + } + case "guild.raceActivityHandler.useItem": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + if (!checkNaturalStrings(msg.toGuild)) return false; + break; + } + case "guild.raceActivityHandler.battleEnd": + { + if (!checkNaturalStrings(msg.code)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case "guild.wishPoolHandler.wishGoods": + { + if (!checkNaturalNumbers(msg.goodId, msg.type)) return false; + break; + } + case "guild.wishPoolHandler.donateGoods": + { + if (!checkNaturalStrings(msg.wishRoleId, msg.id)) return false; + break; + } + case "guild.wishPoolHandler.receiveGoods": + { + if (!checkNaturalStrings(msg.id)) return false; + break; + } + case "guild.gvgHandler.chooseJob": + { + if (msg.job != LEAGUE_JOB.FIGHTER && msg.job != LEAGUE_JOB.PRODUCER) return false; + break; + } + case "guild.gvgHandler.receiveBox": + { + if (!checkNaturalNumbers(msg.boxId)) return false; + break; + } + case "guild.gvgHandler.receiveLvReward": + { + if (!checkNaturalNumbers(msg.lv)) return false; + break; + } + case "guild.gvgHandler.receiveLvReward": + { + if (!checkNaturalNumbers(msg.receiveTask)) return false; + break; + } + case "guild.gvgHandler.unlockTech": + { + if (!checkNaturalNumbers(msg.techId)) return false; + break; + } + case "guild.gvgHandler.activate": + { + if (!checkNaturalNumbers(msg.techId, msg.battleFeats)) return false; + break; + } + case "guild.gvgManageHandler.createLeague": + { + let { name, icon, notice } = msg; + if (!checkNaturalStrings(name)) return false; + if (!checkStringIfExist(notice)) return false; + if (!checkNaturalNumbers(icon)) return false; + break; + } + case "guild.gvgManageHandler.getLeagues": + case "guild.gvgManageHandler.getInviteGuilds": + { + let { name, page } = msg; + if (!checkStringIfExist(name)) return false; + if (!checkNumberIfExist(page)) return false; + break; + } + case "guild.gvgManageHandler.getLeagueInfo": + case "guild.gvgManageHandler.getGuilds": + case "guild.gvgManageHandler.getMembers": + case "guild.gvgManageHandler.dismiss": + case "guild.gvgManageHandler.getCandidate": + { + if (!checkNaturalStrings(msg.leagueCode)) return false; + break; + } + case "guild.gvgManageHandler.applyLeague": + { + if (!checkStringArray(msg.leagueCodes)) return false; + break; + } + case "guild.gvgManageHandler.handleApply": + { + if (!checkNaturalStrings(msg.guildCode)) return false; + if (!checkBoolean(msg.isReceive)) return false; + break; + } + case "guild.gvgManageHandler.inviteGuild": + { + if (!checkStringArray(msg.guildCodes)) return false; + break; + } + case "guild.gvgManageHandler.handleInvitation": + { + if (!checkNaturalStrings(msg.leagueCode)) return false; + if (!checkBoolean(msg.isReceive)) return false; + break; + } + case "guild.gvgManageHandler.kick": + case "guild.gvgManageHandler.quit": + { + if (!checkNaturalStrings(msg.guildCode)) return false; + break; + } + case "guild.gvgManageHandler.abdicate": + { + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "guild.gvgManageHandler.setLeagueInfo": + { + if (!checkNaturalStrings(msg.leagueCode)) return false; + if (!checkStringIfExist(msg.name, msg.notice)) return false; + if (!checkNumberIfExist(msg.icon)) return false; + break; + } + case "guild.gvgManageHandler.sendMail": + case "guild.gvgManageHandler.recruit": + { + if (!checkNaturalStrings(msg.content)) return false; + break; + } + case "guild.gvgProduceHandler.exchangeItem": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "guild.gvgProduceHandler.getProduceList": + { + if (!checkIsInEnum(GVG_RESOURCE_TYPE, msg.type)) return false; + break; + } + case "guild.gvgProduceHandler.getOtherFarms": + case "guild.gvgProduceHandler.getMyFarm": + case "guild.gvgProduceHandler.getOtherMines": + { + if (!checkNaturalNumbers(msg.farmId)) return false; + break; + } + case "guild.gvgProduceHandler.plant": + { + if (!checkNaturalNumbers(msg.farmId)) return false; + if (!checkArrayCanEmpty(msg.seeds)) return false; + for (let { fieldId, seedType, index } of msg.seeds) { + if (!checkNaturalNumbers(fieldId, seedType, index)) return false; + if (!checkIsInEnum(GVG_SEED_TYPE, seedType)) return false; + } + break; + } + case "guild.gvgProduceHandler.harvest": + { + if (!checkNaturalNumbers(msg.farmId)) return false; + if (!checkNumberArray(msg.fieldIds)) return false; + break; + } + case "guild.gvgProduceHandler.plantEnd": + { + if (!checkNaturalNumbers(msg.farmId)) return false; + break; + } + case "guild.gvgProduceHandler.helpHarvest": + { + if (!checkNaturalNumbers(msg.farmId)) return false; + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "guild.gvgProduceHandler.mineStart": + case "guild.gvgProduceHandler.forestryStart": + { + if (!checkNaturalNumbers(msg.farmId, msg.itemId)) return false; + break; + } + case "guild.gvgProduceHandler.mineEnd": + { + if (!checkNaturalNumbers(msg.farmId, msg.fieldId)) return false; + if (!checkArrayCanEmpty(msg.result)) return false; + for (let { type, count } of msg.result) { + if (!checkNaturalNumbers(type, count)) return false; + } + break; + } + case "guild.gvgProduceHandler.forestryEnd": + { + if (!checkNaturalNumbers(msg.farmId, msg.fieldId, msg.result)) return false; + break; + } + case "guild.gvgFightHandler.getVestige": + case "guild.gvgFightHandler.refreshOpp": + case "guild.gvgFightHandler.getRec": + case "guild.gvgFightHandler.getPlayerRank": + + + { + if (!checkNaturalNumbers(msg.vestigeId)) return false; + break; + } + case "guild.gvgFightHandler.saveLineup": + { + if (!checkNaturalNumbers(msg.vestigeId)) return false; + if (!checkArrayCanEmpty(msg.lineup)) return false; + for (let { actorId, dataId, order } of msg.lineup) { + if (!checkNaturalNumbers(actorId, dataId, order)) return false; + } + break; + } + case "guild.gvgFightHandler.getOppLineup": + { + if (!checkNaturalNumbers(msg.vestigeId, msg.rank)) return false; + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "guild.gvgFightHandler.chooseOpp": + { + if (!checkNaturalNumbers(msg.vestigeId, msg.rank, msg.myRank)) return false; + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "guild.gvgFightHandler.giveupCheck": + case "guild.gvgFightHandler.getOppData": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + break; + } + case "guild.gvgFightHandler.checkBattle": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + if (!checkArrayCanEmpty(msg.heroes)) return false; + for (let { actorId, dataId, order } of msg.heroes) { + if (!checkNaturalNumbers(actorId, dataId, order)) return false; + } + break; + } + case "guild.gvgFightHandler.battleEnd": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case "guild.gvgBattleHandler.saveTeam": + { + if (!checkNaturalNumbers(msg.index, msg.head, msg.frame, msg.spine)) return false; + if (msg.lineup) { + for (let { actorId, dataId, order } of msg.lineup) { + if (!checkNaturalNumbers(actorId, dataId, order)) return false; + } + } + break; + } + case "guild.gvgBattleHandler.getCity": + case "guild.gvgBattleHandler.enterCity": + case "guild.gvgBattleHandler.leaveCity": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + break; + } + case "guild.gvgBattleHandler.startMove": + case "guild.gvgBattleHandler.stopMove": + { + if (!checkNaturalNumbers(msg.cityId, msg.areaId)) return false; + if (!checkNaturalStrings(msg.teamCode)) return false; + break; + } + case "guild.gvgBattleHandler.teamSettle": + { + if (!checkNaturalNumbers(msg.cityId, msg.areaId, msg.pointId)) return false; + if (!checkNaturalStrings(msg.teamCode)) return false; + break; + } + case "guild.gvgBattleHandler.teamLeave": + { + //TODO + break; + } + case "guild.gvgBattleHandler.battleStart": + { + if (!checkNaturalStrings(msg.teamCode, msg.oppoTeamCode)) return false; + break; + } + case "guild.gvgBattleHandler.battleEnd": + { + if (!checkNaturalStrings(msg.battleCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + if (!checkGvgEndHeroFormat(msg.myHeroes)) return false; + if (!checkGvgEndHeroFormat(msg.oppHeroes)) return false; + break; + } + case "guild.gvgBattleHandler.useItem": + { + if (!checkNaturalNumbers(msg.cityId, msg.itemId)) return false; + if (!checkNaturalStrings(msg.teamCode, msg.oppoTeamCode)) return false; + break; + } + case "guild.gvgBattleHandler.reviveTeam": + { + if (!checkNaturalStrings(msg.teamCode)) return false; + break; + } + case "guild.gvgBattleHandler.getRecs": + { + if (!checkNaturalNumbers(msg.type)) return false; + break; + } + case "guild.gvgBattleHandler.getOverview": + { + break; + } + case "guild.gvgBattleHandler.getAreaTeams": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + if (!checkNumberArray(msg.areaIds)) return false; + break; + } + case "guild.gvgBattleHandler.setTargetCity": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + if (!checkBoolean(msg.isTarget)) return false; + break; + } + case "guild.gvgBattleHandler.getAreaTeams": + { + if (!checkStringIfExist(msg.notice)) return false; + break; + } + case "guild.gvgBattleHandler.getOppTeam": + { + if (!checkNaturalNumbers(msg.cityId)) return false; + if (!checkNaturalStrings(msg.teamCode)) return false; + break; + } + case "order.orderHandler.applyOrder": + { + let { productID, payType, activityId, paramStr, useVoucher } = msg; + if (!checkNaturalNumbers(payType, activityId, useVoucher)) return false; + if (!checkNaturalStrings(productID)) return false; + if (!checkStringIfExist(paramStr)) return false; + break; + } + case "order.orderHandler.checkOrder": + { + if (!checkNaturalStrings(msg.localOrderID)) return false; + break; + } + case "role.equipHandler.composeEquip": + case "role.equipHandler.putOffJewel": + { + if (!checkNaturalNumbers(msg.hid, msg.ePlaceId)) return false; + break; + } + case "role.equipHandler.strengthen": + case "role.equipHandler.qualityUp": + case "role.equipHandler.starUp": + { + if (!checkNaturalNumbers(msg.hid, msg.ePlaceId)) return false; + if (!checkBoolean(msg.isOneClick)) return false; + break; + } + case "role.equipHandler.strengthenAll": + { + if (!checkNaturalNumbers(msg.hid, msg.lv)) return false; + break; + } + case "role.equipHandler.putOnJewel": + { + if (!checkNaturalNumbers(msg.hid, msg.ePlaceId, msg.jewel)) return false; + break; + } + case "role.equipHandler.putOnOrOffStone": + { + if (!checkNaturalNumbers(msg.hid, msg.ePlaceId, msg.stonesId, msg.gid)) return false; + break; + } + case "role.equipHandler.lockRandSe": + { + if (!checkNaturalNumbers(msg.seqId, msg.randSeId, msg.type)) return false; + if (msg.type != 0 && msg.type != 1) return false; + break; + } + case "role.equipHandler.previewRandSe": + case "role.equipHandler.resetRandSe": + case "role.equipHandler.giveupPreview": + case "role.equipHandler.quench": + { + if (!checkNaturalNumbers(msg.seqId)) return false; + break; + } + case "role.equipHandler.chooseQuench": + { + if (!checkNaturalNumbers(msg.seqId, msg.randSeId)) return false; + break; + } + case "role.equipHandler.decomposeItem": + { + if (!checkNaturalArray(msg.origin)) return false; + for (let { id, count } of msg.origin) { + if (!checkNaturalNumbers(id, count)) return false; + } + break; + } + case "role.equipHandler.decomposeJewel": + { + if (!checkNumberArray(msg.origin)) return false; + break; + } + case "role.equipHandler.composeStone": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "role.equipHandler.composeStoneByItId": + { + if (!checkNaturalNumbers(msg.itId)) return false; + break; + } + case "role.equipHandler.inheritJewel": + { + if (!checkNaturalNumbers(msg.originJewel, msg.targetJewel)) return false; + break; + } + case "role.artifactHandler.putOn": + { + if (!checkSeqId(msg.seqId)) return false; + if (!checkNaturalNumbers(msg.hid)) return false; + break; + } + case "role.artifactHandler.putOff": + { + if (!checkSeqId(msg.seqId)) return false; + break; + } + case "role.artifactHandler.lvUp": + { + if (!checkSeqId(msg.seqId)) return false; + if (!checkBoolean(msg.isOneClick)) return false; + break; + } + case "role.artifactHandler.compose": + { + if (!checkSeqId(msg.seqId)) return false; + if (!checkSeqId(...msg.material)) return false; + if (!checkArrayCanEmpty(msg.generalItems)) return false; + for (let { id, count } of msg.generalItems) { + if (!checkNaturalNumbers(id, count)) return false; + } + break; + } + case "role.artifactHandler.transfer": + { + if (!checkSeqId(msg.seqId)) return false; + if (!checkNaturalNumbers(msg.type)) return false; + break; + } + case "role.artifactHandler.previewRebuild": + case "role.artifactHandler.rebuild": + case "role.artifactHandler.decompose": + { + if (!checkSeqId(...msg.seqIds)) return false; + break; + } + case "role.friendHandler.searchUser": + { + if (!checkNaturalStrings(msg.value)) return false; + break; + } + case "role.friendHandler.applyFriend": + { + if (!checkStringArray(msg.roleIds)) return false; + break; + } + case "role.friendHandler.handleApply": + { + if (!checkStringArray(msg.applyCodeList)) return false; + if (!checkBoolean(msg.isPass)) return false; + break; + } + case "role.friendHandler.setBlackList": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalNumbers(msg.type)) return false; + if (!checkIsInEnum(BLOCK_OPEATE, msg.type)) return false; + break; + } + case "role.friendHandler.sendHeart": + case "role.friendHandler.receiveHeart": + { + if (!checkStringIfExist(msg.roleId)) return false; + break; + } + case "role.friendHandler.getPlayerSimpleInfo": + case "role.friendHandler.getPlayerDetail": + { + if (!checkNaturalStrings(msg.roleId)) return false; + break; + } + case "role.friendHandler.sendPresent": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNaturalArray(msg.items)) return false; + for (let { id, count } of msg.items) { + if (!checkNaturalNumbers(id, count)) return false; + } + break; + } + case "role.friendHandler.getHeroDetail": + { + if (!checkNaturalStrings(msg.roleId)) return false; + if (!checkNumberArray(msg.hids)) return false; + break; + } + case "role.heroHandler.compose": + { + if (!checkNaturalNumbers(msg.hid)) return false; + break; + } + case "role.heroHandler.lvUp": + { + if (!checkNaturalNumbers(msg.hid, msg.type)) return false; + break; + } + case "role.heroHandler.starUp": + { + let { hid, star, starStage, isOneClick } = msg; + if (!checkNaturalNumbers(hid, star, starStage)) return false; + if (!checkBoolean(isOneClick)) return false; + break; + } + case "role.heroHandler.qualityUp": + { + let { hid, quality } = msg; + if (!checkNaturalNumbers(hid, quality)) return false; + break; + } + case "role.heroHandler.wakeUp": + { + let { hid, colorStar, colorStarStage, isOneClick } = msg; + if (!checkNaturalNumbers(hid, colorStar, colorStarStage)) return false; + if (!checkBoolean(isOneClick)) return false; + break; + } + case "role.heroHandler.heroJobTrain": + { + let { hid, isOneClick, canReplace } = msg; + if (!checkNaturalNumbers(hid)) return false; + if (!checkBoolean(isOneClick, canReplace)) return false; + break; + } + case "role.heroHandler.heroJobStageUp": + { + if (!checkNaturalNumbers(msg.hid)) return false; + break; + } + case "role.heroHandler.heroGiveFavor": + { + if (!checkNaturalNumbers(msg.hid, msg.shipId, msg.type)) return false; + break; + } + case "role.heroHandler.heroWearSkin": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "role.heroHandler.previewRebirth": + case "role.heroHandler.rebirth": + case "role.heroHandler.resetTalent": + { + if (!checkNaturalNumbers(msg.hid)) return false; + break; + } + case "role.heroHandler.unlockTalent": + case "role.heroHandler.upgradeTalent": + { + if (!checkNaturalNumbers(msg.hid, msg.id)) return false; + break; + } + case "role.heroHandler.heroReborn": + { + const { originHid, targetHid } = msg; + if (originHid == targetHid) return false; + if (!checkNaturalNumbers(originHid, targetHid)) return false; + break; + } + case "role.itemHandler.useItem": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + if (!checkNumberArray(msg.selected)) return false; + break; + } + case "role.itemHandler.useApItem": + case "role.itemHandler.buyApItem": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "role.itemHandler.useGiftCode": + { + if (!checkNaturalStrings(msg.code)) return false; + break; + } + case "role.itemHandler.getApByLv": + { + if (!checkNaturalNumbers(msg.lv)) return false; + break; + } + case "role.itemHandler.exchangeSpirit": + { + if (!checkNaturalArray(msg.origin)) return false; + for (let { id, count } of msg.origin) { + if (!checkNaturalNumbers(id, count)) return false; + } + break; + } + case "role.mailHandler.readMail": + { + if (!checkNaturalStrings(msg.id)) return false; + if (!checkMailType(msg.mailType)) return false; + break; + } + case "role.mailHandler.delMails": + case "role.mailHandler.getMailRewards": + { + if (!checkStringIfExist(msg.id)) return false; + if (!checkMailType(msg.mailType)) return false; + if (msg.type != 1 && msg.type != 2) return false; + break; + } + case "role.rankHandler.getRank": + case "role.rankHandler.getGuildRank": + { + if (!checkNaturalNumbers(msg.type)) return false; + break; + } + case "role.rankHandler.getHeroRank": + { + if (!checkNaturalNumbers(msg.type, msg.hid)) return false; + break; + } + case "role.rankHandler.receiveReward": + { + if (!checkNaturalNumbers(msg.type, msg.id)) return false; + break; + } + case "role.roleHandler.initRole": + case "role.roleHandler.rename": + { + if (!checkNaturalStrings(msg.roleName)) return false; + break; + } + case "role.roleHandler.getRoleInfo": + { + if (!checkNaturalStrings(msg.targetRoleId)) return false; + break; + } + case "role.roleHandler.roleTeraphStrengthen": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "role.roleHandler.roleTeraphQualityUp": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "role.roleHandler.changeSchoolHero": + { + let { schoolId, positionId, hid } = msg; + if (!checkNaturalNumbers(schoolId, positionId, hid)) return false; + break; + } + case "role.roleHandler.unlockSchoolPosition": + { + if (!checkNaturalNumbers(msg.schoolId, msg.positionId)) return false; + break; + } + case "role.roleHandler.activeHeroScroll": + { + if (!checkNaturalNumbers(msg.hid)) return false; + break; + } + case "role.roleHandler.saveShowLineup": + { + if (!checkArrayCanEmpty(msg.showLineup)) return false; + for (let hid of msg.showLineup) { + if (!checkNaturalNumbers(hid)) return false; + } + break; + } + case "role.roleHandler.setHead": + case "role.roleHandler.setFrame": + case "role.roleHandler.setSpine": + { + if (!checkNaturalNumbers(msg.id)) return false; + break; + } + case "role.roleHandler.saveGuide": + { + if (!checkNumberArray(msg.ids)) return false; + break; + } + case "role.shopHandler.getShopList": + case "role.shopHandler.readShop": + { + if (!checkNaturalNumbers(msg.shop, msg.type)) return false; + break; + } + case "role.shopHandler.purchase": + { + if (!checkNaturalNumbers(msg.shopItemId, msg.count)) return false; + break; + } + case "role.shopHandler.recycleSoul": + { + if (!checkNaturalNumbers(msg.goodsId, msg.count)) return false; + break; + } + case "role.shopHandler.recycleSoulFast": + { + if (!checkNaturalArray(msg.recycleSoulFastPara)) return false; + for (let { hid, count } of msg.recycleSoulFastPara) { + if (!checkNaturalNumbers(hid, count)) return false; + } + break; + } + case "role.taskHandler.receiveTask": + { + if (!checkNaturalNumbers(msg.type, msg.id)) return false; + break; + } + case "role.taskHandler.receiveBox": + { + if (!checkNaturalNumbers(msg.type, msg.id)) return false; + break; + } + case "role.taskHandler.receiveMainStage": + { + if (!checkNaturalNumbers(msg.stage)) return false; + break; + } + case "battle.ladderHandler.getRec": + { + if (!checkNaturalStrings(msg.name)) return false; + if (!checkStringIfExist(msg.notice)) return false; + if (!checkNaturalNumbers(msg.icon)) return false; + break; + } + case "role.heroHandler.addItem": + { + if (!isDevelopEnv()) return false; + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "role.roleHandler.setPushMsgTrigger": + { + if (!isBoolean(msg.isClosePush)) return false; + break; + } + case "role.roleHandler.setHasComment": + { + if (!isBoolean(msg.hasComment)) return false; + break; + } + case "role.authorBookHandler.starUp": + { + if (!checkNaturalNumbers(msg.bookId, msg.subId, msg.star)) return false; + if (!isBoolean(msg.useItem)) return false; + break; + } + case "role.authorBookHandler.resetAuthor": + { + if (!checkNaturalNumbers(msg.bookId, msg.subId, msg.star)) return false; + break; + } + case "role.authorBookHandler.buySpirit": + { + if (!checkNaturalNumbers(msg.id, msg.count)) return false; + break; + } + case "role.authorBookHandler.decomposeSpirit": + { + if (!checkNaturalArray(msg.spirits)) return false; + for (let { id, count } of msg.spirits) { + if (!checkNaturalNumbers(id, count)) return false; + } + break; + } + case "role.resonanceHandler.getData": + { + break; + } + case "role.resonanceHandler.unlockPosition": + { + if (!checkNaturalNumbers(msg.position)) return false; + break; + } + case "role.resonanceHandler.heroPutPosition": + { + if (!checkNaturalNumbers(msg.position, msg.hid)) return false; + break; + } + case "role.resonanceHandler.heroOffPosition": + { + if (!checkNaturalNumbers(msg.position, msg.hid)) return false; + break; + } + case 'activity.dragonBoatHandler.gameStart': + case 'activity.dragonBoatHandler.gameEnd': + { + if (!checkNaturalNumbers(msg.activityId, msg.id)) return false; + break; + } + case 'activity.dragonBoatHandler.buyCnt': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.qixiHandler.gameStart': + { + if (!checkNaturalNumbers(msg.activityId, msg.progress)) return false; + break; + } + case 'activity.qixiHandler.gameEnd': + { + if (!checkNaturalNumbers(msg.activityId, msg.progress, msg.addProgress)) return false; + if (!checkNaturalStrings(msg.gameCode)) return false; + break; + } + case 'activity.qixiHandler.buyCnt': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.midAutumnHandler.gameStart': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.midAutumnHandler.gameEnd': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + if (!checkNaturalStrings(msg.gameCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case 'activity.midAutumnHandler.buyCnt': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.midAutumnHandler.gameSweep': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.authorGachaHandler.getData': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.authorGachaHandler.receiveBox': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.chongyangHandler.getData': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.chongyangHandler.gameStart': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; + break; + } + case 'activity.chongyangHandler.gameEnd': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex)) return false; + if (!checkNaturalStrings(msg.gameCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case 'activity.chongyangHandler.buyCnt': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.count)) return false; + break; + } + case 'activity.chongyangHandler.gameSweep': + { + if (!checkNaturalNumbers(msg.activityId, msg.dayIndex, msg.count)) return false; + break; + } + case 'activity.novemberHandler.getData': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.novemberHandler.gameStart': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + break; + } + case 'activity.novemberHandler.gameEnd': + { + if (!checkNaturalNumbers(msg.activityId)) return false; + if (!checkNaturalStrings(msg.gameCode)) return false; + if (!checkBoolean(msg.isSuccess)) return false; + break; + } + case 'activity.novemberHandler.buyCnt': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.novemberHandler.gameSweep': + { + if (!checkNaturalNumbers(msg.activityId, msg.count)) return false; + break; + } + case 'activity.activityHandler.debugActivityMemory': + case 'activity.popUpShopHandler.debugPushPopUpShop': + case 'activity.popUpShopHandler.debugPushPopUpInterval': + case 'activity.popUpShopHandler.debugStopPupUpInterval': + case 'activity.popUpShopHandler.debugSendMail': + case 'activity.popUpShopHandler.debugTakeSnapshot': + case "battle.dailyBattleHandler.debugResetNum": + case "battle.dungeonBattleHandler.debugResetRefTime": + case "battle.eventBattleHandler.debugRefEvent": + case "battle.expeditionBattleHandler.debugResetResetNum": + case "battle.pvpHandler.addRoleScore": + case "battle.pvpHandler.debugAddChallengeCnt": + case "battle.pvpHandler.debugPvpSeasonResetTime": + case "battle.pvpHandler.debugResetAttackCnt": + case "battle.pvpHandler.debugResetBox": + case "battle.pvpHandler.debugResetRefOppCnt": + case "connector.entryHandler.debugGetRole": + case "connector.entryHandler.debugPushRefToOnlineUsers": + case "connector.entryHandler.debugQueryToken": + case "connector.entryHandler.debugQueryTokenById": + case "connector.entryHandler.debugQueryTokenByTel": + case "guild.auctionHandler.debugAddLots": + case "guild.auctionHandler.debugScheduleSendUngotDividend": + case "guild.auctionHandler.debugScheduleStartGuild": + case "guild.auctionHandler.debugScheduleStartWorld": + case "guild.auctionHandler.debugScheduleStopAuction": + case "guild.auctionHandler.debugSetDividendStatus": + case "guild.auctionHandler.debugSetLotStage": + case "guild.auctionHandler.debugSetPlayTime": + case "guild.cityActivityHandler.debugResetCity": + case "guild.gateActivityHandler.debugAddParticipants": + case "guild.gateActivityHandler.debugDelRedis": + case "guild.gateActivityHandler.debugEndActivity": + case "guild.gateActivityHandler.debugGetPrivate": + case "guild.gateActivityHandler.debugIncChallengeCnt": + case "guild.gateActivityHandler.debugSetDay": + case "guild.gateActivityHandler.debugStartActivity": + case "guild.gateActivityHandler.test": + case "guild.guildHandler.debugAddActive": + case "guild.guildHandler.debugAdddFund": + case "guild.guildHandler.debugClearQuitGuildTime": + case "guild.guildHandler.debugJoinGuild": + case "guild.guildBossHandler.debugAddBattleTimes": + case "guild.guildBossHandler.debugAddOpenTimes": + case "guild.guildHandler.debugLeaderLeaveTime": + case "guild.guildHandler.debugWeeklyRask": + case "order.orderHandler.debugOrder": + case "role.heroHandler.debugGetAllHeroes": + case "role.heroHandler.debugSetHero": + case "guild.guildTrainHandler.debugAddTrainCount": + case "guild.guildTrainHandler.debugResetTrainInstance": + case "role.heroHandler.testCleanUp": + case "role.itemHandler.debugIncAp": + case "role.itemHandler.debugResetBuyTimes": + case "role.roleHandler.debugClearRole": + case "role.roleHandler.debugPlayerTime": + case "role.roleHandler.debugRoleLvUp": + case "role.roleHandler.debugSetRole": + case "role.roleHandler.debugTreatRoleName": + case "role.roleHandler.test": + case "role.taskHandler.test": + case "role.taskHandler.debugCompleteMainStage": + case "role.taskHandler.debugCompleteRandTask": + case "role.taskHandler.debugGetDicTask": + case "role.taskHandler.debugIncPoint": + case "role.taskHandler.debugRefTask": + case "role.shopHandler.debugClearPurchaseLimit": + case "guild.raceActivityHandler.settleReward": + case "battle.ladderHandler.resetCnt": + case "battle.ladderHandler.setMyRank": + case "battle.ladderHandler.setMyOpp": + case "guild.raceActivityHandler.debugAddHorse": + case "activity.gachaHandler.debugClearGachaRecord": + case "battle.eventBattleHandler.debugRefEvent": + // case "guild.raceActivityHandler.debugResetJoin": + case "guild.cityActivityHandler.debugStartHitGate": + case "guild.cityActivityHandler.debugStopHitGate": + case "guild.cityActivityHandler.debugTestAutoDeclare": + case "activity.groupShopHandler.debugRefund": + case "activity.groupShopHandler.debugSetSum": + case "activity.groupShopHandler.debugClearCnt": + case "activity.groupShopHandler.debugAddLeagueItem": + case "activity.groupShopHandler.debugHandleCost": + case "guild.gvgProduceHandler.debugAddResource": + case "guild.gvgFightHandler.debugCalRec": + case "guild.gvgFightHandler.debugSaveScore": + case "guild.gvgBattleHandler.createCity": + case "guild.gvgProduceHandler.debugAdjustHarvest": + case "guild.gvgFightHandler.debugSetMyRank": + case "guild.gvgFightHandler.debugSetMyOpp": + case "guild.gvgBattleHandler.debugAddRobots": + case "guild.gvgBattleHandler.debugMoveRobots": + case "guild.gvgBattleHandler.debugStopMoveRobot": + case "chat.chatHandler.debugPushMessage": + case "activity.monthlyFundHandler.debugSendMonthlyFundReward": + case "activity.bindPhoneHandler.debugSetGiftCodeStatus": + case 'activity.rebateHandler.debugSetRebate': + case 'activity.newHeroGKHandler.debugResetGK': + case 'battle.rougeHandler.debugClearTech': + case "battle.rougeHandler.debugAddCard": + case "battle.rougeHandler.debugAddScore": + case "battle.rougeHandler.debugRepaireScoreReward": + case "battle.rougeHandler.debugAddCollection": + { + if (msg.magicWord !== DEBUG_MAGIC_WORD || !isDevelopEnv()) return false; + break; + } + case "battle.rougeHandler.debugAddLimitId": + + case "comBattle.comBattleHandler.getTeams": + case "comBattle.comBattleHandler.teammateReady": + case "comBattle.comBattleHandler.battleEnd": + case "connector.entryHandler.addSession": + case "connector.entryHandler.getIp": + case "chat.chatHandler.getInitMessage": + case "connector.entryHandler.onGmUserLeave": + case "connector.entryHandler.onUserLeave": + case "gm.gmHandler.sendMail": + case "gm.gmHandler.saveGroupToServer": + case "gm.gmHandler.saveActivitiesToGroup": + case "role.mailHandler.refrshMails": + { + return false + } + } + return true; +} + +function checkNaturalNumbers(...params: number[]) { + for (let param of params) { + if (param == undefined || !isNumber(param) || param < 0) return false; + } + return true +} + +function checkNaturalArray(array: T[]) { + return isArray(array) && array.length > 0; +} + +function checkArrayCanEmpty(array: T[]) { + return isArray(array); +} + +function checkNaturalStrings(...params: string[]) { + for (let param of params) { + if (param == undefined || !isString(param) || param == '') return false; + } + return true; +} + +function checkStringIfExist(...params: string[]) { + for (let param of params) { + if (!!param && !isString(param)) return false; + } + return true; +} + +function checkNumberIfExist(...params: number[]) { + for (let param of params) { + if (!!param && !isNumber(param)) return false; + } + return true; +} + +function checkNumberArray(...params: number[][]) { + for (let array of params) { + if (array == undefined || !isArray(array)) return false; + if (!checkNaturalNumbers(...array)) return false; + } + return true; +} + +function checkStringArray(...params: string[][]) { + for (let array of params) { + if (array == undefined || !isArray(array)) return false; + if (!checkNaturalStrings(...array)) return false; + } + return true; +} + +function checkBoolean(...params: boolean[]) { + for (let param of params) { + if (!isBoolean(param)) return false; + } + return true; +} + +function checkBooleanIfExist(...params: boolean[]) { + for (let param of params) { + if (param != undefined && !isBoolean(param)) return false; + } + return true; +} + +function checkExpeditionBattleHeroFormat(...params: { dataId: number, hp: number, ap: number }[][]) { + for (let param of params) { + if (!checkArrayCanEmpty(param)) return false; + for (let { dataId, hp, ap } of param) { + if (!checkNaturalNumbers(dataId, ap)) return false; + if (!isNumber(hp)) return false; + } + } + return true; +} + +function checkPvpEndHeroFormat(...params: pvpEndParamInter[][]) { + for (let param of params) { + if (!checkArrayCanEmpty(param)) return false; + for (let { hid, damage, heal, underDamage } of param) { + if (!checkNaturalNumbers(hid, damage, heal, underDamage)) return false; + } + } + return true; +} + +function checkGvgEndHeroFormat(...params: gvgEndParamInter[][]) { + for (let param of params) { + if (!checkArrayCanEmpty(param)) return false; + for (let { actorId, hp, others } of param) { + if (!checkNaturalNumbers(actorId, hp)) return false; + if (!checkStringIfExist(others)) return false; + } + } + return true; +} + +function checkIsInEnum(someEnum: T, value: T) { + return Object.values(someEnum).includes(value) +} + +function checkMailType(mailType: any) { + if (!checkNaturalNumbers(mailType)) return false; + if (!checkIsInEnum(GM_MAIL_TYPE, mailType)) return false; + return true; +} + +function checkSeqId(...seqIds: (number | string)[]) { + for (let seqId of seqIds) { + if (!checkNaturalNumbers(seqId) && !checkNaturalStrings(seqId)) return false + } + return true; +} + +function checkCombo(combo: { groupId: number, levelList: number[] }[]) { + if (combo) { + if (!isArray(combo)) return false; + for (let { groupId, levelList } of combo) { + if (!isNumber(groupId)) return false; + if (!isArray(levelList)) return false; + for (let lv of levelList) { + if (!isNumber(lv)) return false; + } + } + } + return true; +} + +function checkIsDuplicateNumbers(array: number[]) { + const seen = new Set(); + for (const item of array) { + if (!isNumber(item)) return false; + if (seen.has(item)) { + return false; // 发现重复元素 + } + seen.add(item); + } + return true; // 没有重复元素 +} + +function checkIsDuplicateStrings(array: string[]) { + const seen = new Set(); + for (const item of array) { + if (!isString(item)) return false; + if (seen.has(item)) { + return false; // 发现重复元素 + } + seen.add(item); + } + return true; // 没有重复元素 +} diff --git a/game-server/app/services/connectorService.ts b/game-server/app/services/connectorService.ts index 0d4e4d0fc..d555622a6 100644 --- a/game-server/app/services/connectorService.ts +++ b/game-server/app/services/connectorService.ts @@ -1,516 +1,516 @@ -/** - * entry触发后引起的下发 - */ -import { getMails } from './mailService'; -import { recentGuildMsgs, recentLeagueMsgs, recentPrivateChatInfos, recentServerGroupMsgs, recentSysMsgs, recentWorldMsgs } from './chatService'; -import { getCurTask, getPvpTask } from './task/taskService'; - -import { RoleModel, RoleType } from '../db/Role'; -import { Application, BackendSession, FrontendOrBackendSession, pinus, RpcClient } from 'pinus'; -import { compareVersion, getRandEelmWithWeight, resResult } from '../pubUtils/util'; -import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE, HERO_SELECT, ENTERY_ROLE_PICK, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE, ARTIFACT_SELECT, ACTIVITYITEM_SELECT, SNS_LINK_TYPE, VESTIGE_STATUS, HERO_SYSTEM_TYPE } from '../consts'; -import { getAllShopList } from './shopService'; -import { getGeneralRank, getRankFirstReward } from './rankService'; -import { getFriendList, getApplyList } from './friendService'; -import { getDailyBattleList } from './dailyBattleService'; -import { getExpeditionStatus } from './expeditionService'; -import { getTowerStatus, getHungupRewards, getTasks } from './battleService'; -import { getAllAssistCnt, getCapExtraCnt, getComBtlLvByPlayerLv } from './battle/comBattleService'; -import { getDungeonData } from './dungeonService'; -import { nowSeconds, getZeroPoint, getTimeFunM } from '../pubUtils/timeUtil'; -import { getGachaList, getVisitedHeroList } from './activity/gachaService'; -import { getSchoolList } from './roleService'; -import { addRoleToGuildChannel } from './chatChannelService'; -import { getMyGuildInfo, getUserGuildWithRefActive, getWishPool, getInvitationList } from './guildService'; -import { getAuction } from './auctionService'; -import { getGuildTrainInstance, getTrainBoxRewardsResult } from './guildTrainService'; -import { getBossInstanceInfo } from './guildBossService'; -import { getEvent } from './eventSercive'; -import { getBattleListOfMain, getMainChapter } from './normalBattleService'; -import { GuildModel, GuildType } from '../db/Guild'; -import UserGuild, { UserGuildType } from '../db/UserGuild'; -import { getAllGuildActivityStatus } from './guildActivity/guildActivityService'; -import { checkRecalJewelOpen, getAllOnlineRoles, getAllServers, incConnectorNum, redisClient } from './redisService'; -import Item, { ItemModel } from '../db/Item'; -import { PvpDefenseModel } from '../db/PvpDefense'; -import { getDonation } from './donateService'; -import { refChallengeCnt, sendLastSeasonRewardIfNotSent } from './pvpService'; -import { HeroModel, HeroType } from '../db/Hero'; -import { JewelModel, JewelType } from '../db/Jewel'; -import { SkinModel, SkinType } from '../db/Skin'; -import { getAp } from './actionPointService'; -import { HeroParam } from '../domain/roleField/hero'; -import { pick } from 'underscore'; -import { sendMessageToAllWithSuc, sendMessageToServerWithSuc, sendMessageToUser, sendMessageToUserWithSuc } from './pushService'; -import { getSurvey } from './gmService'; -import { ComBattleTeamModel } from '../db/ComBattleTeam'; -import { INFO_WINDOW } from '../pubUtils/dicParam'; -import { getLadderData } from './ladderService'; -import { dispatch } from '../pubUtils/dispatcher'; -import { PvpDataReturn } from '../domain/battleField/pvp'; -import { ArtifactModel, ArtifactModelType } from '../db/Artifact'; -import { ActivityItemModel } from '../db/ActivityItem'; -import { LinkModel } from '../db/Link'; -import { getHiddenData } from './memoryCache/hiddenData'; -import { AuthorBookModel } from '../db/AuthorBook'; -import { gameData } from '../pubUtils/data'; -import { getRougeData } from './battle/rougeService'; -import { LadderMatchRecModel } from '../db/LadderMatchRec'; -import { GVGVestigeRecModel, GVGVestigeRecUpdate } from '../db/GVGVestigeRec'; -import { getVestigeRecStatus } from './gvg/gvgFightService'; -import { getRemoteRplPrefix } from '../pubUtils/battleUtils'; -import { calculateCeWithRole } from './playerCeService'; -import { SchoolModel } from '../db/School'; -import { getResonanceDataMap } from './role/resonanceService'; - -/** - * init: 初始的时候是否推送 true-推 false-不推 - * refresh: 凌晨5点刷新时是否推送 true-推 false-不推 - * guild: 是否一定有了军团才要推送 true-必须要 false-不用 - */ -const modules = [ - { id: 1, type: 'role', init: true, refresh: true, guild: false }, - { id: 2, type: 'battle', init: true, refresh: false, guild: false }, - { id: 3, type: 'chapter', init: true, refresh: false, guild: false }, - { id: 4, type: 'rank', init: false, refresh: false, guild: false }, - { id: 5, type: 'mail', init: false, refresh: false, guild: false }, - { id: 6, type: 'friend', init: false, refresh: true, guild: false }, - { id: 7, type: 'daily', init: false, refresh: true, guild: false }, - { id: 8, type: 'expedition', init: false, refresh: true, guild: false }, - { id: 9, type: 'tower', init: false, refresh: true, guild: false }, - { id: 10, type: 'comBattle', init: false, refresh: true, guild: false }, - { id: 11, type: 'dungeon', init: false, refresh: true, guild: false }, - { id: 12, type: 'pvp', init: false, refresh: true, guild: false }, - { id: 13, type: 'gacha', init: false, refresh: true, guild: false }, - // { id: 14, type: 'school', init: false, refresh: false, guild: false }, - { id: 15, type: 'task', init: false, refresh: true, guild: false }, - { id: 16, type: 'chat', init: false, refresh: false, guild: false }, - // { id: 17, type: 'event', init: false, refresh: true, guild: false }, - { id: 18, type: 'guild', init: false, refresh: true, guild: false }, - { id: 19, type: 'auction', init: false, refresh: false, guild: true }, - { id: 20, type: 'train', init: false, refresh: true, guild: true }, - { id: 21, type: 'boss', init: false, refresh: true, guild: true }, - { id: 22, type: 'wishPool', init: false, refresh: true, guild: true }, - { id: 23, type: 'guildActivity', init: false, refresh: true, guild: true }, - { id: 24, type: 'donate', init: false, refresh: true, guild: true }, - { id: 25, type: 'shop', init: false, refresh: true, guild: false }, - { id: 26, type: 'survey', init: false, refresh: true, guild: false }, - { id: 27, type: 'ladder', init: false, refresh: true, guild: false }, - { id: 28, type: 'hiddenData', init: true, refresh: true, guild: false }, - { id: 29, type: 'rouge', init: true, refresh: true, guild: false }, - { id: 30, type: 'iconShow', init: true, refresh: true, guild: false }, - -] - -export async function pushData(hasInit: boolean, role: RoleType, session: FrontendOrBackendSession, pushType: 'entry' | 'refresh' = 'entry') { - try { - const { roleId } = role; - const sid = session.get('sid'); - - pushEntryStart(roleId, sid); - // 军团 - const guildData = await getGuildEntryData(role, sid, session); - for (let { type, init, refresh, guild } of modules) { - if (!hasInit && !init) continue; - if (pushType == 'refresh' && !refresh) continue; - if (!guildData.hasGuild && guild) continue; - - let data = await getModuleData(type, { role, session }, guildData); - if (data) { - pushEntryData(type, roleId, sid, data); - } - } - - pushEntryEnd(roleId, sid); - } catch (e) { - console.error(e.stack); - } -} - -export async function getModuleData(type: string, data: { role: RoleType, session: FrontendOrBackendSession }, guildData: { hasGuild: boolean, guild?: GuildType, userGuild?: UserGuildType, guildResult?: any } = { hasGuild: false }) { - try { - let { role, session } = data; - const { roleId, serverId, roleName, guildCode } = role; - let { hasGuild, guild, userGuild, guildResult } = guildData; - switch (type) { - case 'role': - let heros = await HeroModel.findByRole(role.roleId, [], HERO_SELECT.ENTRY, true); - let jewels = await JewelModel.findbyRole(role.roleId, JEWEL_SELECT.ENTRY); - let items = await ItemModel.findbyRole(role.roleId, ITEM_SELECT.ENTRY); - let skins = await SkinModel.findbyRole(role.roleId, SKIN_SELECT.ENTRY); - let artifacts = await ArtifactModel.findbyRole(role.roleId, ARTIFACT_SELECT.ENTRY); - let activityItems = await ActivityItemModel.findbyRole(role.roleId, ACTIVITYITEM_SELECT.ENTRY); - let link = await LinkModel.findByType(SNS_LINK_TYPE.CUSTOMER); - - await reCalJewel(role, heros, jewels, skins, artifacts); - let { dbResonanceMap } = await getResonanceDataMap(role.roleId); - - role['heros'] = heros.map(hero => new HeroParam(hero)); - for (let hero of role['heros']) { - hero.isResonance = false; - if (dbResonanceMap.has(hero.hid)) { - hero.isResonance = true; - } - } - - role['jewels'] = jewels; - role['consumeGoods'] = items; - role['skins'] = skins; - let apJson = await getAp(role.roleId, '', role.lv); - role['apJson'] = apJson; - role['ipLocation'] = role.fixedIpLocation || role.ipLocation || '未知'; - role['artifacts'] = artifacts; - role['activityItems'] = activityItems; - role['authorBook'] = await getAuthorBook(role.roleId); - - if (!role.showLineup) role.showLineup = role.topLineup.map(cur => cur.hid); - role.heads = role.heads.filter(cur => cur.status); - role.frames = role.frames.filter(cur => cur.status); - role.spines = role.spines.filter(cur => cur.status); - role['customerLink'] = link?.link || ''; - return pick(role, ENTERY_ROLE_PICK); - case 'shop': // 商店 - return await getAllShopList(roleId, serverId); - case 'rank': // 排名 - const rewards = await getRankFirstReward(role, serverId); - return { rewards } - case 'mail': // 邮件 - return await getMails(roleId, serverId); - case 'friend': // 好友 - const friendList = await getFriendList(role); - const applyList = await getApplyList(roleId); - return { friendList, applyList } - case 'daily': // 每日 - return await getDailyBattleList(role); - case 'expedition': // 远征 - return await getExpeditionStatus(roleId, roleName, true); - case 'tower': // 镇念塔 - return await getTowerEntryData(role); - case 'comBattle': // 寻宝 - return await getComBattleEntryData(role, guildCode); - case 'dungeon': // 秘境 - return await getDungeonData(role); - case 'pvp': // pvp - return await getPvpEntryData(roleId); - case 'gacha': - const gachalist = await getGachaList(roleId); - const visitList = await getVisitedHeroList(roleId); - return { hasInit: true, gachalist, visitList } - case 'school': - return await getSchoolList(roleId); - case 'guild': - let invitation = await getInvitationList(roleId, ''); - return { ...guildResult, invitation }; - case 'auction': - return hasGuild ? await getAuction(guildCode, session) : null; - case 'train': - if (hasGuild) { - let trainInstance = await getGuildTrainInstance(roleId, guild, userGuild); - if (!trainInstance) return null; - let trainBoxRewards = await getTrainBoxRewardsResult(guildCode); - return { trainInstance, trainBoxRewards } - } - break; - case 'boss': - if (hasGuild) { - return await getBossInstanceInfo(userGuild, guild); - } - return null; - case 'wishPool': - return hasGuild ? await getWishPool(userGuild) : null; - case 'donate': - if (hasGuild) { - const { guildCode: code, donateCnt, receiveBoxs } = userGuild; - let { donateFund, reports, donationLv } = await getDonation(code, guild); - return { receiveBoxs, donateFund, reports, donateCnt: donateCnt || 0, donationLv }; - } - break; - case 'task': - let tasks = await getCurTask(role.roleId, session); - let pvpTask = await getPvpTask(role.roleId); - return { ...tasks, pvpTask } - case 'chat': - const worldMsgs = await recentWorldMsgs(serverId); - const sysMsgs = await recentSysMsgs(serverId); - const guildMsgs = await recentGuildMsgs(guildCode); - const gvgMsgs = await recentServerGroupMsgs(serverId); - const leagueMsgs = await recentLeagueMsgs(guildCode); - const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName); - return { worldMsgs, sysMsgs, guildMsgs, gvgMsgs, leagueMsgs, recentPrivateChats }; - case 'event': - return await getEvent(role.eventStatus, roleId, roleName); - case 'battle': - return await getBattleListOfMain(role); - case 'guildActivity': - return getAllGuildActivityStatus(role.guildCode, role.serverId); - case 'chapter': - return getMainChapter(role); - case 'survey': - return await getSurvey(role.roleId, role.lv); - case 'ladder': - return await getLadderData(role.roleId, false); - case 'hiddenData': - return getHiddenData(); - case 'rouge': - return await getRougeData(role.roleId); - case 'iconShow': - return await getIconShow(role.roleId, session); - default: - return null; - } - } catch (e) { - console.error(e.stack); - return false - } -} - -function pushEntryData(type: string, roleId: string, sid: string, param: T) { - let data = { type }; - data[type] = param; - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA, data, sid); -} - -function pushEntryStart(roleId: string, sid: string) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA_START, {}, sid); -} - -function pushEntryEnd(roleId: string, sid: string) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA_END, {}, sid); -} - - -/** - * 镇念塔初始数据 - * @param role - */ -async function getTowerEntryData(role: RoleType) { - const { roleId } = role; - const status = await getTowerStatus(role); - const hungUp = await getHungupRewards(roleId); - if (!hungUp) { - return { status, hungUp: {} } - } else { - return { status, hungUp: hungUp } - } -} - -/** - * 获取是否存在pvp赛季奖励 - * @param roleId - */ -async function getPvpEntryData(roleId: string) { - let seasonNum: number = pinus.app.get('pvpSeasonNum'); - let seasonEndTime: number = pinus.app.get('pvpSeasonEndTime'); - let seasonStartTime: number = pinus.app.get('pvpSeasonStartTime'); - let seasonRewardTime: number = pinus.app.get('pvpSeasonRewardTime'); - - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - if (pvpDefense) { - pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense); - - let result = new PvpDataReturn(); // 返回对象 - result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); - result.setPvpDefense(pvpDefense); - result.calHasSaveDefense(); - let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId); - let { challengeCnt } = refChallengeObj; - result.setChallengeCnt(challengeCnt); - return pick(result, ['challengeCnt', 'score', 'seasonWinNum', 'receivedBox', 'hasSaveDefense', 'seasonNum', 'seasonEndTime', 'seasonStartTime', 'seasonRewardTime']) - } else { - let result = new PvpDataReturn(); // 返回对象 - result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); - return pick(result, ['seasonNum', 'seasonEndTime', 'seasonStartTime', 'seasonRewardTime']) - } -} - -/** - * 获取军团信息,并加入军团频道 - * @param role - * @param sid - * @param session - */ -async function getGuildEntryData(role: RoleType, sid: string, session: FrontendOrBackendSession) { - - if (role.hasGuild) { - let userGuild = await getUserGuildWithRefActive(role.roleId); - if (userGuild) { - let guild = await GuildModel.findByCode(userGuild.guildCode, role.serverId); - if (guild) { - addRoleToGuildChannel(role.roleId, sid, userGuild.guildCode); - - let result = await getMyGuildInfo(role.roleId, sid, userGuild, guild, role.serverId, session); - return { hasGuild: true, guild, userGuild, guildResult: result }; - } - } - } - return { hasGuild: false } -} - -async function getComBattleEntryData(role: RoleType, guildCode: string) { - let { roleId, lv, topLineupCe } = role; - const assistCnt = await getAllAssistCnt(roleId); - const blueprts = await Item.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); - let { minLv, maxLv } = getComBtlLvByPlayerLv(lv); - let refreshTime = nowSeconds() - INFO_WINDOW.TEAM_INFORMATION_TIME; - const invitations = await ComBattleTeamModel.findInvitations(roleId, guildCode, minLv, maxLv, topLineupCe, refreshTime, 1); - let capExtraCnt = await getCapExtraCnt(roleId); - return { assistCnt, blueprts, hasInvitation: invitations.length > 0, invitationTime: invitations.length > 0 ? invitations[0].inviteTime : 0, capExtraCnt } -} - -export async function pushRefreshTime() { - let todayZeroPoint = getZeroPoint(); - await sendMessageToAllWithSuc(PUSH_ROUTE.REFRESH_TIME, { todayZeroPoint }); -} - -export async function kickUser(app: Application, uid: string, message = STATUS.LOGIN_ERR) { - let sessionService = app.get('sessionService'); - let sessions = sessionService.getByUid(uid); - if (!!sessions) { - sessions.forEach(session => { - let roleId = session.get('roleId'); - let sid = session.get('sid'); - sendMessageToUser(roleId, PUSH_ROUTE.REMOTE_LOGIN, resResult(message), sid); - }); - } - await sessionService.akick(uid); -} - -export async function assignServer(roleId: string, session: FrontendOrBackendSession) { - try { - let activity = await _assignServer(roleId, 'activity'); - let battle = await _assignServer(roleId, 'battle'); - let chat = await _assignServer(roleId, 'chat'); - let guild = await _assignServer(roleId, 'guild'); - let role = await _assignServer(roleId, 'role'); - let order = await _assignServer(roleId, 'order'); - let comBattle = await _assignServer(roleId, 'comBattle'); - if (activity) { - session.set('activityServer', activity); - session.push('activityServer', () => { }); - } - if (battle) { - session.set('battleServer', battle); - session.push('battleServer', () => { }); - } - if (chat) { - session.set('chatServer', chat); - session.push('chatServer', () => { }); - } - if (guild) { - session.set('guildServer', guild); - session.push('guildServer', () => { }); - } - if (role) { - session.set('roleServer', role); - session.push('roleServer', () => { }); - } - if (order) { - session.set('orderServer', order); - session.push('orderServer', () => { }); - } - if (comBattle) { - session.set('comBattleServer', comBattle); - session.push('comBattleServer', () => { }); - } - } catch (e) { - console.log(e) - } -} - -async function _assignServer(roleId: string, serverType: string) { - let servers = pinus.app.getServersByType(serverType) || []; - let sum = servers.reduce((pre, cur) => pre + (cur['num'] || 0), 0); - let id = ''; - if (sum > 0) { - let serversWithWeight = servers.map(cur => ({ ...cur, weight: sum - (cur['num'] || 0) })); - let { dic: server } = getRandEelmWithWeight(serversWithWeight); - id = server?.id; - } - if (!id) { - id = (await dispatch(redisClient(), roleId, servers, serverType))?.id; - } - return id -} - -export function incServerNum(sid: string, inc: number) { - if (!pinus.app.getServerById(sid)) return; - if (!pinus.app.getServerById(sid)['num']) { - pinus.app.getServerById(sid)['num'] = 0; - } - pinus.app.getServerById(sid)['num'] += inc; - if (pinus.app.getServerById(sid)['num'] < 0) { - pinus.app.getServerById(sid)['num'] = 0; - } -} - -export async function leaveServer(session: FrontendOrBackendSession) { - let activity = session.get('activityServer'); - let battle = session.get('battleServer'); - let chat = session.get('chatServer'); - let guild = session.get('guildServer'); - let role = session.get('roleServer'); - let order = session.get('orderServer'); - let sid = session.get('sid'); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(activity, -1); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(battle, -1); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(chat, -1); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(guild, -1); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(role, -1); - pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(order, -1); - - incServerNum(sid, -1); - incConnectorNum(sid, -1); -} - -async function getAuthorBook(roleId: string) { - let result: { bookId: number, authors: { subId: number, star: number }[], progress: number, maxProgress: number }[] = []; - let authorBooks = await AuthorBookModel.findByRoleId(roleId); - for (let [bookId, maxProgress] of gameData.authorBookMaxProgress) { - let authorBook = authorBooks.find(cur => cur.bookId == bookId); - result.push({ bookId, authors: authorBook?.authors ?? [], progress: authorBook?.progress ?? 0, maxProgress }); - } - return result -} - -async function getIconShow(roleId: string, session:FrontendOrBackendSession) { - let quitTime = session.get('quitTime'); - if (!roleId) return; - let ladderIconShow = await LadderMatchRecModel.findRecByRoleId(roleId, quitTime); - - let list = await GVGVestigeRecModel.findRecCurDay(roleId, Math.max(quitTime, getZeroPoint()*1000)); - let result: (GVGVestigeRecUpdate & { rplFileUrl: string })[] = []; - for (let rec of list) { - const { attackRoleId, battleCode, hasRpl, remoteUrl } = rec; - const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; - const obj = getVestigeRecStatus(rec); - if (obj.status == VESTIGE_STATUS.COMPLETE && result.length < 10) result.push({ ...rec, endTime: obj.time, rplFileUrl }); - } - let gvgFightRecs = { list: result, rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) }; - - return { ladderIconShow, gvgFightRecs } -} - -export async function pushIconShow(roleId: string, ladderIconShow?: boolean, gvgFightRecs?) { - if (!roleId) return; - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LADDER_OR_GVG_ICON_SHOW, { ladderIconShow, gvgFightRecs }); -} - -export async function reCalJewel(role: RoleType, heroes: HeroType[], jewels: JewelType[], skins: SkinType[], artifacts: ArtifactModelType[]) { - if (role.hasTreat || !await checkRecalJewelOpen()) return - role = await RoleModel.updateRoleInfo(role.roleId, { hasTreat: true }); - for (let jewel of jewels) { - let hero = heroes.find(hero => { - let ePlace = hero.ePlace.find(e => e.jewel == jewel.seqId); - return !!ePlace; - }); - if (hero && hero.hid != jewel.hid) { - let ePlace = hero.ePlace.find(e => e.jewel == jewel.seqId); - if (ePlace) { - await JewelModel.updateInfo(jewel.seqId, { hid: hero.hid, ePlaceId: ePlace.id }); - jewel.hid = hero.hid; jewel.ePlaceId = ePlace.id; - } - } - } - let schools = await SchoolModel.findByRoleId(role.roleId); - await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, role.roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); -} \ No newline at end of file +/** + * entry触发后引起的下发 + */ +import { getMails } from './mailService'; +import { recentGuildMsgs, recentLeagueMsgs, recentPrivateChatInfos, recentServerGroupMsgs, recentSysMsgs, recentWorldMsgs } from './chatService'; +import { getCurTask, getPvpTask } from './task/taskService'; + +import { RoleModel, RoleType } from '@db/Role'; +import { Application, BackendSession, FrontendOrBackendSession, pinus, RpcClient } from 'pinus'; +import { compareVersion, getRandEelmWithWeight, resResult } from '@pubUtils/util'; +import { STATUS, PUSH_BATCH, PUSH_INTERVAL, CONSUME_TYPE, HERO_SELECT, ENTERY_ROLE_PICK, JEWEL_SELECT, ITEM_SELECT, SKIN_SELECT, PUSH_ROUTE, ARTIFACT_SELECT, ACTIVITYITEM_SELECT, SNS_LINK_TYPE, VESTIGE_STATUS, HERO_SYSTEM_TYPE } from '@consts'; +import { getAllShopList } from './shopService'; +import { getGeneralRank, getRankFirstReward } from './rankService'; +import { getFriendList, getApplyList } from './friendService'; +import { getDailyBattleList } from './dailyBattleService'; +import { getExpeditionStatus } from './expeditionService'; +import { getTowerStatus, getHungupRewards, getTasks } from './battleService'; +import { getAllAssistCnt, getCapExtraCnt, getComBtlLvByPlayerLv } from './battle/comBattleService'; +import { getDungeonData } from './dungeonService'; +import { nowSeconds, getZeroPoint, getTimeFunM } from '@pubUtils/timeUtil'; +import { getGachaList, getVisitedHeroList } from './activity/gachaService'; +import { getSchoolList } from './roleService'; +import { addRoleToGuildChannel } from './chatChannelService'; +import { getMyGuildInfo, getUserGuildWithRefActive, getWishPool, getInvitationList } from './guildService'; +import { getAuction } from './auctionService'; +import { getGuildTrainInstance, getTrainBoxRewardsResult } from './guildTrainService'; +import { getBossInstanceInfo } from './guildBossService'; +import { getEvent } from './eventSercive'; +import { getBattleListOfMain, getMainChapter } from './normalBattleService'; +import { GuildModel, GuildType } from '@db/Guild'; +import UserGuild, { UserGuildType } from '@db/UserGuild'; +import { getAllGuildActivityStatus } from './guildActivity/guildActivityService'; +import { checkRecalJewelOpen, getAllOnlineRoles, getAllServers, incConnectorNum, redisClient } from './redisService'; +import Item, { ItemModel } from '@db/Item'; +import { PvpDefenseModel } from '@db/PvpDefense'; +import { getDonation } from './donateService'; +import { refChallengeCnt, sendLastSeasonRewardIfNotSent } from './pvpService'; +import { HeroModel, HeroType } from '@db/Hero'; +import { JewelModel, JewelType } from '@db/Jewel'; +import { SkinModel, SkinType } from '@db/Skin'; +import { getAp } from './actionPointService'; +import { HeroParam } from '@domain/roleField/hero'; +import { pick } from 'underscore'; +import { sendMessageToAllWithSuc, sendMessageToServerWithSuc, sendMessageToUser, sendMessageToUserWithSuc } from './pushService'; +import { getSurvey } from './gmService'; +import { ComBattleTeamModel } from '@db/ComBattleTeam'; +import { INFO_WINDOW } from '@pubUtils/dicParam'; +import { getLadderData } from './ladderService'; +import { dispatch } from '@pubUtils/dispatcher'; +import { PvpDataReturn } from '@domain/battleField/pvp'; +import { ArtifactModel, ArtifactModelType } from '@db/Artifact'; +import { ActivityItemModel } from '@db/ActivityItem'; +import { LinkModel } from '@db/Link'; +import { getHiddenData } from './memoryCache/hiddenData'; +import { AuthorBookModel } from '@db/AuthorBook'; +import { gameData } from '@pubUtils/data'; +import { getRougeData } from './battle/rougeService'; +import { LadderMatchRecModel } from '@db/LadderMatchRec'; +import { GVGVestigeRecModel, GVGVestigeRecUpdate } from '@db/GVGVestigeRec'; +import { getVestigeRecStatus } from './gvg/gvgFightService'; +import { getRemoteRplPrefix } from '@pubUtils/battleUtils'; +import { calculateCeWithRole } from './playerCeService'; +import { SchoolModel } from '@db/School'; +import { getResonanceDataMap } from './role/resonanceService'; + +/** + * init: 初始的时候是否推送 true-推 false-不推 + * refresh: 凌晨5点刷新时是否推送 true-推 false-不推 + * guild: 是否一定有了军团才要推送 true-必须要 false-不用 + */ +const modules = [ + { id: 1, type: 'role', init: true, refresh: true, guild: false }, + { id: 2, type: 'battle', init: true, refresh: false, guild: false }, + { id: 3, type: 'chapter', init: true, refresh: false, guild: false }, + { id: 4, type: 'rank', init: false, refresh: false, guild: false }, + { id: 5, type: 'mail', init: false, refresh: false, guild: false }, + { id: 6, type: 'friend', init: false, refresh: true, guild: false }, + { id: 7, type: 'daily', init: false, refresh: true, guild: false }, + { id: 8, type: 'expedition', init: false, refresh: true, guild: false }, + { id: 9, type: 'tower', init: false, refresh: true, guild: false }, + { id: 10, type: 'comBattle', init: false, refresh: true, guild: false }, + { id: 11, type: 'dungeon', init: false, refresh: true, guild: false }, + { id: 12, type: 'pvp', init: false, refresh: true, guild: false }, + { id: 13, type: 'gacha', init: false, refresh: true, guild: false }, + // { id: 14, type: 'school', init: false, refresh: false, guild: false }, + { id: 15, type: 'task', init: false, refresh: true, guild: false }, + { id: 16, type: 'chat', init: false, refresh: false, guild: false }, + // { id: 17, type: 'event', init: false, refresh: true, guild: false }, + { id: 18, type: 'guild', init: false, refresh: true, guild: false }, + { id: 19, type: 'auction', init: false, refresh: false, guild: true }, + { id: 20, type: 'train', init: false, refresh: true, guild: true }, + { id: 21, type: 'boss', init: false, refresh: true, guild: true }, + { id: 22, type: 'wishPool', init: false, refresh: true, guild: true }, + { id: 23, type: 'guildActivity', init: false, refresh: true, guild: true }, + { id: 24, type: 'donate', init: false, refresh: true, guild: true }, + { id: 25, type: 'shop', init: false, refresh: true, guild: false }, + { id: 26, type: 'survey', init: false, refresh: true, guild: false }, + { id: 27, type: 'ladder', init: false, refresh: true, guild: false }, + { id: 28, type: 'hiddenData', init: true, refresh: true, guild: false }, + { id: 29, type: 'rouge', init: true, refresh: true, guild: false }, + { id: 30, type: 'iconShow', init: true, refresh: true, guild: false }, + +] + +export async function pushData(hasInit: boolean, role: RoleType, session: FrontendOrBackendSession, pushType: 'entry' | 'refresh' = 'entry') { + try { + const { roleId } = role; + const sid = session.get('sid'); + + pushEntryStart(roleId, sid); + // 军团 + const guildData = await getGuildEntryData(role, sid, session); + for (let { type, init, refresh, guild } of modules) { + if (!hasInit && !init) continue; + if (pushType == 'refresh' && !refresh) continue; + if (!guildData.hasGuild && guild) continue; + + let data = await getModuleData(type, { role, session }, guildData); + if (data) { + pushEntryData(type, roleId, sid, data); + } + } + + pushEntryEnd(roleId, sid); + } catch (e) { + console.error(e.stack); + } +} + +export async function getModuleData(type: string, data: { role: RoleType, session: FrontendOrBackendSession }, guildData: { hasGuild: boolean, guild?: GuildType, userGuild?: UserGuildType, guildResult?: any } = { hasGuild: false }) { + try { + let { role, session } = data; + const { roleId, serverId, roleName, guildCode } = role; + let { hasGuild, guild, userGuild, guildResult } = guildData; + switch (type) { + case 'role': + let heros = await HeroModel.findByRole(role.roleId, [], HERO_SELECT.ENTRY, true); + let jewels = await JewelModel.findbyRole(role.roleId, JEWEL_SELECT.ENTRY); + let items = await ItemModel.findbyRole(role.roleId, ITEM_SELECT.ENTRY); + let skins = await SkinModel.findbyRole(role.roleId, SKIN_SELECT.ENTRY); + let artifacts = await ArtifactModel.findbyRole(role.roleId, ARTIFACT_SELECT.ENTRY); + let activityItems = await ActivityItemModel.findbyRole(role.roleId, ACTIVITYITEM_SELECT.ENTRY); + let link = await LinkModel.findByType(SNS_LINK_TYPE.CUSTOMER); + + await reCalJewel(role, heros, jewels, skins, artifacts); + let { dbResonanceMap } = await getResonanceDataMap(role.roleId); + + role['heros'] = heros.map(hero => new HeroParam(hero)); + for (let hero of role['heros']) { + hero.isResonance = false; + if (dbResonanceMap.has(hero.hid)) { + hero.isResonance = true; + } + } + + role['jewels'] = jewels; + role['consumeGoods'] = items; + role['skins'] = skins; + let apJson = await getAp(role.roleId, '', role.lv); + role['apJson'] = apJson; + role['ipLocation'] = role.fixedIpLocation || role.ipLocation || '未知'; + role['artifacts'] = artifacts; + role['activityItems'] = activityItems; + role['authorBook'] = await getAuthorBook(role.roleId); + + if (!role.showLineup) role.showLineup = role.topLineup.map(cur => cur.hid); + role.heads = role.heads.filter(cur => cur.status); + role.frames = role.frames.filter(cur => cur.status); + role.spines = role.spines.filter(cur => cur.status); + role['customerLink'] = link?.link || ''; + return pick(role, ENTERY_ROLE_PICK); + case 'shop': // 商店 + return await getAllShopList(roleId, serverId); + case 'rank': // 排名 + const rewards = await getRankFirstReward(role, serverId); + return { rewards } + case 'mail': // 邮件 + return await getMails(roleId, serverId); + case 'friend': // 好友 + const friendList = await getFriendList(role); + const applyList = await getApplyList(roleId); + return { friendList, applyList } + case 'daily': // 每日 + return await getDailyBattleList(role); + case 'expedition': // 远征 + return await getExpeditionStatus(roleId, roleName, true); + case 'tower': // 镇念塔 + return await getTowerEntryData(role); + case 'comBattle': // 寻宝 + return await getComBattleEntryData(role, guildCode); + case 'dungeon': // 秘境 + return await getDungeonData(role); + case 'pvp': // pvp + return await getPvpEntryData(roleId); + case 'gacha': + const gachalist = await getGachaList(roleId); + const visitList = await getVisitedHeroList(roleId); + return { hasInit: true, gachalist, visitList } + case 'school': + return await getSchoolList(roleId); + case 'guild': + let invitation = await getInvitationList(roleId, ''); + return { ...guildResult, invitation }; + case 'auction': + return hasGuild ? await getAuction(guildCode, session) : null; + case 'train': + if (hasGuild) { + let trainInstance = await getGuildTrainInstance(roleId, guild, userGuild); + if (!trainInstance) return null; + let trainBoxRewards = await getTrainBoxRewardsResult(guildCode); + return { trainInstance, trainBoxRewards } + } + break; + case 'boss': + if (hasGuild) { + return await getBossInstanceInfo(userGuild, guild); + } + return null; + case 'wishPool': + return hasGuild ? await getWishPool(userGuild) : null; + case 'donate': + if (hasGuild) { + const { guildCode: code, donateCnt, receiveBoxs } = userGuild; + let { donateFund, reports, donationLv } = await getDonation(code, guild); + return { receiveBoxs, donateFund, reports, donateCnt: donateCnt || 0, donationLv }; + } + break; + case 'task': + let tasks = await getCurTask(role.roleId, session); + let pvpTask = await getPvpTask(role.roleId); + return { ...tasks, pvpTask } + case 'chat': + const worldMsgs = await recentWorldMsgs(serverId); + const sysMsgs = await recentSysMsgs(serverId); + const guildMsgs = await recentGuildMsgs(guildCode); + const gvgMsgs = await recentServerGroupMsgs(serverId); + const leagueMsgs = await recentLeagueMsgs(guildCode); + const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName); + return { worldMsgs, sysMsgs, guildMsgs, gvgMsgs, leagueMsgs, recentPrivateChats }; + case 'event': + return await getEvent(role.eventStatus, roleId, roleName); + case 'battle': + return await getBattleListOfMain(role); + case 'guildActivity': + return getAllGuildActivityStatus(role.guildCode, role.serverId); + case 'chapter': + return getMainChapter(role); + case 'survey': + return await getSurvey(role.roleId, role.lv); + case 'ladder': + return await getLadderData(role.roleId, false); + case 'hiddenData': + return getHiddenData(); + case 'rouge': + return await getRougeData(role.roleId); + case 'iconShow': + return await getIconShow(role.roleId, session); + default: + return null; + } + } catch (e) { + console.error(e.stack); + return false + } +} + +function pushEntryData(type: string, roleId: string, sid: string, param: T) { + let data = { type }; + data[type] = param; + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA, data, sid); +} + +function pushEntryStart(roleId: string, sid: string) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA_START, {}, sid); +} + +function pushEntryEnd(roleId: string, sid: string) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ENTRY_DATA_END, {}, sid); +} + + +/** + * 镇念塔初始数据 + * @param role + */ +async function getTowerEntryData(role: RoleType) { + const { roleId } = role; + const status = await getTowerStatus(role); + const hungUp = await getHungupRewards(roleId); + if (!hungUp) { + return { status, hungUp: {} } + } else { + return { status, hungUp: hungUp } + } +} + +/** + * 获取是否存在pvp赛季奖励 + * @param roleId + */ +async function getPvpEntryData(roleId: string) { + let seasonNum: number = pinus.app.get('pvpSeasonNum'); + let seasonEndTime: number = pinus.app.get('pvpSeasonEndTime'); + let seasonStartTime: number = pinus.app.get('pvpSeasonStartTime'); + let seasonRewardTime: number = pinus.app.get('pvpSeasonRewardTime'); + + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + if (pvpDefense) { + pvpDefense = await sendLastSeasonRewardIfNotSent(pvpDefense); + + let result = new PvpDataReturn(); // 返回对象 + result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); + result.setPvpDefense(pvpDefense); + result.calHasSaveDefense(); + let refChallengeObj = await refChallengeCnt(pvpDefense.challengeCnt, pvpDefense.challengeRefTime, seasonEndTime, roleId); + let { challengeCnt } = refChallengeObj; + result.setChallengeCnt(challengeCnt); + return pick(result, ['challengeCnt', 'score', 'seasonWinNum', 'receivedBox', 'hasSaveDefense', 'seasonNum', 'seasonEndTime', 'seasonStartTime', 'seasonRewardTime']) + } else { + let result = new PvpDataReturn(); // 返回对象 + result.setPvpConfig(seasonNum, seasonStartTime, seasonEndTime, seasonRewardTime); + return pick(result, ['seasonNum', 'seasonEndTime', 'seasonStartTime', 'seasonRewardTime']) + } +} + +/** + * 获取军团信息,并加入军团频道 + * @param role + * @param sid + * @param session + */ +async function getGuildEntryData(role: RoleType, sid: string, session: FrontendOrBackendSession) { + + if (role.hasGuild) { + let userGuild = await getUserGuildWithRefActive(role.roleId); + if (userGuild) { + let guild = await GuildModel.findByCode(userGuild.guildCode, role.serverId); + if (guild) { + addRoleToGuildChannel(role.roleId, sid, userGuild.guildCode); + + let result = await getMyGuildInfo(role.roleId, sid, userGuild, guild, role.serverId, session); + return { hasGuild: true, guild, userGuild, guildResult: result }; + } + } + } + return { hasGuild: false } +} + +async function getComBattleEntryData(role: RoleType, guildCode: string) { + let { roleId, lv, topLineupCe } = role; + const assistCnt = await getAllAssistCnt(roleId); + const blueprts = await Item.findByRoleAndType(roleId, CONSUME_TYPE.BLUEPRT); + let { minLv, maxLv } = getComBtlLvByPlayerLv(lv); + let refreshTime = nowSeconds() - INFO_WINDOW.TEAM_INFORMATION_TIME; + const invitations = await ComBattleTeamModel.findInvitations(roleId, guildCode, minLv, maxLv, topLineupCe, refreshTime, 1); + let capExtraCnt = await getCapExtraCnt(roleId); + return { assistCnt, blueprts, hasInvitation: invitations.length > 0, invitationTime: invitations.length > 0 ? invitations[0].inviteTime : 0, capExtraCnt } +} + +export async function pushRefreshTime() { + let todayZeroPoint = getZeroPoint(); + await sendMessageToAllWithSuc(PUSH_ROUTE.REFRESH_TIME, { todayZeroPoint }); +} + +export async function kickUser(app: Application, uid: string, message = STATUS.LOGIN_ERR) { + let sessionService = app.get('sessionService'); + let sessions = sessionService.getByUid(uid); + if (!!sessions) { + sessions.forEach(session => { + let roleId = session.get('roleId'); + let sid = session.get('sid'); + sendMessageToUser(roleId, PUSH_ROUTE.REMOTE_LOGIN, resResult(message), sid); + }); + } + await sessionService.akick(uid); +} + +export async function assignServer(roleId: string, session: FrontendOrBackendSession) { + try { + let activity = await _assignServer(roleId, 'activity'); + let battle = await _assignServer(roleId, 'battle'); + let chat = await _assignServer(roleId, 'chat'); + let guild = await _assignServer(roleId, 'guild'); + let role = await _assignServer(roleId, 'role'); + let order = await _assignServer(roleId, 'order'); + let comBattle = await _assignServer(roleId, 'comBattle'); + if (activity) { + session.set('activityServer', activity); + session.push('activityServer', () => { }); + } + if (battle) { + session.set('battleServer', battle); + session.push('battleServer', () => { }); + } + if (chat) { + session.set('chatServer', chat); + session.push('chatServer', () => { }); + } + if (guild) { + session.set('guildServer', guild); + session.push('guildServer', () => { }); + } + if (role) { + session.set('roleServer', role); + session.push('roleServer', () => { }); + } + if (order) { + session.set('orderServer', order); + session.push('orderServer', () => { }); + } + if (comBattle) { + session.set('comBattleServer', comBattle); + session.push('comBattleServer', () => { }); + } + } catch (e) { + console.log(e) + } +} + +async function _assignServer(roleId: string, serverType: string) { + let servers = pinus.app.getServersByType(serverType) || []; + let sum = servers.reduce((pre, cur) => pre + (cur['num'] || 0), 0); + let id = ''; + if (sum > 0) { + let serversWithWeight = servers.map(cur => ({ ...cur, weight: sum - (cur['num'] || 0) })); + let { dic: server } = getRandEelmWithWeight(serversWithWeight); + id = server?.id; + } + if (!id) { + id = (await dispatch(redisClient(), roleId, servers, serverType))?.id; + } + return id +} + +export function incServerNum(sid: string, inc: number) { + if (!pinus.app.getServerById(sid)) return; + if (!pinus.app.getServerById(sid)['num']) { + pinus.app.getServerById(sid)['num'] = 0; + } + pinus.app.getServerById(sid)['num'] += inc; + if (pinus.app.getServerById(sid)['num'] < 0) { + pinus.app.getServerById(sid)['num'] = 0; + } +} + +export async function leaveServer(session: FrontendOrBackendSession) { + let activity = session.get('activityServer'); + let battle = session.get('battleServer'); + let chat = session.get('chatServer'); + let guild = session.get('guildServer'); + let role = session.get('roleServer'); + let order = session.get('orderServer'); + let sid = session.get('sid'); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(activity, -1); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(battle, -1); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(chat, -1); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(guild, -1); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(role, -1); + pinus.app.rpc.connector.connectorRemote.incServerNum.broadcast(order, -1); + + incServerNum(sid, -1); + incConnectorNum(sid, -1); +} + +async function getAuthorBook(roleId: string) { + let result: { bookId: number, authors: { subId: number, star: number }[], progress: number, maxProgress: number }[] = []; + let authorBooks = await AuthorBookModel.findByRoleId(roleId); + for (let [bookId, maxProgress] of gameData.authorBookMaxProgress) { + let authorBook = authorBooks.find(cur => cur.bookId == bookId); + result.push({ bookId, authors: authorBook?.authors ?? [], progress: authorBook?.progress ?? 0, maxProgress }); + } + return result +} + +async function getIconShow(roleId: string, session:FrontendOrBackendSession) { + let quitTime = session.get('quitTime'); + if (!roleId) return; + let ladderIconShow = await LadderMatchRecModel.findRecByRoleId(roleId, quitTime); + + let list = await GVGVestigeRecModel.findRecCurDay(roleId, Math.max(quitTime, getZeroPoint()*1000)); + let result: (GVGVestigeRecUpdate & { rplFileUrl: string })[] = []; + for (let rec of list) { + const { attackRoleId, battleCode, hasRpl, remoteUrl } = rec; + const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; + const obj = getVestigeRecStatus(rec); + if (obj.status == VESTIGE_STATUS.COMPLETE && result.length < 10) result.push({ ...rec, endTime: obj.time, rplFileUrl }); + } + let gvgFightRecs = { list: result, rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) }; + + return { ladderIconShow, gvgFightRecs } +} + +export async function pushIconShow(roleId: string, ladderIconShow?: boolean, gvgFightRecs?) { + if (!roleId) return; + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LADDER_OR_GVG_ICON_SHOW, { ladderIconShow, gvgFightRecs }); +} + +export async function reCalJewel(role: RoleType, heroes: HeroType[], jewels: JewelType[], skins: SkinType[], artifacts: ArtifactModelType[]) { + if (role.hasTreat || !await checkRecalJewelOpen()) return + role = await RoleModel.updateRoleInfo(role.roleId, { hasTreat: true }); + for (let jewel of jewels) { + let hero = heroes.find(hero => { + let ePlace = hero.ePlace.find(e => e.jewel == jewel.seqId); + return !!ePlace; + }); + if (hero && hero.hid != jewel.hid) { + let ePlace = hero.ePlace.find(e => e.jewel == jewel.seqId); + if (ePlace) { + await JewelModel.updateInfo(jewel.seqId, { hid: hero.hid, ePlaceId: ePlace.id }); + jewel.hid = hero.hid; jewel.ePlaceId = ePlace.id; + } + } + } + let schools = await SchoolModel.findByRoleId(role.roleId); + await calculateCeWithRole(HERO_SYSTEM_TYPE.RE_CAL, role.roleId, role.serverId, null, {}, { role, schools, jewels, heroes, skins, artifacts }); +} diff --git a/game-server/app/services/dailyBattleService.ts b/game-server/app/services/dailyBattleService.ts index 56a2b5d31..e59282749 100644 --- a/game-server/app/services/dailyBattleService.ts +++ b/game-server/app/services/dailyBattleService.ts @@ -1,139 +1,139 @@ -/** - * 每日本相关 - */ - -import DailyRecord, { DailyRecordModel } from '../db/DailyRecord'; -import { resResult } from '../pubUtils/util'; -import { STATUS } from '../consts/statusCode'; -import { RoleModel, RoleType } from '../db/Role'; -import { gameData } from '../pubUtils/data'; -import { DicWar } from '../pubUtils/dictionary/DicWar'; -import { WarStar } from '../domain/dbGeneral'; -import * as dicParam from '../pubUtils/dicParam'; -import { calculateWarStar } from './normalBattleService'; -import { getVipDailyCnt } from './activity/monthlyTicketService'; - -/** - * 获取全部每日关卡列表 - * @param role - */ -export async function getDailyBattleList(role: RoleType) { - let { roleId, warStar } = role; - let dicDaily = gameData.daily; - - let result = new Array(); - for(let {dailyType: type, timesPerDay, timesCanBuy, name } of dicDaily) { - let refreshResult = await DailyRecordModel.refreshRecord(roleId, type); - let wars: {battleId: number, cost: number, star: number, status: number}[] = new Array(); - let dicDailyWar = gameData.dailyWarByType.get(type); - for(let dic of dicDailyWar) { - let war = getDailyWarStatus(dic, warStar); - wars.push(war); - } - let checkDailyResult = await getDailyNum(refreshResult, role); - result.push({ - type, name, ...checkDailyResult, - wars - }); - } - return result; -} - -function getDailyWarStatus(dicDailyWar: DicWar, warStar: WarStar[]) { - let {war_id, cost, previousGk } = dicDailyWar; - let status = 0, star = 0; - let curBattle = warStar.find(cur => cur.id == war_id); - if(curBattle) { - status = 2; - star = curBattle.star; - } else { - if (previousGk) { - let preBattleRecord = warStar.find(cur => cur.id == previousGk); - if(preBattleRecord) { - status = 1; - } else { - status = 0; - } - } else { - status = 1; - } - } - return { - battleId: war_id, cost, star, status - } -} - -// 检查每日本次数checkBattle使用 -export async function checkDaily(roleId: string, battleId: number, inc: number) { - let dailyWar = gameData.war.get(battleId); - if(!dailyWar) return { status: -1, resResult: resResult(STATUS.DAILY_WAR_NOT_FOUND) }; - let type = dailyWar.dailyType; - - let curDaily = gameData.daily.find(cur => cur.dailyType == type); - if(!curDaily) return { status: -1, resResult: resResult(STATUS.DAILY_TYPE_NOT_FOUND) }; - let dailyRecord = await DailyRecordModel.refreshRecord(roleId, type); - let checkDailyResult = await getDailyNum(dailyRecord); - let { count = 0 } = checkDailyResult; - if(count < inc) { - return { status: -1, resResult: resResult(STATUS.DAILY_TIMES_LACK) } - } - return {status: 1, data: {type, ...checkDailyResult }}; -} - -/** - * 检查每日本次数并添加,warEnd和warSweep使用 - * @param roleId - * @param battleId - * @param inc 增加的次数 - * @param isRef 在计算之前是否检查每日的刷新 - */ - -export async function checkDailyAndIncrease(roleId: string, warStar: WarStar[], battleId: number, inc: number, isRef: boolean, stars = [], role?: RoleType) { - let { newWarStars } = calculateWarStar(warStar, battleId, stars); - - let dailyWar = gameData.war.get(battleId); - if(!dailyWar) return { status: -1, resResult: resResult(STATUS.DAILY_WAR_NOT_FOUND) }; - let type = dailyWar.dailyType; - let war = getDailyWarStatus(dailyWar, newWarStars); - - let dailyRecord: any; - if(isRef) { - dailyRecord = await DailyRecordModel.refreshRecord(roleId, type); - } else { // 如果是手动挑战,由于在进入时已经检查过了,所以即使结算时过去了一天也还是累计在上一天 - dailyRecord = await DailyRecordModel.getDailyRecordById(roleId, type); - } - - let { count } = await getDailyNum(dailyRecord, role); - if(count < inc) { - return { status: -1, resResult: resResult(STATUS.DAILY_TIMES_LACK) } - } - let result = await DailyRecordModel.increseDailyCount(roleId, type, inc); - let checkDailyResult = await getDailyNum(result); - return {status: 1, data: {type, ...checkDailyResult, war}}; -} - -export async function getDailyNum(dailyRecord: DailyRecord, role?: RoleType) { - let {roleId, type, count = 0, buyCount = 0} = dailyRecord; - const curDaily = gameData.daily.find(cur => cur.dailyType == type); - let {timesPerDay, timesCanBuy} = curDaily; - - if(!role) { - role = await RoleModel.findByRoleId(roleId, 'vipStartTime'); - } - timesPerDay = getVipDailyCnt(timesPerDay, role); - // console.log('###### getDailyNum', timesPerDay, count, buyCount, timesCanBuy) - return {count: timesPerDay - count + buyCount, buyCount: timesCanBuy - buyCount} -} - -/** - * 每日购买次数的花费 - * @param num 如果没有买过次数,那么这里算第一次,传1 - * @returns - */ -export function getDailyBuyCountCost(num: number) { - let cost = ( num - 1 ) * dicParam.DAILY_CONST.DAILY_CONST_UP + dicParam.DAILY_CONST.DAILY_CONST_BASE; - if(cost > dicParam.DAILY_CONST.DAILY_CONST_TOP) { - cost = dicParam.DAILY_CONST.DAILY_CONST_TOP; - } - return cost; -} \ No newline at end of file +/** + * 每日本相关 + */ + +import DailyRecord, { DailyRecordModel } from '@db/DailyRecord'; +import { resResult } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { RoleModel, RoleType } from '@db/Role'; +import { gameData } from '@pubUtils/data'; +import { DicWar } from '@pubUtils/dictionary/DicWar'; +import { WarStar } from '@domain/dbGeneral'; +import * as dicParam from '@pubUtils/dicParam'; +import { calculateWarStar } from './normalBattleService'; +import { getVipDailyCnt } from './activity/monthlyTicketService'; + +/** + * 获取全部每日关卡列表 + * @param role + */ +export async function getDailyBattleList(role: RoleType) { + let { roleId, warStar } = role; + let dicDaily = gameData.daily; + + let result = new Array(); + for(let {dailyType: type, timesPerDay, timesCanBuy, name } of dicDaily) { + let refreshResult = await DailyRecordModel.refreshRecord(roleId, type); + let wars: {battleId: number, cost: number, star: number, status: number}[] = new Array(); + let dicDailyWar = gameData.dailyWarByType.get(type); + for(let dic of dicDailyWar) { + let war = getDailyWarStatus(dic, warStar); + wars.push(war); + } + let checkDailyResult = await getDailyNum(refreshResult, role); + result.push({ + type, name, ...checkDailyResult, + wars + }); + } + return result; +} + +function getDailyWarStatus(dicDailyWar: DicWar, warStar: WarStar[]) { + let {war_id, cost, previousGk } = dicDailyWar; + let status = 0, star = 0; + let curBattle = warStar.find(cur => cur.id == war_id); + if(curBattle) { + status = 2; + star = curBattle.star; + } else { + if (previousGk) { + let preBattleRecord = warStar.find(cur => cur.id == previousGk); + if(preBattleRecord) { + status = 1; + } else { + status = 0; + } + } else { + status = 1; + } + } + return { + battleId: war_id, cost, star, status + } +} + +// 检查每日本次数checkBattle使用 +export async function checkDaily(roleId: string, battleId: number, inc: number) { + let dailyWar = gameData.war.get(battleId); + if(!dailyWar) return { status: -1, resResult: resResult(STATUS.DAILY_WAR_NOT_FOUND) }; + let type = dailyWar.dailyType; + + let curDaily = gameData.daily.find(cur => cur.dailyType == type); + if(!curDaily) return { status: -1, resResult: resResult(STATUS.DAILY_TYPE_NOT_FOUND) }; + let dailyRecord = await DailyRecordModel.refreshRecord(roleId, type); + let checkDailyResult = await getDailyNum(dailyRecord); + let { count = 0 } = checkDailyResult; + if(count < inc) { + return { status: -1, resResult: resResult(STATUS.DAILY_TIMES_LACK) } + } + return {status: 1, data: {type, ...checkDailyResult }}; +} + +/** + * 检查每日本次数并添加,warEnd和warSweep使用 + * @param roleId + * @param battleId + * @param inc 增加的次数 + * @param isRef 在计算之前是否检查每日的刷新 + */ + +export async function checkDailyAndIncrease(roleId: string, warStar: WarStar[], battleId: number, inc: number, isRef: boolean, stars = [], role?: RoleType) { + let { newWarStars } = calculateWarStar(warStar, battleId, stars); + + let dailyWar = gameData.war.get(battleId); + if(!dailyWar) return { status: -1, resResult: resResult(STATUS.DAILY_WAR_NOT_FOUND) }; + let type = dailyWar.dailyType; + let war = getDailyWarStatus(dailyWar, newWarStars); + + let dailyRecord: any; + if(isRef) { + dailyRecord = await DailyRecordModel.refreshRecord(roleId, type); + } else { // 如果是手动挑战,由于在进入时已经检查过了,所以即使结算时过去了一天也还是累计在上一天 + dailyRecord = await DailyRecordModel.getDailyRecordById(roleId, type); + } + + let { count } = await getDailyNum(dailyRecord, role); + if(count < inc) { + return { status: -1, resResult: resResult(STATUS.DAILY_TIMES_LACK) } + } + let result = await DailyRecordModel.increseDailyCount(roleId, type, inc); + let checkDailyResult = await getDailyNum(result); + return {status: 1, data: {type, ...checkDailyResult, war}}; +} + +export async function getDailyNum(dailyRecord: DailyRecord, role?: RoleType) { + let {roleId, type, count = 0, buyCount = 0} = dailyRecord; + const curDaily = gameData.daily.find(cur => cur.dailyType == type); + let {timesPerDay, timesCanBuy} = curDaily; + + if(!role) { + role = await RoleModel.findByRoleId(roleId, 'vipStartTime'); + } + timesPerDay = getVipDailyCnt(timesPerDay, role); + // console.log('###### getDailyNum', timesPerDay, count, buyCount, timesCanBuy) + return {count: timesPerDay - count + buyCount, buyCount: timesCanBuy - buyCount} +} + +/** + * 每日购买次数的花费 + * @param num 如果没有买过次数,那么这里算第一次,传1 + * @returns + */ +export function getDailyBuyCountCost(num: number) { + let cost = ( num - 1 ) * dicParam.DAILY_CONST.DAILY_CONST_UP + dicParam.DAILY_CONST.DAILY_CONST_BASE; + if(cost > dicParam.DAILY_CONST.DAILY_CONST_TOP) { + cost = dicParam.DAILY_CONST.DAILY_CONST_TOP; + } + return cost; +} diff --git a/game-server/app/services/dataService.ts b/game-server/app/services/dataService.ts index 71e4fdbf2..d5a04142f 100644 --- a/game-server/app/services/dataService.ts +++ b/game-server/app/services/dataService.ts @@ -1,83 +1,83 @@ -import { pinus } from 'pinus'; -import { isEqual } from 'underscore'; -import { ITEM_CHANGE_REASON, PUSH_ROUTE } from '../consts'; -import { HiddenDataModelType } from '../db/HiddenData'; -import { sendMessageToAllServersWithSuc } from './pushService'; -import { itemLogger } from '../util/logger'; -import { getHiddenData, setHiddenData } from './memoryCache/hiddenData'; - -export async function setHiddenDataToMemory(data: HiddenDataModelType, nextData: HiddenDataModelType) { - let heroes = data?.heroes??[]; - let goods = data?.goods??[]; - let refTime = nextData?.refTime||0; - sendUpdateMessage(getHiddenData(), heroes, goods, refTime); - pinus.app.rpc.activity.activityRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.battle.battleRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.comBattle.comBattleRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.chat.chatRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.connector.connectorRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.guild.guildRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.order.orderRemote.setHiddenData.broadcast(heroes, goods, refTime); - pinus.app.rpc.role.roleRemote.setHiddenData.broadcast(heroes, goods, refTime); - if(pinus.app.getServerType() != 'gm') { - pinus.app.rpc.gm.gmRemote.setHiddenData.broadcast(heroes, goods, refTime); - } - if(pinus.app.getServerType() != 'systimer') { - pinus.app.rpc.systimer.systimerRemote.setHiddenData.broadcast(heroes, goods, refTime); - } - setHiddenData(heroes, goods, refTime); -} - -async function sendUpdateMessage(origin: {heroes: number[], items: number[], refTime: number}, heroes: number[], goods: number[], refTime: number) { - console.log('##### sendUpdateMessage', origin.refTime, refTime, origin.heroes, heroes, origin.items, goods) - if(origin.refTime != refTime || !isEqual(origin.heroes, heroes) || !isEqual(origin.items, goods)) { - console.log('******'); - await sendMessageToAllServersWithSuc(PUSH_ROUTE.HIDDEN_DATA, { heroes, items: goods, refTime }); - } -} - -export function filterHeroes(arr: T[], cb?: (obj: T) => number, roleId?: string) { - return arr.filter(obj => { - let hid = cb? cb(obj): (typeof obj == 'number'? obj: 0); - let { heroes } = getHiddenData(); - if(heroes.indexOf(hid) != -1) { - if(roleId) itemLogger.error(`玩家 ${roleId} 的武将 ${hid} 未获得`); - return false; - } - return true; - }); -} - -export function filterGoods(arr: T[], cb?: (obj: T) => number, roleId?: string, reason?: ITEM_CHANGE_REASON) { - return arr.filter(obj => { - let gid = cb? cb(obj): (typeof obj == 'number'? obj: 0); - let { items } = getHiddenData(); - if(items.indexOf(gid) != -1) { - if(roleId) itemLogger.error(`玩家 ${roleId} 的道具 ${gid} 未获得 (${reason})`); - return false; - } - return true; - }); -} - -export function isHeroHidden(...hids: number[]) { - for(let hid of hids) { - let { heroes } = getHiddenData(); - if(heroes.indexOf(hid) != -1) { - itemLogger.error(`武将 ${hid} 被拦截`); - return true; - } - } - return false; -} - -export function isGoodsHidden(...gids: number[]) { - for(let gid of gids) { - let { items } = getHiddenData(); - if(items.indexOf(gid) != -1) { - itemLogger.error(`道具 ${gid} 被拦截`); - return true; - } - } - return false; -} \ No newline at end of file +import { pinus } from 'pinus'; +import { isEqual } from 'underscore'; +import { ITEM_CHANGE_REASON, PUSH_ROUTE } from '@consts'; +import { HiddenDataModelType } from '@db/HiddenData'; +import { sendMessageToAllServersWithSuc } from './pushService'; +import { itemLogger } from '../util/logger'; +import { getHiddenData, setHiddenData } from './memoryCache/hiddenData'; + +export async function setHiddenDataToMemory(data: HiddenDataModelType, nextData: HiddenDataModelType) { + let heroes = data?.heroes??[]; + let goods = data?.goods??[]; + let refTime = nextData?.refTime||0; + sendUpdateMessage(getHiddenData(), heroes, goods, refTime); + pinus.app.rpc.activity.activityRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.battle.battleRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.comBattle.comBattleRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.chat.chatRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.connector.connectorRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.guild.guildRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.order.orderRemote.setHiddenData.broadcast(heroes, goods, refTime); + pinus.app.rpc.role.roleRemote.setHiddenData.broadcast(heroes, goods, refTime); + if(pinus.app.getServerType() != 'gm') { + pinus.app.rpc.gm.gmRemote.setHiddenData.broadcast(heroes, goods, refTime); + } + if(pinus.app.getServerType() != 'systimer') { + pinus.app.rpc.systimer.systimerRemote.setHiddenData.broadcast(heroes, goods, refTime); + } + setHiddenData(heroes, goods, refTime); +} + +async function sendUpdateMessage(origin: {heroes: number[], items: number[], refTime: number}, heroes: number[], goods: number[], refTime: number) { + console.log('##### sendUpdateMessage', origin.refTime, refTime, origin.heroes, heroes, origin.items, goods) + if(origin.refTime != refTime || !isEqual(origin.heroes, heroes) || !isEqual(origin.items, goods)) { + console.log('******'); + await sendMessageToAllServersWithSuc(PUSH_ROUTE.HIDDEN_DATA, { heroes, items: goods, refTime }); + } +} + +export function filterHeroes(arr: T[], cb?: (obj: T) => number, roleId?: string) { + return arr.filter(obj => { + let hid = cb? cb(obj): (typeof obj == 'number'? obj: 0); + let { heroes } = getHiddenData(); + if(heroes.indexOf(hid) != -1) { + if(roleId) itemLogger.error(`玩家 ${roleId} 的武将 ${hid} 未获得`); + return false; + } + return true; + }); +} + +export function filterGoods(arr: T[], cb?: (obj: T) => number, roleId?: string, reason?: ITEM_CHANGE_REASON) { + return arr.filter(obj => { + let gid = cb? cb(obj): (typeof obj == 'number'? obj: 0); + let { items } = getHiddenData(); + if(items.indexOf(gid) != -1) { + if(roleId) itemLogger.error(`玩家 ${roleId} 的道具 ${gid} 未获得 (${reason})`); + return false; + } + return true; + }); +} + +export function isHeroHidden(...hids: number[]) { + for(let hid of hids) { + let { heroes } = getHiddenData(); + if(heroes.indexOf(hid) != -1) { + itemLogger.error(`武将 ${hid} 被拦截`); + return true; + } + } + return false; +} + +export function isGoodsHidden(...gids: number[]) { + for(let gid of gids) { + let { items } = getHiddenData(); + if(items.indexOf(gid) != -1) { + itemLogger.error(`道具 ${gid} 被拦截`); + return true; + } + } + return false; +} diff --git a/game-server/app/services/donateService.ts b/game-server/app/services/donateService.ts index 82addb72c..b82e8adca 100644 --- a/game-server/app/services/donateService.ts +++ b/game-server/app/services/donateService.ts @@ -1,88 +1,88 @@ - -import { DonationModel, Report } from '../db/Donation'; -import { getZeroPoint, nowSeconds } from '../pubUtils/timeUtil'; -import { GuildModel, GuildType } from '../db/Guild'; -import { findWhere } from 'underscore'; -import { GUILD_STRUCTURE } from '../consts/constModules/guildConst'; -import { gameData } from '../pubUtils/data'; -import { shouldRefresh } from '../pubUtils/util'; -import { recordGuildFund } from './activity/timeLimitRankService'; -import { pushGuildInfoUpdate } from './guildService'; -import { getArmyDonateBoxBaseById, getArmyDonateBoxBaseByLvAndIndex } from '../pubUtils/data'; -/** - * 获得军团捐献,并检查是否刷新捐献数据 - * @param code - * @param serverId - */ -export async function getDonation(code: string, guild: GuildType) { - let refTime = getZeroPoint(); - let donation = await DonationModel.findOrCreateDonationByRefTime(code, refTime, getDonateLv(guild)); - return donation; -} - -export async function donate(code: string, fund: number, donateId: number, roleName: string, donateLv: number) { - let refTime = getZeroPoint(); - let donation = await DonationModel.donate(code, refTime, fund, { id: donateId, roleName, time: refTime, fund }, donateLv); - return donation; -} - -export function getDonateLv(guild: GuildType) { - let structure = guild.structure.find(cur => cur.id == GUILD_STRUCTURE.DONATE); - return structure? structure.lv: 0; -} - -export async function getGuildFundByRefTime(guildCode: string, refTime: number) { - let donation = await DonationModel.findDonationByRefTime(guildCode, refTime); - return { donationLv: donation? donation.donationLv: 0, fund: donation? donation.donateFund: 0} -} - -// 增加资金 -export async function addFund(code: string, serverId: number, fund: number) { - try { - let guild = await GuildModel.findByCode(code, serverId, 'lv todayFund refTodayFund'); - let {lv, todayFund, refTodayFund} = guild; - if(!guild) return null - - let dicStructure = gameData.centerBase.get(lv); - if(!dicStructure) return null - if(shouldRefresh(refTodayFund, new Date())) { - todayFund = 0; - refTodayFund = new Date(); - } - if(todayFund + fund > dicStructure.maxFund) { - fund = dicStructure.maxFund - todayFund; - todayFund = dicStructure.maxFund; - } else { - todayFund += fund; - } - if(fund < 0) return null - - guild = await GuildModel.updateInfo(code, { todayFund, refTodayFund }, { fund }); - await pushGuildInfoUpdate(code, { fund: guild.fund }); - await recordGuildFund(serverId, guild, fund); - - return guild - } catch(e) { - return null - } - -} - -/** - * 将已经领取的其他等级捐赠宝箱id转为donationLv对应等级相同index的宝箱id - * - * @export - * @param {number[]} receiveBoxs 已领取的宝箱id - * @param {number} donationLv 当前捐赠等级 - */ -export function changeReceiveBoxIdByLvAndIndex(receiveBoxs: number[], donationLv: number) { - let haveGotBoxIds: number[] = []; - receiveBoxs.forEach((boxId) => { - // 获取已领取箱子的index - let { index } = getArmyDonateBoxBaseById(boxId); - // 获取donationLv等级,第index个箱子的id - let donateInfo = getArmyDonateBoxBaseByLvAndIndex(donationLv, index); - haveGotBoxIds.push(donateInfo ? donateInfo.id : 0); - }); - return haveGotBoxIds; -} \ No newline at end of file + +import { DonationModel, Report } from '@db/Donation'; +import { getZeroPoint, nowSeconds } from '@pubUtils/timeUtil'; +import { GuildModel, GuildType } from '@db/Guild'; +import { findWhere } from 'underscore'; +import { GUILD_STRUCTURE } from '@consts/constModules/guildConst'; +import { gameData } from '@pubUtils/data'; +import { shouldRefresh } from '@pubUtils/util'; +import { recordGuildFund } from './activity/timeLimitRankService'; +import { pushGuildInfoUpdate } from './guildService'; +import { getArmyDonateBoxBaseById, getArmyDonateBoxBaseByLvAndIndex } from '@pubUtils/data'; +/** + * 获得军团捐献,并检查是否刷新捐献数据 + * @param code + * @param serverId + */ +export async function getDonation(code: string, guild: GuildType) { + let refTime = getZeroPoint(); + let donation = await DonationModel.findOrCreateDonationByRefTime(code, refTime, getDonateLv(guild)); + return donation; +} + +export async function donate(code: string, fund: number, donateId: number, roleName: string, donateLv: number) { + let refTime = getZeroPoint(); + let donation = await DonationModel.donate(code, refTime, fund, { id: donateId, roleName, time: refTime, fund }, donateLv); + return donation; +} + +export function getDonateLv(guild: GuildType) { + let structure = guild.structure.find(cur => cur.id == GUILD_STRUCTURE.DONATE); + return structure? structure.lv: 0; +} + +export async function getGuildFundByRefTime(guildCode: string, refTime: number) { + let donation = await DonationModel.findDonationByRefTime(guildCode, refTime); + return { donationLv: donation? donation.donationLv: 0, fund: donation? donation.donateFund: 0} +} + +// 增加资金 +export async function addFund(code: string, serverId: number, fund: number) { + try { + let guild = await GuildModel.findByCode(code, serverId, 'lv todayFund refTodayFund'); + let {lv, todayFund, refTodayFund} = guild; + if(!guild) return null + + let dicStructure = gameData.centerBase.get(lv); + if(!dicStructure) return null + if(shouldRefresh(refTodayFund, new Date())) { + todayFund = 0; + refTodayFund = new Date(); + } + if(todayFund + fund > dicStructure.maxFund) { + fund = dicStructure.maxFund - todayFund; + todayFund = dicStructure.maxFund; + } else { + todayFund += fund; + } + if(fund < 0) return null + + guild = await GuildModel.updateInfo(code, { todayFund, refTodayFund }, { fund }); + await pushGuildInfoUpdate(code, { fund: guild.fund }); + await recordGuildFund(serverId, guild, fund); + + return guild + } catch(e) { + return null + } + +} + +/** + * 将已经领取的其他等级捐赠宝箱id转为donationLv对应等级相同index的宝箱id + * + * @export + * @param {number[]} receiveBoxs 已领取的宝箱id + * @param {number} donationLv 当前捐赠等级 + */ +export function changeReceiveBoxIdByLvAndIndex(receiveBoxs: number[], donationLv: number) { + let haveGotBoxIds: number[] = []; + receiveBoxs.forEach((boxId) => { + // 获取已领取箱子的index + let { index } = getArmyDonateBoxBaseById(boxId); + // 获取donationLv等级,第index个箱子的id + let donateInfo = getArmyDonateBoxBaseByLvAndIndex(donationLv, index); + haveGotBoxIds.push(donateInfo ? donateInfo.id : 0); + }); + return haveGotBoxIds; +} diff --git a/game-server/app/services/dungeonService.ts b/game-server/app/services/dungeonService.ts index fa7a629cf..a06f417b8 100644 --- a/game-server/app/services/dungeonService.ts +++ b/game-server/app/services/dungeonService.ts @@ -1,115 +1,115 @@ -/** - * 每日本相关 - */ - -import { resResult, shouldRefresh, } from '../pubUtils/util'; -import { STATUS } from '../consts/statusCode'; -import { RoleModel, RoleType, WarStar } from '../db/Role'; -import * as dicParam from '../pubUtils/dicParam'; -import { RankParam } from '../domain/rank'; -import { BattleRecordType } from '../db/BattleRecord'; -import { gameData } from '../pubUtils/data'; -import { DungeonFirstModel } from '../db/DungeonFirst'; -import { nowSeconds } from '../pubUtils/timeUtil'; -import { getVipDungeonCnt } from './activity/monthlyTicketService'; - -/** - * 获取秘境本数据 - * @param role - */ -export async function getDungeonData(role: RoleType) { - let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, dungeonHeroes=[] } = role; - let curTime = new Date(); - if(shouldRefresh(dungeonRefTime, curTime)) { - dungeonCnt = 0; dungeonBuyCnt = 0; - } - - let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + 1); - let freeCount = getVipDungeonCnt(role.vipStartTime); - return { - nextCostGold, - dungeonHeroes, - battleCount: freeCount + dungeonBuyCnt - dungeonCnt, - buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - } -} - -function isFirstPass(warStar: WarStar[], warId: number) { - let index = warStar.findIndex(cur => cur.id == warId); - return index == -1; -} - -// 检查秘境本次数checkBattle使用 -export async function checkDungeonNum(roleId: string, inc: number, warId: number) { - let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, vipStartTime, warStar } = await RoleModel.findByRoleId(roleId); - if(isFirstPass(warStar, warId)) inc = 0; - - let curTime = new Date(); - let needRefresh = shouldRefresh(dungeonRefTime, curTime); - if(needRefresh) { - dungeonCnt = 0; dungeonBuyCnt = 0; - } - let freeCount = getVipDungeonCnt(vipStartTime); - if(dungeonCnt + inc > freeCount + dungeonBuyCnt) { - return {status: -1, resResult: resResult(STATUS.DUNGEON_TIMES_LACK)} - } - await RoleModel.increaseDungeonCnt(roleId, needRefresh, 0, curTime); - - return { status: 0, data: { - battleCount: freeCount + dungeonBuyCnt - dungeonCnt, - buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - }}; -} - -/** - * 检查秘境本次数并添加,warEnd和warSweep使用 - * @param roleId - * @param inc 增加的次数 - * @param isRef 在计算之前是否检查每日的刷新 - */ - -export async function checkDungeonAndIncrease(roleId: string, inc: number, isRef: boolean, warId: number) { - - let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, vipStartTime, warStar } = await RoleModel.findByRoleId(roleId); - if(isFirstPass(warStar, warId)) inc = 0; - let curTime = new Date(); - - let needRefresh = isRef && shouldRefresh(dungeonRefTime, curTime); - if(needRefresh) { - dungeonCnt = 0; dungeonBuyCnt = 0; - } - let freeCount = getVipDungeonCnt(vipStartTime); - - if(dungeonCnt + inc > freeCount + dungeonBuyCnt ) { - return { status: -1, resResult: resResult(STATUS.DUNGEON_TIMES_LACK) } - } - // console.log('needRefresh', needRefresh); - await RoleModel.increaseDungeonCnt(roleId, needRefresh, inc, curTime); - return {status: 1, data: { - battleCount: freeCount + dungeonBuyCnt - dungeonCnt - inc, - buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - }}; -} - -/** - * 秘境购买次数的花费 - * @param num 如果没有买过次数,那么这里算第一次,传1 - * @returns - */ -export function getDungeonBuyCountCost(num:number) { - let cost = (num - 1) * dicParam.DUNGEON_CONST.DUNGEON_CONST_UP + dicParam.DUNGEON_CONST.DUNGEON_CONST_BASE; - if(cost > dicParam.DUNGEON_CONST.DUNGEON_CONST_TOP) { - cost = dicParam.DUNGEON_CONST.DUNGEON_CONST_TOP; - } - return cost; -} - -export async function saveDungeonFirst(role: RoleType, warId: number, battleRecord: BattleRecordType) { - if(!role) return null; - let userInfo = new RankParam(role); - let lineup = battleRecord.record.lineup; - let dicWar = gameData.war.get(warId); - await DungeonFirstModel.createDungeonFirst(role.serverId, dicWar.movePoint, warId, { - time: nowSeconds(), roleId: role.roleId, userInfo, lineup - }) -} \ No newline at end of file +/** + * 每日本相关 + */ + +import { resResult, shouldRefresh, } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { RoleModel, RoleType, WarStar } from '@db/Role'; +import * as dicParam from '@pubUtils/dicParam'; +import { RankParam } from '@domain/rank'; +import { BattleRecordType } from '@db/BattleRecord'; +import { gameData } from '@pubUtils/data'; +import { DungeonFirstModel } from '@db/DungeonFirst'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { getVipDungeonCnt } from './activity/monthlyTicketService'; + +/** + * 获取秘境本数据 + * @param role + */ +export async function getDungeonData(role: RoleType) { + let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, dungeonHeroes=[] } = role; + let curTime = new Date(); + if(shouldRefresh(dungeonRefTime, curTime)) { + dungeonCnt = 0; dungeonBuyCnt = 0; + } + + let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + 1); + let freeCount = getVipDungeonCnt(role.vipStartTime); + return { + nextCostGold, + dungeonHeroes, + battleCount: freeCount + dungeonBuyCnt - dungeonCnt, + buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt + } +} + +function isFirstPass(warStar: WarStar[], warId: number) { + let index = warStar.findIndex(cur => cur.id == warId); + return index == -1; +} + +// 检查秘境本次数checkBattle使用 +export async function checkDungeonNum(roleId: string, inc: number, warId: number) { + let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, vipStartTime, warStar } = await RoleModel.findByRoleId(roleId); + if(isFirstPass(warStar, warId)) inc = 0; + + let curTime = new Date(); + let needRefresh = shouldRefresh(dungeonRefTime, curTime); + if(needRefresh) { + dungeonCnt = 0; dungeonBuyCnt = 0; + } + let freeCount = getVipDungeonCnt(vipStartTime); + if(dungeonCnt + inc > freeCount + dungeonBuyCnt) { + return {status: -1, resResult: resResult(STATUS.DUNGEON_TIMES_LACK)} + } + await RoleModel.increaseDungeonCnt(roleId, needRefresh, 0, curTime); + + return { status: 0, data: { + battleCount: freeCount + dungeonBuyCnt - dungeonCnt, + buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt + }}; +} + +/** + * 检查秘境本次数并添加,warEnd和warSweep使用 + * @param roleId + * @param inc 增加的次数 + * @param isRef 在计算之前是否检查每日的刷新 + */ + +export async function checkDungeonAndIncrease(roleId: string, inc: number, isRef: boolean, warId: number) { + + let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime, vipStartTime, warStar } = await RoleModel.findByRoleId(roleId); + if(isFirstPass(warStar, warId)) inc = 0; + let curTime = new Date(); + + let needRefresh = isRef && shouldRefresh(dungeonRefTime, curTime); + if(needRefresh) { + dungeonCnt = 0; dungeonBuyCnt = 0; + } + let freeCount = getVipDungeonCnt(vipStartTime); + + if(dungeonCnt + inc > freeCount + dungeonBuyCnt ) { + return { status: -1, resResult: resResult(STATUS.DUNGEON_TIMES_LACK) } + } + // console.log('needRefresh', needRefresh); + await RoleModel.increaseDungeonCnt(roleId, needRefresh, inc, curTime); + return {status: 1, data: { + battleCount: freeCount + dungeonBuyCnt - dungeonCnt - inc, + buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt + }}; +} + +/** + * 秘境购买次数的花费 + * @param num 如果没有买过次数,那么这里算第一次,传1 + * @returns + */ +export function getDungeonBuyCountCost(num:number) { + let cost = (num - 1) * dicParam.DUNGEON_CONST.DUNGEON_CONST_UP + dicParam.DUNGEON_CONST.DUNGEON_CONST_BASE; + if(cost > dicParam.DUNGEON_CONST.DUNGEON_CONST_TOP) { + cost = dicParam.DUNGEON_CONST.DUNGEON_CONST_TOP; + } + return cost; +} + +export async function saveDungeonFirst(role: RoleType, warId: number, battleRecord: BattleRecordType) { + if(!role) return null; + let userInfo = new RankParam(role); + let lineup = battleRecord.record.lineup; + let dicWar = gameData.war.get(warId); + await DungeonFirstModel.createDungeonFirst(role.serverId, dicWar.movePoint, warId, { + time: nowSeconds(), roleId: role.roleId, userInfo, lineup + }) +} diff --git a/game-server/app/services/equipService.ts b/game-server/app/services/equipService.ts index 285551fb4..54f61149f 100644 --- a/game-server/app/services/equipService.ts +++ b/game-server/app/services/equipService.ts @@ -1,226 +1,226 @@ -import { getRandEelm, sortArrRandom, } from '../pubUtils/util'; -import { EPlace, Stone } from "../db/Hero"; -import { gameData, getArtifactWithQuality, getDicArtifactLvByPlanId, getDicArtifactQualityByStage, getJewelConditionByLvAndSeId, getNextArtifact, getNextArtifactQuality, getRandEffectByGroupAndLevel } from "../pubUtils/data"; -import { JewelType, RandSe } from '../db/Jewel'; -import { DicRandomEffectPool } from '../pubUtils/dictionary/DicRandomEffectPool'; -import { getJewelRandSe } from './role/rewardService'; -import { ArtifactModelType } from '../db/Artifact'; -import { STATUS } from '../consts'; -import { ItemInter } from '../pubUtils/interface'; -import { combineItems } from './role/util'; - -export function getRandSeResult(id: number, randSe: RandSe[], originSe: RandSe[] = [], originId?: number) { - let { randomEffect, effectCount, lv } = gameData.jewel.get(id); - - let chosen = randSe.filter(cur => cur.locked).map(cur => cur.seid); // 上一轮随机出来的 - - let newRandSe: RandSe[] = []; // 随机结果 - let startId = 0; - for(let { id, seid } of originSe) { - let { lv: oldLv } = gameData.jewel.get(originId); - // 替换成高阶 - let dicRandomEffect = gameData.randomEffectPool.get(seid); - let nextRandEffect: DicRandomEffectPool; - let targetRandLv = dicRandomEffect.level + lv - oldLv; - while(!nextRandEffect) { - nextRandEffect = getRandEffectByGroupAndLevel(dicRandomEffect.group, targetRandLv); - targetRandLv--; - if(targetRandLv < 0) break; - } - let newSeid = nextRandEffect? nextRandEffect.id: seid; - newRandSe.push(getJewelRandSe(id, newSeid)); - chosen.push(newSeid); - startId++; - } - - let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), effectCount); // 随机出的结果 - if(randomResult.length < effectCount) { // 去上轮之后不够,把上轮加入 - let chosenRandom = getRandEelm(chosen, effectCount - randomResult.length); - randomResult.push(...chosenRandom); - } - if(randomResult.length < effectCount) { // 还是不够 - let allRandom = getRandEelm(randomEffect, effectCount - randomResult.length); - randomResult.push(...allRandom); - } - - let arr = sortArrRandom(randomResult); - // console.log('##### getRandSeResult', startId, effectCount) - - for (let i = startId; i < effectCount; i++) { - if(randSe[i]) { - if(randSe[i] && randSe[i].locked) { - newRandSe.push(randSe[i]); - } else { - newRandSe.push(getJewelRandSe(randSe[i].id, arr[i])); - } - } else { - newRandSe.push(getJewelRandSe(i + 1, arr[i])); - } - } - if(newRandSe.length < randSe.length) { - newRandSe.push(...randSe.splice(newRandSe.length)); - } - - return newRandSe -} - -export function updateStone(origin: Stone[], id: number, target: number) { - let newStones: Stone[] = []; - let hasTarget = false; - for(let stone of origin) { - if(stone.id == id) { - newStones.push({ id, stone: target }); - hasTarget = true; - } else { - newStones.push(stone); - } - } - if(!hasTarget) { - newStones.push({ id, stone: target }); - } - return newStones; -} - -export function updateEplace(eplace: EPlace[], eplaceId: number, update: Partial) { - let newEplace: EPlace[] = []; - let newEquip: EPlace; - let updatedEplace: Partial[] = []; - for(let equip of eplace) { - if(equip.id == eplaceId) { - newEplace.push({ ...equip, ...update }); - newEquip = { ...equip, ...update }; - updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update }); - } else { - newEplace.push(equip); - } - } - return {newEplace, updatedEplace, newEquip }; -} - -export function updateEplaces(eplace: EPlace[], update: Map>) { - let newEplace: EPlace[] = []; - let updatedEplace: Partial[] = []; - for(let equip of eplace) { - if(update.has(equip.id)) { - newEplace.push({ ...equip, ...update.get(equip.id) }); - updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update.get(equip.id) }); - } else { - newEplace.push(equip); - } - } - return {newEplace, updatedEplace}; -} - -/** - * 检查天晶石能否装备上这个装备 - * @param equip - * @param jewel - */ -export function checkJewelCanPutOnEquip(equip: EPlace, jewel: JewelType) { - // 位置是否满足 - let dicJewel = gameData.jewel.get(jewel.id); - if(!dicJewel || dicJewel.eplaceId != equip.id) return false; - // 品质是否满足 - let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality); - if(!dicEquipQualityExtra || dicEquipQualityExtra.jewelCnt == 0) return false; - return true -} - -export function checkStoneCanPutOnEquip(equip: EPlace, id: number, stone: number) { - if(stone == 0) return true; // 卸载 - // 位置是否满足 - let dicStone = gameData.stone.get(stone); - if(!dicStone || dicStone.eplaceId != equip.id) return false; - // 品质是否满足 - let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality); - if(!dicEquipQualityExtra || dicEquipQualityExtra.stoneCnt < id) return false; - return true; -} - -export function isLocked(randSe: RandSe[]) { - for(let { locked } of randSe) { - if(locked) return true; - } - return false; -} - -export function getEquipById(oldEplace: EPlace[], newEplace: EPlace[], eplaceId: number) { - let oldEquip = oldEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0); - let newEquip = newEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0); - return { oldEquip, newEquip } -} - -export function getJewelByEquip(equip: EPlace, jewels: JewelType[]) { - if(!equip) return null - let jewel = jewels.find(cur => cur && cur.seqId == equip.jewel); - return jewel -} - -export function isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[]) { - let dicJewel = gameData.jewel.get(jewelId); - let dicJewelCondition = getJewelConditionByLvAndSeId(dicJewel.lv, randSeId); - let stoneCnt = 0, stoneLv = 0; - for(let { stone } of stones) { - let dicStone = gameData.stone.get(stone); - if(dicStone) { - stoneCnt++; - stoneLv += dicStone.lv; - } - } - return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv; -} - -export function checkArtifactCanCompose(originArtifactId: number, artifact: ArtifactModelType) { - if(!artifact) return STATUS.ARTIFACT_IS_NOT_FIND; - // 宝物表 - let dicArtifact = gameData.artifact.get(artifact.artifactId); - if(!dicArtifact) return STATUS.ARTIFACT_IS_NOT_FIND; - // 宝物品质表 - let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage); - if(!dicArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND; - // 狗粮不可装备 - if(artifact.hid > 0) return STATUS.ARTIFACT_IS_EQUIPED; - // 狗粮不可强化 - if(artifact.lv > 0) return STATUS.ARTIFACT_CAN_NOT_STRENGTHEN; - - // 合成目标 - let dicTargetArtifactQuality = getNextArtifact(originArtifactId); - if(!dicTargetArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND; - - // 检查狗粮品质 - if(dicTargetArtifactQuality.materialId != dicArtifactQuality.uniqId) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR; - // 检查是否同名 - if(dicTargetArtifactQuality.materialGroup == 1 && dicTargetArtifactQuality.group != dicArtifact.group) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR; - return STATUS.SUCCESS; -} - -export function getRebuildConsume(artifacts: ArtifactModelType[]) { - let usedConsumes: ItemInter[] = []; - for(let artifact of artifacts) { - let dicArtifact = getArtifactWithQuality(artifact.artifactId); - if(!dicArtifact) continue; - if(!hasArtifactStrength(artifact)) continue; - - for(let lv = 1; lv <= artifact.lv; lv++) { - let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); - usedConsumes.push(...dicArtifactLv.consumes); - } - for(let stage = 0; stage < artifact.qualityStage; stage++) { - let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, stage); - let dicNextArtifactQuality = gameData.artifactQualityById.get(dicArtifactQuality?.nextId); - if(!dicNextArtifactQuality) continue; - let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifactQuality.materialId); - if(!dicMaterialArtifactQuality) continue; - - let consumes = dicMaterialArtifactQuality.generalItem.map(({id, count}) => ({ id, count: count * dicNextArtifactQuality.materialCnt})); - usedConsumes.push(...consumes); - } - } - return combineItems(usedConsumes); -} - -// 宝物是否有养成 -export function hasArtifactStrength(artifact: ArtifactModelType) { - if(!artifact) return false; - return artifact.lv >= 1 || artifact.qualityStage > 0; -} \ No newline at end of file +import { getRandEelm, sortArrRandom, } from '@pubUtils/util'; +import { EPlace, Stone } from "@db/Hero"; +import { gameData, getArtifactWithQuality, getDicArtifactLvByPlanId, getDicArtifactQualityByStage, getJewelConditionByLvAndSeId, getNextArtifact, getNextArtifactQuality, getRandEffectByGroupAndLevel } from "@pubUtils/data"; +import { JewelType, RandSe } from '@db/Jewel'; +import { DicRandomEffectPool } from '@pubUtils/dictionary/DicRandomEffectPool'; +import { getJewelRandSe } from './role/rewardService'; +import { ArtifactModelType } from '@db/Artifact'; +import { STATUS } from '@consts'; +import { ItemInter } from '@pubUtils/interface'; +import { combineItems } from './role/util'; + +export function getRandSeResult(id: number, randSe: RandSe[], originSe: RandSe[] = [], originId?: number) { + let { randomEffect, effectCount, lv } = gameData.jewel.get(id); + + let chosen = randSe.filter(cur => cur.locked).map(cur => cur.seid); // 上一轮随机出来的 + + let newRandSe: RandSe[] = []; // 随机结果 + let startId = 0; + for(let { id, seid } of originSe) { + let { lv: oldLv } = gameData.jewel.get(originId); + // 替换成高阶 + let dicRandomEffect = gameData.randomEffectPool.get(seid); + let nextRandEffect: DicRandomEffectPool; + let targetRandLv = dicRandomEffect.level + lv - oldLv; + while(!nextRandEffect) { + nextRandEffect = getRandEffectByGroupAndLevel(dicRandomEffect.group, targetRandLv); + targetRandLv--; + if(targetRandLv < 0) break; + } + let newSeid = nextRandEffect? nextRandEffect.id: seid; + newRandSe.push(getJewelRandSe(id, newSeid)); + chosen.push(newSeid); + startId++; + } + + let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), effectCount); // 随机出的结果 + if(randomResult.length < effectCount) { // 去上轮之后不够,把上轮加入 + let chosenRandom = getRandEelm(chosen, effectCount - randomResult.length); + randomResult.push(...chosenRandom); + } + if(randomResult.length < effectCount) { // 还是不够 + let allRandom = getRandEelm(randomEffect, effectCount - randomResult.length); + randomResult.push(...allRandom); + } + + let arr = sortArrRandom(randomResult); + // console.log('##### getRandSeResult', startId, effectCount) + + for (let i = startId; i < effectCount; i++) { + if(randSe[i]) { + if(randSe[i] && randSe[i].locked) { + newRandSe.push(randSe[i]); + } else { + newRandSe.push(getJewelRandSe(randSe[i].id, arr[i])); + } + } else { + newRandSe.push(getJewelRandSe(i + 1, arr[i])); + } + } + if(newRandSe.length < randSe.length) { + newRandSe.push(...randSe.splice(newRandSe.length)); + } + + return newRandSe +} + +export function updateStone(origin: Stone[], id: number, target: number) { + let newStones: Stone[] = []; + let hasTarget = false; + for(let stone of origin) { + if(stone.id == id) { + newStones.push({ id, stone: target }); + hasTarget = true; + } else { + newStones.push(stone); + } + } + if(!hasTarget) { + newStones.push({ id, stone: target }); + } + return newStones; +} + +export function updateEplace(eplace: EPlace[], eplaceId: number, update: Partial) { + let newEplace: EPlace[] = []; + let newEquip: EPlace; + let updatedEplace: Partial[] = []; + for(let equip of eplace) { + if(equip.id == eplaceId) { + newEplace.push({ ...equip, ...update }); + newEquip = { ...equip, ...update }; + updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update }); + } else { + newEplace.push(equip); + } + } + return {newEplace, updatedEplace, newEquip }; +} + +export function updateEplaces(eplace: EPlace[], update: Map>) { + let newEplace: EPlace[] = []; + let updatedEplace: Partial[] = []; + for(let equip of eplace) { + if(update.has(equip.id)) { + newEplace.push({ ...equip, ...update.get(equip.id) }); + updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update.get(equip.id) }); + } else { + newEplace.push(equip); + } + } + return {newEplace, updatedEplace}; +} + +/** + * 检查天晶石能否装备上这个装备 + * @param equip + * @param jewel + */ +export function checkJewelCanPutOnEquip(equip: EPlace, jewel: JewelType) { + // 位置是否满足 + let dicJewel = gameData.jewel.get(jewel.id); + if(!dicJewel || dicJewel.eplaceId != equip.id) return false; + // 品质是否满足 + let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality); + if(!dicEquipQualityExtra || dicEquipQualityExtra.jewelCnt == 0) return false; + return true +} + +export function checkStoneCanPutOnEquip(equip: EPlace, id: number, stone: number) { + if(stone == 0) return true; // 卸载 + // 位置是否满足 + let dicStone = gameData.stone.get(stone); + if(!dicStone || dicStone.eplaceId != equip.id) return false; + // 品质是否满足 + let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality); + if(!dicEquipQualityExtra || dicEquipQualityExtra.stoneCnt < id) return false; + return true; +} + +export function isLocked(randSe: RandSe[]) { + for(let { locked } of randSe) { + if(locked) return true; + } + return false; +} + +export function getEquipById(oldEplace: EPlace[], newEplace: EPlace[], eplaceId: number) { + let oldEquip = oldEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0); + let newEquip = newEplace.find(cur => cur.id == eplaceId)||new EPlace(eplaceId, 0); + return { oldEquip, newEquip } +} + +export function getJewelByEquip(equip: EPlace, jewels: JewelType[]) { + if(!equip) return null + let jewel = jewels.find(cur => cur && cur.seqId == equip.jewel); + return jewel +} + +export function isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[]) { + let dicJewel = gameData.jewel.get(jewelId); + let dicJewelCondition = getJewelConditionByLvAndSeId(dicJewel.lv, randSeId); + let stoneCnt = 0, stoneLv = 0; + for(let { stone } of stones) { + let dicStone = gameData.stone.get(stone); + if(dicStone) { + stoneCnt++; + stoneLv += dicStone.lv; + } + } + return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv; +} + +export function checkArtifactCanCompose(originArtifactId: number, artifact: ArtifactModelType) { + if(!artifact) return STATUS.ARTIFACT_IS_NOT_FIND; + // 宝物表 + let dicArtifact = gameData.artifact.get(artifact.artifactId); + if(!dicArtifact) return STATUS.ARTIFACT_IS_NOT_FIND; + // 宝物品质表 + let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, dicArtifact.qualityStage); + if(!dicArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND; + // 狗粮不可装备 + if(artifact.hid > 0) return STATUS.ARTIFACT_IS_EQUIPED; + // 狗粮不可强化 + if(artifact.lv > 0) return STATUS.ARTIFACT_CAN_NOT_STRENGTHEN; + + // 合成目标 + let dicTargetArtifactQuality = getNextArtifact(originArtifactId); + if(!dicTargetArtifactQuality) return STATUS.DIC_DATA_NOT_FOUND; + + // 检查狗粮品质 + if(dicTargetArtifactQuality.materialId != dicArtifactQuality.uniqId) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR; + // 检查是否同名 + if(dicTargetArtifactQuality.materialGroup == 1 && dicTargetArtifactQuality.group != dicArtifact.group) return STATUS.ARTIFACT_MATERIAL_QUALITY_ERR; + return STATUS.SUCCESS; +} + +export function getRebuildConsume(artifacts: ArtifactModelType[]) { + let usedConsumes: ItemInter[] = []; + for(let artifact of artifacts) { + let dicArtifact = getArtifactWithQuality(artifact.artifactId); + if(!dicArtifact) continue; + if(!hasArtifactStrength(artifact)) continue; + + for(let lv = 1; lv <= artifact.lv; lv++) { + let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); + usedConsumes.push(...dicArtifactLv.consumes); + } + for(let stage = 0; stage < artifact.qualityStage; stage++) { + let dicArtifactQuality = getDicArtifactQualityByStage(dicArtifact.quality, stage); + let dicNextArtifactQuality = gameData.artifactQualityById.get(dicArtifactQuality?.nextId); + if(!dicNextArtifactQuality) continue; + let dicMaterialArtifactQuality = gameData.artifactQualityById.get(dicNextArtifactQuality.materialId); + if(!dicMaterialArtifactQuality) continue; + + let consumes = dicMaterialArtifactQuality.generalItem.map(({id, count}) => ({ id, count: count * dicNextArtifactQuality.materialCnt})); + usedConsumes.push(...consumes); + } + } + return combineItems(usedConsumes); +} + +// 宝物是否有养成 +export function hasArtifactStrength(artifact: ArtifactModelType) { + if(!artifact) return false; + return artifact.lv >= 1 || artifact.qualityStage > 0; +} diff --git a/game-server/app/services/eventSercive.ts b/game-server/app/services/eventSercive.ts index 7131f1590..1f46b02e4 100644 --- a/game-server/app/services/eventSercive.ts +++ b/game-server/app/services/eventSercive.ts @@ -1,391 +1,391 @@ -import { FrontendOrBackendSession, pinus } from 'pinus'; -import EventRecord, { EventRecordModel } from '../db/EventRecord'; -import { RoleModel } from '../db/Role'; -import { genCode, getRandEelmWithWeight, resResult, getRandSingleEelm } from '../pubUtils/util'; -import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_TYPE, EVENT_RANDOM_TYPE_ONE_OPEN, EVENT_QUIZ_NUM, EVENT_ANSWER_STATUS, FUNCS_ID, PUSH_ROUTE } from '../consts'; -import { EVENT_REFRESH_NUM } from '../consts'; -import { STATUS } from '../consts/statusCode'; -import { gameData } from '../pubUtils/data'; -import { DicQuestion } from '../pubUtils/dictionary/DicQuestion'; -import { sendMessageToUserWithSuc } from './pushService'; -import { WarStar } from '../domain/dbGeneral'; - -/** - * 从检查接口调用,检查是否有这么个战斗,顺便保存一下battleCode - * - * @param roleId - * @param eventStatus - * @param battleId - * @param battleCode - */ -export async function checkEventBattle(roleId: string, eventStatus: number, battleId: number, battleCode: string) { - let now = new Date(); - let refTime = eventStatus == EVENT_STATUS.OPEN? getEventTime(now): 0; - - let result = await EventRecordModel.setBattleCode(roleId, battleId, refTime, battleCode); - if (!result) { - if(refTime) { - let preTime = getEventTime(new Date(refTime - 1)); - // console.log('preTime:', preTime); - result = await EventRecordModel.setBattleCode(roleId, battleId, preTime, battleCode); - } - } - if (!result) { - return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; - } else { - return { status: 0, data: result }; - } -} - -/** - * 从关卡结算接口调用,保存战斗情况 - * - * @param session - * @param roleId - * @param battleId - * @param isSuccess - * @param battleCode - */ -export async function setBattleStatus(session: FrontendOrBackendSession, roleId: string, battleId: number , isSuccess: boolean, battleCode: string) { - - let { BATTLE_SUCCESS, BATTLE_FAIL } = EVENT_RECORD_STATUS; - let result = await EventRecordModel.setBattleStatus(roleId, battleId, battleCode, isSuccess?BATTLE_SUCCESS:BATTLE_FAIL); - if (!result) { - return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; - } - // await checkEvent(session, true); - return { status: 0, data: result }; -} - -/** - * 获取刷新时间,12点时间或18点时间 - * - * @param now - */ -export function getEventTime(now: Date) { - let curTime = Number(now); - let todayA = now.setHours(12, 0, 0, 0); // 每天12点 - let todayB = now.setHours(18, 0, 0, 0); // 每天18点 - let yesterdayB = todayB - 86400000; // 前一天12点 - let t = 0; - if(curTime < todayA) { - t = yesterdayB; - } else if (curTime >= todayA && curTime < todayB) { - t = todayA; - } else if (curTime >= todayB) { - t = todayB; - } - return t -} - -/** - * 从挑战结算接口调用,挑战完主线某一关,开始刷奇遇关卡 - * - * @param session - */ -export async function startEvent(session: FrontendOrBackendSession) { - - const eventStatus = session.get('eventStatus'); - // console.log('*******startEvent ', eventStatus) - if(eventStatus == EVENT_STATUS.WAITING) { - let roleId = session.get('roleId'); - let roleName = session.get('roleName'); - let sid = session.get('sid'); - let event = await refreshEvent(1, roleId, roleName, 0, []); // 刷新初始的一件 - if(event.length > 0) { - await RoleModel.setEventStatus(roleId, EVENT_STATUS.STARTING); - session.set('eventStatus', EVENT_STATUS.STARTING); - session.push('eventStatus', () => {}); - pushEventMsg(sid, roleId, { event }); // 推送 - } - return event; - } else { - return [] - } -} - -/** - * 获取当前的奇遇事件 - * - * @param eventStatus - * @param roleId - * @param roleName - */ -export async function getEvent(eventStatus: number, roleId: string, roleName: string) { - - let now = new Date(); - let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18 - let preTime = getEventTime(new Date(curTime - 1)); // 上一次的时间节点 - - let event: Array = []; - if (eventStatus == EVENT_STATUS.STARTING) { - let result = await EventRecordModel.getEventRecordByTime(roleId, 0); - for(let e of result) event.push(e); - } else if( eventStatus == EVENT_STATUS.OPEN ) { - let preEvents = await EventRecordModel.getEventRecordByTime(roleId, preTime); // 上次3个 - if(!preEvents.length) preEvents = await EventRecordModel.getEventRecordByTime(roleId, 0); - let curEvents = await EventRecordModel.getEventRecordByTime(roleId, curTime); // 这次3个 - - if(curEvents.length == 0) { // 这次3个没刷过,那就刷一下 - let result = await refreshEvent(EVENT_REFRESH_NUM, roleId, roleName, curTime, preEvents); - for(let e of result) event.push(e); - } else { - for(let e of curEvents) event.push(e); - } - - for(let e of preEvents) { - let index = event.findIndex(cur => cur.point == e.point); - if(index == -1) { // 这个位置空着,则塞入 - event.push(e); - } else { - let curEvent = event[index]; - if(curEvent.status == EVENT_RECORD_STATUS.FAIL_RECEIVED || curEvent.status == EVENT_RECORD_STATUS.SUCCESS_RECEIVED) { // 当前的几个已领取,pre的补位 - event[index] = e; - } - } - } - } - - return event; -} - - -/** - * 刷新事件 - * - * @param num 刷多少事件 - * @param roleId - * @param roleName - * @param t 时间刷新时间,每天的12点或18点 - */ -export async function refreshEvent(num: number, roleId: string, roleName: string, t: number, preEvents: Array) { - let {WAITING, BATTLE_SUCCESS, BATTLE_FAIL} = EVENT_RECORD_STATUS; - - let prePoint = preEvents.filter(cur => { - return [WAITING, BATTLE_SUCCESS, BATTLE_FAIL].includes(cur.status); - }).map(cur => cur.point); - - let event = new Array(); - let dicEvent = gameData.eventList.filter(cur => cur.movePointArray && cur.movePointArray.length > 0); - let role = await RoleModel.findByRoleId(roleId); - dicEvent = dicEvent.filter(cur => { // 筛选适合等级 - let { suitLevel, previousGk } = cur; - return suitLevel.min <= role.lv && suitLevel.max >= role.lv && checkPreviousGk(previousGk, role.warStar) - }); - if(EVENT_RANDOM_TYPE_ONE_OPEN) { - let historyRecord = await EventRecordModel.getHostoryEventRecord(roleId); - let {history, turn} = historyRecord; - let randomList = dicEvent.filter(cur => { - return history.find(ccur => { - return ccur.eventId != cur.eventID; - }); - }); - - let curPoint = new Array(); - for(let i = 0; i < num; i++) { - if(randomList.length == 0) { // 一轮刷新过,开始新的一轮,保证所有事件都能刷新一遍 - turn ++; - randomList = [...dicEvent]; - } - if(randomList.length == 0) break; // 如果还是为0,pass - - let index = Math.floor(Math.random() * randomList.length); - let dic = randomList[index]; - let point = randomPosition(dic.movePointArray, prePoint, curPoint); - if(!point) break; - let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined; - let eventCode = genCode(8); - let data = await EventRecordModel.saveEventRecord(eventCode, { - roleId, refTime: t, eventId: dic.eventID, - roleName, turn, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, - status: EVENT_RECORD_STATUS.WAITING, - point, question - }); - event.push(data); - randomList.splice(index, 1); - } - } else { - let randomList = dicEvent; - if(randomList.length == 0) return [] - let curPoint = new Array(); - for(let i = 0; i < num; i++) { - let {dic} = getRandEelmWithWeight(randomList); - // 临时处理,不出现相同的关卡id - for(let x = 0; x < 1000; x++) { // 防死循环 - let hasEvent = event.find(cur => { - return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); - let hasPreEvent = preEvents.find(cur => { - return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); - - if(x < 500) { // 基本不希望本轮和上轮出现过的关卡再次出现 - if(!hasEvent && !hasPreEvent) break; - } else { // 但是实在找不到,只要本轮没出现过就好 - if(!hasEvent) break; - } - dic = getRandEelmWithWeight(randomList).dic; - } - - if(!dic) break; - let point = randomPosition(dic.movePointArray, prePoint, curPoint); - if(!point) break; - let eventCode = genCode(8); - let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): []; - let data = await EventRecordModel.saveEventRecord(eventCode, { - roleId, refTime: t, eventId: dic.eventID, - roleName, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, - status: EVENT_RECORD_STATUS.WAITING, - point, question - }); - event.push(data) - } - - } - return event; -} - -export function checkPreviousGk(previousGk: number, warStar: WarStar[]) { - if(!previousGk) return true; - let preBattle = warStar.findIndex(cur => cur.id == previousGk); - return preBattle != -1; -} - -/** - * 随机出当前事件的位置 - * - * @param positionStr - */ -export function randomPosition(positionArr: number[], prePoint: Array, curPoint: Array) { - let range = positionArr.filter(point => {return !prePoint.includes(point) && !curPoint.includes(point)}); - if(range.length == 0) { // 如果位置总数不够,就不管prePoint里的 - range = positionArr.filter(point => {return !curPoint.includes(point)}); - } - if(range.length == 0) { // 还是不够,那是配表的问题,直接报错 - return false; - } - let index = Math.floor(Math.random() * range.length); - let point = range[index]; - curPoint.push(point); - - return point -} - -/** - * 推送 - * - * @param roleId - * @param msg - */ -function pushEventMsg(sid: string, roleId: string, msg: any ) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.SEND_EVENT, msg, sid); -} - -/** - * 领取奖励时检查状态是否正确 - * - * @param type 事件类型 - * @param status 状态id - */ -export function checkEventStatus(type: number, status: number) { - // console.log('type = '+ type + ' status = '+status); - let flag: boolean; // 检查状态是否正确 - if(type == EVENT_TYPE.BATTLE||type ==EVENT_TYPE.QUIZ) { - if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { - flag = true; - } else if (status == EVENT_RECORD_STATUS.BATTLE_FAIL) { - flag = true; - } else { - flag = true; - } - } else { - if(status == EVENT_RECORD_STATUS.WAITING) { - flag = true; - } else { - flag = false; - } - } - return flag -} - -/** - * 领取奖励时调用,领取的是胜利奖励还是失败奖励 - * - * @param type - * @param status - * @param question - */ -export function getEventSuccessStatus(type: number, status: number, question: Array<{id: number, status: number}>) { - let isSuccess: boolean, returnResult = 1; // 检查状态是否正确 - if(type == EVENT_TYPE.BATTLE) { - if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { - isSuccess = true; - } else { - isSuccess = false; - } - } else if(type == EVENT_TYPE.BOX) { - isSuccess = true; - } else if (type == EVENT_TYPE.QUIZ) { - isSuccess = true; - for(let { status = EVENT_ANSWER_STATUS.WAITING } of question) { - // console.log(status); - if(status == EVENT_ANSWER_STATUS.WRONG) { - isSuccess = false; - } else if(status == EVENT_ANSWER_STATUS.WAITING) { - isSuccess = false; - returnResult = -1; - } - } - } - return { isSuccess, status: returnResult } -} - -export function checkQuizParam(param: Array, database?: Array<{id: number}>) { - - if(database) { - let flag = true; - for(let {id} of database) { - let index = param.indexOf(id); - if(index == -1) flag = false; break; - } - return flag - } else { - return true - } -} - -/** - * 从题库中随机题目 - * - * @param num 题目数量 - */ -export function randomQuestion(num: number) { - let questions = new Array(); - gameData.question.forEach(cur => { - questions.push(cur); - }); - let rid:Array = [], result = []; - while(num > 0) { - let dicQuestion = getRandSingleEelm(questions); - let {id, question, answer } = dicQuestion; - if(rid.includes(id)) continue; - rid.push(id); - result.push({id, question, answer}); - num--; - } - return result; -} - -/** - * 对答案 - * - * @param id - * @param answer - */ -export function checkQuiz(id: number, answer: number) { - let result = gameData.question.get(id); - - return { - isCorrect: !!result && result.correct == answer, - answerNo: result?result.correct: 0 - } -} - +import { FrontendOrBackendSession, pinus } from 'pinus'; +import EventRecord, { EventRecordModel } from '@db/EventRecord'; +import { RoleModel } from '@db/Role'; +import { genCode, getRandEelmWithWeight, resResult, getRandSingleEelm } from '@pubUtils/util'; +import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_TYPE, EVENT_RANDOM_TYPE_ONE_OPEN, EVENT_QUIZ_NUM, EVENT_ANSWER_STATUS, FUNCS_ID, PUSH_ROUTE } from '@consts'; +import { EVENT_REFRESH_NUM } from '@consts'; +import { STATUS } from '@consts/statusCode'; +import { gameData } from '@pubUtils/data'; +import { DicQuestion } from '@pubUtils/dictionary/DicQuestion'; +import { sendMessageToUserWithSuc } from './pushService'; +import { WarStar } from '@domain/dbGeneral'; + +/** + * 从检查接口调用,检查是否有这么个战斗,顺便保存一下battleCode + * + * @param roleId + * @param eventStatus + * @param battleId + * @param battleCode + */ +export async function checkEventBattle(roleId: string, eventStatus: number, battleId: number, battleCode: string) { + let now = new Date(); + let refTime = eventStatus == EVENT_STATUS.OPEN? getEventTime(now): 0; + + let result = await EventRecordModel.setBattleCode(roleId, battleId, refTime, battleCode); + if (!result) { + if(refTime) { + let preTime = getEventTime(new Date(refTime - 1)); + // console.log('preTime:', preTime); + result = await EventRecordModel.setBattleCode(roleId, battleId, preTime, battleCode); + } + } + if (!result) { + return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; + } else { + return { status: 0, data: result }; + } +} + +/** + * 从关卡结算接口调用,保存战斗情况 + * + * @param session + * @param roleId + * @param battleId + * @param isSuccess + * @param battleCode + */ +export async function setBattleStatus(session: FrontendOrBackendSession, roleId: string, battleId: number , isSuccess: boolean, battleCode: string) { + + let { BATTLE_SUCCESS, BATTLE_FAIL } = EVENT_RECORD_STATUS; + let result = await EventRecordModel.setBattleStatus(roleId, battleId, battleCode, isSuccess?BATTLE_SUCCESS:BATTLE_FAIL); + if (!result) { + return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; + } + // await checkEvent(session, true); + return { status: 0, data: result }; +} + +/** + * 获取刷新时间,12点时间或18点时间 + * + * @param now + */ +export function getEventTime(now: Date) { + let curTime = Number(now); + let todayA = now.setHours(12, 0, 0, 0); // 每天12点 + let todayB = now.setHours(18, 0, 0, 0); // 每天18点 + let yesterdayB = todayB - 86400000; // 前一天12点 + let t = 0; + if(curTime < todayA) { + t = yesterdayB; + } else if (curTime >= todayA && curTime < todayB) { + t = todayA; + } else if (curTime >= todayB) { + t = todayB; + } + return t +} + +/** + * 从挑战结算接口调用,挑战完主线某一关,开始刷奇遇关卡 + * + * @param session + */ +export async function startEvent(session: FrontendOrBackendSession) { + + const eventStatus = session.get('eventStatus'); + // console.log('*******startEvent ', eventStatus) + if(eventStatus == EVENT_STATUS.WAITING) { + let roleId = session.get('roleId'); + let roleName = session.get('roleName'); + let sid = session.get('sid'); + let event = await refreshEvent(1, roleId, roleName, 0, []); // 刷新初始的一件 + if(event.length > 0) { + await RoleModel.setEventStatus(roleId, EVENT_STATUS.STARTING); + session.set('eventStatus', EVENT_STATUS.STARTING); + session.push('eventStatus', () => {}); + pushEventMsg(sid, roleId, { event }); // 推送 + } + return event; + } else { + return [] + } +} + +/** + * 获取当前的奇遇事件 + * + * @param eventStatus + * @param roleId + * @param roleName + */ +export async function getEvent(eventStatus: number, roleId: string, roleName: string) { + + let now = new Date(); + let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18 + let preTime = getEventTime(new Date(curTime - 1)); // 上一次的时间节点 + + let event: Array = []; + if (eventStatus == EVENT_STATUS.STARTING) { + let result = await EventRecordModel.getEventRecordByTime(roleId, 0); + for(let e of result) event.push(e); + } else if( eventStatus == EVENT_STATUS.OPEN ) { + let preEvents = await EventRecordModel.getEventRecordByTime(roleId, preTime); // 上次3个 + if(!preEvents.length) preEvents = await EventRecordModel.getEventRecordByTime(roleId, 0); + let curEvents = await EventRecordModel.getEventRecordByTime(roleId, curTime); // 这次3个 + + if(curEvents.length == 0) { // 这次3个没刷过,那就刷一下 + let result = await refreshEvent(EVENT_REFRESH_NUM, roleId, roleName, curTime, preEvents); + for(let e of result) event.push(e); + } else { + for(let e of curEvents) event.push(e); + } + + for(let e of preEvents) { + let index = event.findIndex(cur => cur.point == e.point); + if(index == -1) { // 这个位置空着,则塞入 + event.push(e); + } else { + let curEvent = event[index]; + if(curEvent.status == EVENT_RECORD_STATUS.FAIL_RECEIVED || curEvent.status == EVENT_RECORD_STATUS.SUCCESS_RECEIVED) { // 当前的几个已领取,pre的补位 + event[index] = e; + } + } + } + } + + return event; +} + + +/** + * 刷新事件 + * + * @param num 刷多少事件 + * @param roleId + * @param roleName + * @param t 时间刷新时间,每天的12点或18点 + */ +export async function refreshEvent(num: number, roleId: string, roleName: string, t: number, preEvents: Array) { + let {WAITING, BATTLE_SUCCESS, BATTLE_FAIL} = EVENT_RECORD_STATUS; + + let prePoint = preEvents.filter(cur => { + return [WAITING, BATTLE_SUCCESS, BATTLE_FAIL].includes(cur.status); + }).map(cur => cur.point); + + let event = new Array(); + let dicEvent = gameData.eventList.filter(cur => cur.movePointArray && cur.movePointArray.length > 0); + let role = await RoleModel.findByRoleId(roleId); + dicEvent = dicEvent.filter(cur => { // 筛选适合等级 + let { suitLevel, previousGk } = cur; + return suitLevel.min <= role.lv && suitLevel.max >= role.lv && checkPreviousGk(previousGk, role.warStar) + }); + if(EVENT_RANDOM_TYPE_ONE_OPEN) { + let historyRecord = await EventRecordModel.getHostoryEventRecord(roleId); + let {history, turn} = historyRecord; + let randomList = dicEvent.filter(cur => { + return history.find(ccur => { + return ccur.eventId != cur.eventID; + }); + }); + + let curPoint = new Array(); + for(let i = 0; i < num; i++) { + if(randomList.length == 0) { // 一轮刷新过,开始新的一轮,保证所有事件都能刷新一遍 + turn ++; + randomList = [...dicEvent]; + } + if(randomList.length == 0) break; // 如果还是为0,pass + + let index = Math.floor(Math.random() * randomList.length); + let dic = randomList[index]; + let point = randomPosition(dic.movePointArray, prePoint, curPoint); + if(!point) break; + let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined; + let eventCode = genCode(8); + let data = await EventRecordModel.saveEventRecord(eventCode, { + roleId, refTime: t, eventId: dic.eventID, + roleName, turn, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, + status: EVENT_RECORD_STATUS.WAITING, + point, question + }); + event.push(data); + randomList.splice(index, 1); + } + } else { + let randomList = dicEvent; + if(randomList.length == 0) return [] + let curPoint = new Array(); + for(let i = 0; i < num; i++) { + let {dic} = getRandEelmWithWeight(randomList); + // 临时处理,不出现相同的关卡id + for(let x = 0; x < 1000; x++) { // 防死循环 + let hasEvent = event.find(cur => { + return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); + let hasPreEvent = preEvents.find(cur => { + return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); + + if(x < 500) { // 基本不希望本轮和上轮出现过的关卡再次出现 + if(!hasEvent && !hasPreEvent) break; + } else { // 但是实在找不到,只要本轮没出现过就好 + if(!hasEvent) break; + } + dic = getRandEelmWithWeight(randomList).dic; + } + + if(!dic) break; + let point = randomPosition(dic.movePointArray, prePoint, curPoint); + if(!point) break; + let eventCode = genCode(8); + let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): []; + let data = await EventRecordModel.saveEventRecord(eventCode, { + roleId, refTime: t, eventId: dic.eventID, + roleName, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, + status: EVENT_RECORD_STATUS.WAITING, + point, question + }); + event.push(data) + } + + } + return event; +} + +export function checkPreviousGk(previousGk: number, warStar: WarStar[]) { + if(!previousGk) return true; + let preBattle = warStar.findIndex(cur => cur.id == previousGk); + return preBattle != -1; +} + +/** + * 随机出当前事件的位置 + * + * @param positionStr + */ +export function randomPosition(positionArr: number[], prePoint: Array, curPoint: Array) { + let range = positionArr.filter(point => {return !prePoint.includes(point) && !curPoint.includes(point)}); + if(range.length == 0) { // 如果位置总数不够,就不管prePoint里的 + range = positionArr.filter(point => {return !curPoint.includes(point)}); + } + if(range.length == 0) { // 还是不够,那是配表的问题,直接报错 + return false; + } + let index = Math.floor(Math.random() * range.length); + let point = range[index]; + curPoint.push(point); + + return point +} + +/** + * 推送 + * + * @param roleId + * @param msg + */ +function pushEventMsg(sid: string, roleId: string, msg: any ) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.SEND_EVENT, msg, sid); +} + +/** + * 领取奖励时检查状态是否正确 + * + * @param type 事件类型 + * @param status 状态id + */ +export function checkEventStatus(type: number, status: number) { + // console.log('type = '+ type + ' status = '+status); + let flag: boolean; // 检查状态是否正确 + if(type == EVENT_TYPE.BATTLE||type ==EVENT_TYPE.QUIZ) { + if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { + flag = true; + } else if (status == EVENT_RECORD_STATUS.BATTLE_FAIL) { + flag = true; + } else { + flag = true; + } + } else { + if(status == EVENT_RECORD_STATUS.WAITING) { + flag = true; + } else { + flag = false; + } + } + return flag +} + +/** + * 领取奖励时调用,领取的是胜利奖励还是失败奖励 + * + * @param type + * @param status + * @param question + */ +export function getEventSuccessStatus(type: number, status: number, question: Array<{id: number, status: number}>) { + let isSuccess: boolean, returnResult = 1; // 检查状态是否正确 + if(type == EVENT_TYPE.BATTLE) { + if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { + isSuccess = true; + } else { + isSuccess = false; + } + } else if(type == EVENT_TYPE.BOX) { + isSuccess = true; + } else if (type == EVENT_TYPE.QUIZ) { + isSuccess = true; + for(let { status = EVENT_ANSWER_STATUS.WAITING } of question) { + // console.log(status); + if(status == EVENT_ANSWER_STATUS.WRONG) { + isSuccess = false; + } else if(status == EVENT_ANSWER_STATUS.WAITING) { + isSuccess = false; + returnResult = -1; + } + } + } + return { isSuccess, status: returnResult } +} + +export function checkQuizParam(param: Array, database?: Array<{id: number}>) { + + if(database) { + let flag = true; + for(let {id} of database) { + let index = param.indexOf(id); + if(index == -1) flag = false; break; + } + return flag + } else { + return true + } +} + +/** + * 从题库中随机题目 + * + * @param num 题目数量 + */ +export function randomQuestion(num: number) { + let questions = new Array(); + gameData.question.forEach(cur => { + questions.push(cur); + }); + let rid:Array = [], result = []; + while(num > 0) { + let dicQuestion = getRandSingleEelm(questions); + let {id, question, answer } = dicQuestion; + if(rid.includes(id)) continue; + rid.push(id); + result.push({id, question, answer}); + num--; + } + return result; +} + +/** + * 对答案 + * + * @param id + * @param answer + */ +export function checkQuiz(id: number, answer: number) { + let result = gameData.question.get(id); + + return { + isCorrect: !!result && result.correct == answer, + answerNo: result?result.correct: 0 + } +} + diff --git a/game-server/app/services/expeditionService.ts b/game-server/app/services/expeditionService.ts index 48dc19389..119de495b 100644 --- a/game-server/app/services/expeditionService.ts +++ b/game-server/app/services/expeditionService.ts @@ -1,328 +1,328 @@ - -import { ExpeditionPointModel } from '../db/ExpeditionPoint'; -import Role, { RoleModel } from '../db/Role'; -import { shouldRefresh, getRandSingleEelm } from '../pubUtils/util'; -import { EXPEDITION_WAR_RECORD_STATUS, SYSTEM_OPEN_ID } from '../consts'; -import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord'; -import { HeroType } from '../db/Hero'; -import { gameData } from '../pubUtils/data'; -import { ExpeditionRecordModel } from '../db/ExpeditionRecord'; -import { Attribute, AttributeCal } from '../domain/roleField/attribute'; -import * as dicParam from '../pubUtils/dicParam'; -import { getHeroesAttributes, getSumCe } from './playerCeService'; -import { checkSystemIsOpen } from './roleService'; -import { ArtifactModel } from '../db/Artifact'; -import { JewelModel } from '../db/Jewel'; - -/** - * 获取远征关卡列表 - * @param roleId - * @param roleName - */ -export async function getExpeditionStatus(roleId: string, roleName: string, isEntry = false) { - // 重置次数 - let role = await RoleModel.findByRoleId(roleId); - if(!role.hasInit) return false; - if(isEntry && !checkSystemIsOpen(role, SYSTEM_OPEN_ID.EXPEDITION)) return false - // 获取远征关卡状态 - let expeditionRecord = await ExpeditionRecordModel.getCurRecord(roleId); - if (!expeditionRecord) { // 首次新建一条记录 - // 我方战力 - let myCe = await getSumCe(roleId); - expeditionRecord = await ExpeditionRecordModel.createRecord({ - roleId, roleName, heroes: [], myCe - }); - await findOrCreateEnemies(roleId, myCe, expeditionRecord.expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); - } - - // 每一关的挑战状态 - let { expeditionCode, heroes } = expeditionRecord; - let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode); - let curLv = 0; - if (expeditionWarRecord.length > 0) { - curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId; - } - - let curTime = new Date(); - let { resetCnt } = await getResetRemainCnt(curTime, roleId, role); - - // 点数,和宝箱领取状态 - let pointRewards = await getPointRewardStatus(roleId, role); - return { - expeditionCode, - curLv, - expeditionWarRecord, - pointRewards, - heroes: heroes.map(cur => { return { "dataId": cur.seqId, "hp": cur.hp, "ap": cur.ap, "shield": cur.shield || 0, "others": cur.others || ''} }), - resetCnt - } -} - -/** - * 根据存下的战力获取当前远征关卡的对手 - * @param roleId 我的id - * @param myCe 存在expeditionRecord内的战力(缩过) - * @param expeditionCode 远征批次id - * @param expeditionId 该关卡id - * @param battleStatus 该关卡的挑战状态 - */ -export async function findOrCreateEnemies(roleId: string, myCe: number, expeditionCode: string, expeditionId: number, battleStatus: number) { - - let expeditionWarRecord = await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId, battleStatus); - if(!expeditionWarRecord) { // 如果没有信息 - let curDicExpedition = gameData.expedition.get(expeditionId); - if(curDicExpedition) { - - let enemyObj = { - enemyFrom: 0, - enemyId: '', - enemies: new Array(), - ce: 0 - }; - - // 获取系数和步长 - let { scale, range, lv } = await getCEScaleAndRange(roleId, curDicExpedition); - // 优先匹配其他玩家 - let flag = await matchPlayers(roleId, scale, range, myCe, curDicExpedition.json, enemyObj); - // 当数量不够时使用机器人匹配 - if(!flag) { - flag = await matchRobots(scale, myCe, curDicExpedition.ce, curDicExpedition.json, lv, enemyObj); - } - if(flag) { - // 保存 - let { warId } = curDicExpedition; - let { mapseid } = gameData.war.get(warId); - expeditionWarRecord = await ExpeditionWarRecordModel.saveRecord(expeditionCode, expeditionId, { - roleId, battleId: warId, mapseid: getRandSingleEelm(mapseid), ...enemyObj, battleStatus - }); - } - } - } - - // 处理当前血量 - let {enemiesCurHpAp, enemies} = expeditionWarRecord; - for(let enemy of enemies) { - let cur = {"hp": 0, "ap": 0}; - let getHp = enemiesCurHpAp && enemiesCurHpAp.find(cur => cur.dataId == enemy.dataId); - if(getHp) { - cur.hp = getHp.hp; - cur.ap = getHp.ap; - } else { - let attr = new Attribute(); - attr.setByStr(enemy.attribute); - cur.hp = attr.hp; - cur.ap = 0; - } - enemy["cur"] = cur; - } - - return expeditionWarRecord; -} - -/** - * 远征关卡匹配玩家 - * @param roleId 我的id - * @param scale 己方战力和对方战力比 - * @param range 浮动范围 - * @param myCe 己方战力(已缩小) - * @param warJsonIndex 模板出兵表id - * @param enemyObj 返回的敌军数据 - */ -export async function matchPlayers(roleId: string, scale: number, range: number, myCe: number, warJsonIndex:any, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array, ce: number }) { - let dicWarJson = gameData.warJson.get(warJsonIndex); - - let min = myCe * scale * (1 - range/100); - let max = myCe * scale * (1 + range/100); - - let resultRange = await RoleModel.findByCeScale(min, max); - resultRange = resultRange.filter(cur => cur.roleId != roleId); - if(resultRange.length > 0) { - let role = resultRange[0]; - let {roleId, topLineup, topLineupCe } = role; - let attrByHid = await getHeroesAttributes(roleId); - - enemyObj.enemyFrom = 1; - enemyObj.enemyId = roleId; - enemyObj.ce = topLineupCe; - - let hids = topLineup.map(cur => cur.hid); - let artifacts = await ArtifactModel.findbyHids(roleId, hids); - let jewels = await JewelModel.findbyRoleAndHids(roleId, hids); - - let heroIndex = 0; - for(let json of dicWarJson) { - if(json.relation == 2) { - let hero = topLineup[heroIndex]; - if(hero) { - let h = hero.hero; - if(h) { - let { star, lv, ce, skins, colorStar, quality, job, subHid = 0, subActorId = 0, ePlace = [] } = h; - let artifact = h.artifact? artifacts.find(cur => cur.seqId == h.artifact): null; - let skin = skins?.find(cur => cur.enable); - - let dicHero = gameData.hero.get(hero.hid); - let attr = attrByHid.get(hero.hid); - let attribute = attr.getAttributesToString(); - let heroInfo = { - actorId: hero.hid, - skinId: h.skinId, - actorName: dicHero.name, - skill:0, - seid:'&', - spine: 0, - attribute, - lv, - ce, - star, - colorStar, - quality, - job, - talent: skin? skin.talent: [], - artifact: artifact? [{ artifactId: artifact.artifactId, lv: artifact.lv }]: [], - subHid, - subActorId, - ePlace: ePlace.map(cur => ({ ...cur, jewel: jewels.find(ccur => cur.jewel == ccur.seqId) })), - }; - - enemyObj.enemies.push({...json, ...heroInfo}); - heroIndex ++; - } - } - } - } - if(enemyObj.enemies.length <= 0) return false - return true; - } else { - return false - } -} - -/** - * 匹配远征机器人 - * @param scale 己方战力和出兵表配置战力比 - * @param myCe 己方战力(已缩小) - * @param robotCe 机器人战力(10000,相当于已缩小战力) - * @param warJsonIndex 模板出兵表id - * @param lv 我的主公等级 - * @param enemyObj 返回的敌军数据 - */ -export async function matchRobots(scale: number, myCe: number, robotCe: number, warJsonIndex: number, lv: number, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array, ce: number }) { - let dicWarJson = gameData.warJson.get(warJsonIndex); - if(dicWarJson) { - enemyObj.enemyFrom = 2; - enemyObj.enemyId = warJsonIndex + ''; - - let allCe = 0; - for(let json of dicWarJson) { - if(json.relation == 2) { - const { actorId, attribute, enemyCount } = json; - - let dicHero = gameData.hero.get(actorId); - let { attribute: newAttribute, ce } = getRobotAttribute(actorId, attribute, enemyCount, lv, myCe, robotCe, scale); - enemyObj.enemies.push({...json, skinId: json.actorId, attribute: newAttribute, lv, ce, - star: dicHero.initialStar, - colorStar: dicHero.initialColorStar, - quality: dicHero.quality, - job: dicHero.jobid, - talent: [], - artifact: [], - subHid: 0, - subActorId: 0 - }); - allCe += ce; - } - } - - enemyObj.ce = Math.floor(allCe); - - return true - } else { - return false - } -} - -// 远征匹配系数表 -export async function getCEScaleAndRange(roleId: string, curDicExpedition: any) { - // 匹配,判断是不是新手期 - const role = await RoleModel.findByRoleId(roleId); - let isNew = (role.expeditionHistoryResetCnt||0) <= 3; - - let scale = isNew?curDicExpedition.CEScaleNew:curDicExpedition.CEScale; - let range = isNew?curDicExpedition.CERangeNew:curDicExpedition.CERange; - return {scale, range, lv: role.lv} -} - -// 远征累计点数获取 -export async function getPointRewardStatus(roleId: string, role?: Role) { - if(!role) { - role = await RoleModel.findByRoleId(roleId); - } - let {expeditionPoint = 0} = role; - let dicExpeditionPoint = gameData.expeditionPoint; - let rewards: { point: number, received: boolean }[] = []; - for(let [point] of dicExpeditionPoint) { - rewards.push({ point, received: false }) - } - let pointRewards = { - expeditionPoint, rewards - }; - let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId); - if(pointStatusInDatabase) { - let { rewards = [] } = pointStatusInDatabase; - pointRewards.rewards.forEach(cur => { - let obj = rewards.find(ccur => ccur.point == cur.point); - if(obj) cur.received = obj.received; - }); - } - return pointRewards -} - -export async function getResetRemainCnt(curTime: Date, roleId: string, role?: Role, ) { - if(!role) { - role = await RoleModel.findByRoleId(roleId); - } - - let { expeditionResetCnt, expeditionResetRefTime } = role; - let needRefresh = !expeditionResetRefTime || shouldRefresh(expeditionResetRefTime, curTime); - if(needRefresh) { - expeditionResetCnt = 0; expeditionResetRefTime = curTime; - } - - let maxCnt = dicParam.EXPEDITION_CONST.EXPEDITION_CONST_TIMES; - - return { - resetCnt: maxCnt - expeditionResetCnt, - needRefresh - }; -} - -/** - * 根据比例计算机器人属性 - * @param attribute 出兵表中的属性字段 - * @param ce 我的战力 - * @param enemyCe 出兵表对手战力 - * @param ratio 系数 - */ - export function getRobotAttribute(hid: number, mainAttrs: { id: number, val: number }[], enemyCount: number, lv: number, ce: number, enemyCe: number, ratio: number) { - let _lv = Math.floor(lv * ratio) - let newAttribute = new AttributeCal(); - newAttribute.setLv(_lv); - let dicExpeditionSubAttr = gameData.expeditionSubAttr.get(_lv); - if(!dicExpeditionSubAttr) dicExpeditionSubAttr = gameData.expeditionSubAttr.get('max'); - newAttribute.setByWarJson(hid, dicExpeditionSubAttr.attribute); // 次级属性 - - let subAttrCe = newAttribute.calSubAttrCe() * enemyCount; - if(ce * ratio > subAttrCe) { - let mainAttrCe = ce * ratio - subAttrCe; - newAttribute.setByWarJson(hid, mainAttrs, mainAttrCe / enemyCe); - let attrArr = newAttribute.getAttributesToString(); - let newCe = newAttribute.calCe(); - return { attribute: attrArr, ce: newCe }; - } else { - newAttribute = new AttributeCal(); - newAttribute.setByWarJson(hid, mainAttrs, ce * ratio / enemyCe); - let attrArr = newAttribute.getAttributesToString(); - let newCe = newAttribute.calCe(); - return { attribute: attrArr, ce: newCe }; - } -} \ No newline at end of file + +import { ExpeditionPointModel } from '@db/ExpeditionPoint'; +import Role, { RoleModel } from '@db/Role'; +import { shouldRefresh, getRandSingleEelm } from '@pubUtils/util'; +import { EXPEDITION_WAR_RECORD_STATUS, SYSTEM_OPEN_ID } from '@consts'; +import { ExpeditionWarRecordModel } from '@db/ExpeditionWarRecord'; +import { HeroType } from '@db/Hero'; +import { gameData } from '@pubUtils/data'; +import { ExpeditionRecordModel } from '@db/ExpeditionRecord'; +import { Attribute, AttributeCal } from '@domain/roleField/attribute'; +import * as dicParam from '@pubUtils/dicParam'; +import { getHeroesAttributes, getSumCe } from './playerCeService'; +import { checkSystemIsOpen } from './roleService'; +import { ArtifactModel } from '@db/Artifact'; +import { JewelModel } from '@db/Jewel'; + +/** + * 获取远征关卡列表 + * @param roleId + * @param roleName + */ +export async function getExpeditionStatus(roleId: string, roleName: string, isEntry = false) { + // 重置次数 + let role = await RoleModel.findByRoleId(roleId); + if(!role.hasInit) return false; + if(isEntry && !checkSystemIsOpen(role, SYSTEM_OPEN_ID.EXPEDITION)) return false + // 获取远征关卡状态 + let expeditionRecord = await ExpeditionRecordModel.getCurRecord(roleId); + if (!expeditionRecord) { // 首次新建一条记录 + // 我方战力 + let myCe = await getSumCe(roleId); + expeditionRecord = await ExpeditionRecordModel.createRecord({ + roleId, roleName, heroes: [], myCe + }); + await findOrCreateEnemies(roleId, myCe, expeditionRecord.expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING); + } + + // 每一关的挑战状态 + let { expeditionCode, heroes } = expeditionRecord; + let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode); + let curLv = 0; + if (expeditionWarRecord.length > 0) { + curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId; + } + + let curTime = new Date(); + let { resetCnt } = await getResetRemainCnt(curTime, roleId, role); + + // 点数,和宝箱领取状态 + let pointRewards = await getPointRewardStatus(roleId, role); + return { + expeditionCode, + curLv, + expeditionWarRecord, + pointRewards, + heroes: heroes.map(cur => { return { "dataId": cur.seqId, "hp": cur.hp, "ap": cur.ap, "shield": cur.shield || 0, "others": cur.others || ''} }), + resetCnt + } +} + +/** + * 根据存下的战力获取当前远征关卡的对手 + * @param roleId 我的id + * @param myCe 存在expeditionRecord内的战力(缩过) + * @param expeditionCode 远征批次id + * @param expeditionId 该关卡id + * @param battleStatus 该关卡的挑战状态 + */ +export async function findOrCreateEnemies(roleId: string, myCe: number, expeditionCode: string, expeditionId: number, battleStatus: number) { + + let expeditionWarRecord = await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId, battleStatus); + if(!expeditionWarRecord) { // 如果没有信息 + let curDicExpedition = gameData.expedition.get(expeditionId); + if(curDicExpedition) { + + let enemyObj = { + enemyFrom: 0, + enemyId: '', + enemies: new Array(), + ce: 0 + }; + + // 获取系数和步长 + let { scale, range, lv } = await getCEScaleAndRange(roleId, curDicExpedition); + // 优先匹配其他玩家 + let flag = await matchPlayers(roleId, scale, range, myCe, curDicExpedition.json, enemyObj); + // 当数量不够时使用机器人匹配 + if(!flag) { + flag = await matchRobots(scale, myCe, curDicExpedition.ce, curDicExpedition.json, lv, enemyObj); + } + if(flag) { + // 保存 + let { warId } = curDicExpedition; + let { mapseid } = gameData.war.get(warId); + expeditionWarRecord = await ExpeditionWarRecordModel.saveRecord(expeditionCode, expeditionId, { + roleId, battleId: warId, mapseid: getRandSingleEelm(mapseid), ...enemyObj, battleStatus + }); + } + } + } + + // 处理当前血量 + let {enemiesCurHpAp, enemies} = expeditionWarRecord; + for(let enemy of enemies) { + let cur = {"hp": 0, "ap": 0}; + let getHp = enemiesCurHpAp && enemiesCurHpAp.find(cur => cur.dataId == enemy.dataId); + if(getHp) { + cur.hp = getHp.hp; + cur.ap = getHp.ap; + } else { + let attr = new Attribute(); + attr.setByStr(enemy.attribute); + cur.hp = attr.hp; + cur.ap = 0; + } + enemy["cur"] = cur; + } + + return expeditionWarRecord; +} + +/** + * 远征关卡匹配玩家 + * @param roleId 我的id + * @param scale 己方战力和对方战力比 + * @param range 浮动范围 + * @param myCe 己方战力(已缩小) + * @param warJsonIndex 模板出兵表id + * @param enemyObj 返回的敌军数据 + */ +export async function matchPlayers(roleId: string, scale: number, range: number, myCe: number, warJsonIndex:any, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array, ce: number }) { + let dicWarJson = gameData.warJson.get(warJsonIndex); + + let min = myCe * scale * (1 - range/100); + let max = myCe * scale * (1 + range/100); + + let resultRange = await RoleModel.findByCeScale(min, max); + resultRange = resultRange.filter(cur => cur.roleId != roleId); + if(resultRange.length > 0) { + let role = resultRange[0]; + let {roleId, topLineup, topLineupCe } = role; + let attrByHid = await getHeroesAttributes(roleId); + + enemyObj.enemyFrom = 1; + enemyObj.enemyId = roleId; + enemyObj.ce = topLineupCe; + + let hids = topLineup.map(cur => cur.hid); + let artifacts = await ArtifactModel.findbyHids(roleId, hids); + let jewels = await JewelModel.findbyRoleAndHids(roleId, hids); + + let heroIndex = 0; + for(let json of dicWarJson) { + if(json.relation == 2) { + let hero = topLineup[heroIndex]; + if(hero) { + let h = hero.hero; + if(h) { + let { star, lv, ce, skins, colorStar, quality, job, subHid = 0, subActorId = 0, ePlace = [] } = h; + let artifact = h.artifact? artifacts.find(cur => cur.seqId == h.artifact): null; + let skin = skins?.find(cur => cur.enable); + + let dicHero = gameData.hero.get(hero.hid); + let attr = attrByHid.get(hero.hid); + let attribute = attr.getAttributesToString(); + let heroInfo = { + actorId: hero.hid, + skinId: h.skinId, + actorName: dicHero.name, + skill:0, + seid:'&', + spine: 0, + attribute, + lv, + ce, + star, + colorStar, + quality, + job, + talent: skin? skin.talent: [], + artifact: artifact? [{ artifactId: artifact.artifactId, lv: artifact.lv }]: [], + subHid, + subActorId, + ePlace: ePlace.map(cur => ({ ...cur, jewel: jewels.find(ccur => cur.jewel == ccur.seqId) })), + }; + + enemyObj.enemies.push({...json, ...heroInfo}); + heroIndex ++; + } + } + } + } + if(enemyObj.enemies.length <= 0) return false + return true; + } else { + return false + } +} + +/** + * 匹配远征机器人 + * @param scale 己方战力和出兵表配置战力比 + * @param myCe 己方战力(已缩小) + * @param robotCe 机器人战力(10000,相当于已缩小战力) + * @param warJsonIndex 模板出兵表id + * @param lv 我的主公等级 + * @param enemyObj 返回的敌军数据 + */ +export async function matchRobots(scale: number, myCe: number, robotCe: number, warJsonIndex: number, lv: number, enemyObj: {enemyFrom: number, enemyId: string, enemies: Array, ce: number }) { + let dicWarJson = gameData.warJson.get(warJsonIndex); + if(dicWarJson) { + enemyObj.enemyFrom = 2; + enemyObj.enemyId = warJsonIndex + ''; + + let allCe = 0; + for(let json of dicWarJson) { + if(json.relation == 2) { + const { actorId, attribute, enemyCount } = json; + + let dicHero = gameData.hero.get(actorId); + let { attribute: newAttribute, ce } = getRobotAttribute(actorId, attribute, enemyCount, lv, myCe, robotCe, scale); + enemyObj.enemies.push({...json, skinId: json.actorId, attribute: newAttribute, lv, ce, + star: dicHero.initialStar, + colorStar: dicHero.initialColorStar, + quality: dicHero.quality, + job: dicHero.jobid, + talent: [], + artifact: [], + subHid: 0, + subActorId: 0 + }); + allCe += ce; + } + } + + enemyObj.ce = Math.floor(allCe); + + return true + } else { + return false + } +} + +// 远征匹配系数表 +export async function getCEScaleAndRange(roleId: string, curDicExpedition: any) { + // 匹配,判断是不是新手期 + const role = await RoleModel.findByRoleId(roleId); + let isNew = (role.expeditionHistoryResetCnt||0) <= 3; + + let scale = isNew?curDicExpedition.CEScaleNew:curDicExpedition.CEScale; + let range = isNew?curDicExpedition.CERangeNew:curDicExpedition.CERange; + return {scale, range, lv: role.lv} +} + +// 远征累计点数获取 +export async function getPointRewardStatus(roleId: string, role?: Role) { + if(!role) { + role = await RoleModel.findByRoleId(roleId); + } + let {expeditionPoint = 0} = role; + let dicExpeditionPoint = gameData.expeditionPoint; + let rewards: { point: number, received: boolean }[] = []; + for(let [point] of dicExpeditionPoint) { + rewards.push({ point, received: false }) + } + let pointRewards = { + expeditionPoint, rewards + }; + let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId); + if(pointStatusInDatabase) { + let { rewards = [] } = pointStatusInDatabase; + pointRewards.rewards.forEach(cur => { + let obj = rewards.find(ccur => ccur.point == cur.point); + if(obj) cur.received = obj.received; + }); + } + return pointRewards +} + +export async function getResetRemainCnt(curTime: Date, roleId: string, role?: Role, ) { + if(!role) { + role = await RoleModel.findByRoleId(roleId); + } + + let { expeditionResetCnt, expeditionResetRefTime } = role; + let needRefresh = !expeditionResetRefTime || shouldRefresh(expeditionResetRefTime, curTime); + if(needRefresh) { + expeditionResetCnt = 0; expeditionResetRefTime = curTime; + } + + let maxCnt = dicParam.EXPEDITION_CONST.EXPEDITION_CONST_TIMES; + + return { + resetCnt: maxCnt - expeditionResetCnt, + needRefresh + }; +} + +/** + * 根据比例计算机器人属性 + * @param attribute 出兵表中的属性字段 + * @param ce 我的战力 + * @param enemyCe 出兵表对手战力 + * @param ratio 系数 + */ + export function getRobotAttribute(hid: number, mainAttrs: { id: number, val: number }[], enemyCount: number, lv: number, ce: number, enemyCe: number, ratio: number) { + let _lv = Math.floor(lv * ratio) + let newAttribute = new AttributeCal(); + newAttribute.setLv(_lv); + let dicExpeditionSubAttr = gameData.expeditionSubAttr.get(_lv); + if(!dicExpeditionSubAttr) dicExpeditionSubAttr = gameData.expeditionSubAttr.get('max'); + newAttribute.setByWarJson(hid, dicExpeditionSubAttr.attribute); // 次级属性 + + let subAttrCe = newAttribute.calSubAttrCe() * enemyCount; + if(ce * ratio > subAttrCe) { + let mainAttrCe = ce * ratio - subAttrCe; + newAttribute.setByWarJson(hid, mainAttrs, mainAttrCe / enemyCe); + let attrArr = newAttribute.getAttributesToString(); + let newCe = newAttribute.calCe(); + return { attribute: attrArr, ce: newCe }; + } else { + newAttribute = new AttributeCal(); + newAttribute.setByWarJson(hid, mainAttrs, ce * ratio / enemyCe); + let attrArr = newAttribute.getAttributesToString(); + let newCe = newAttribute.calCe(); + return { attribute: attrArr, ce: newCe }; + } +} diff --git a/game-server/app/services/friendService.ts b/game-server/app/services/friendService.ts index fbf55a234..0e17f9178 100644 --- a/game-server/app/services/friendService.ts +++ b/game-server/app/services/friendService.ts @@ -1,236 +1,236 @@ -import { gameData, getDicFriendByLv } from "../pubUtils/data"; -import { RoleType, RoleModel } from "../db/Role"; -import { FriendRelationType, Relation, FriendRelationModel } from "../db/FriendRelation"; -import { getResStr, shouldRefresh } from "../pubUtils/util"; -import { STATUS, FRIEND_RELATION_TYPE, POPULATE_TYPE, FRIEND_DROP_TYPE } from "../consts"; -import { FriendShipType, FriendShipModel } from "../db/FriendShip"; -import { outputCnt } from '../pubUtils/friendUtil'; -import { isRoleOnline, getServerName, getRoleOnlineInfo } from "./redisService"; -import { FriendApplyModel } from "../db/FriendApply"; -import { FriendApplyParams, FriendListParam } from "../domain/roleField/friend"; -import { FRIEND } from "../pubUtils/dicParam"; -import { FriendPointModel } from "../db/FriendPoint"; - -export async function getFriendList(role: RoleType) { - let { roleId } = role; - let list = new Array(); - let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); - let friendList = myRelation ? myRelation.friends : []; - - for (let friend of friendList) { - let friendRole = friend.role; - let friendShip = friend.friendShip; - if (!friendRole || !friendShip) continue; - - let fs = friend.friendShip; - let ref = shouldRefresh(fs.refTime, new Date()); - if (ref) { - friendShip = await FriendShipModel.refreshSendAndReceive(roleId, friendRole.roleId); - } - - let param = new FriendListParam(friendRole, roleId, friendShip); - let { serverId } = friendRole; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - let isOnline = await isRoleOnline(friendRole.roleId); - param.setOnline(isOnline); - - param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); - - list.push(param); - } - - list.sort((a, b) => { - if (a.isOnline != b.isOnline) { - return a.isOnline ? 1 : -1 - } - if (a.quitTime != b.quitTime) { - return b.quitTime - a.quitTime - } - return a.friendValue - b.friendValue; - }); - - let { friendCnt = 0, blockCnt = 0 } = role; - let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); - let { cnt: todayReceiveCnt = 0, sendCnt: todaySendCnt = 0 } = frdPointRec || {}; - - return { - todayReceiveCnt, - todaySendCnt, - list, - friendCnt, blockCnt - } -} - -/** - * 获取玩家申请列表 - * @param roleId 玩家id - */ -export async function getApplyList(roleId: string) { - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - let list = await FriendApplyModel.getApplyList(roleId); - let result = new Array(); - let delApplyCodeList = new Array(); - for (let apply of list) { - let friend = apply.friend; - let type = getRecommendType(myFriendRelation, roleId, friend.roleId); - - let param = new FriendApplyParams(apply.applyCode, friend); - - let { serverId } = friend; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - param.setType(type); - if (type != FRIEND_RELATION_TYPE.NORMAL) { - delApplyCodeList.push(apply.applyCode); - continue; - } - - result.push(param); - } - let deleteCount = await FriendApplyModel.deleteApply(delApplyCodeList); - await RoleModel.increaseFriendApplyCnt(roleId, -1 * deleteCount, FRIEND.FRIEND_MANAGE_APPLICATION); - return result; -} - -export async function getMyApplyParam(applyCode: string, role: RoleType) { - let param = new FriendApplyParams(applyCode, role); - - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - param.setType(FRIEND_RELATION_TYPE.NORMAL); - return param; -} - - -export async function getMyParamAsFriend(friendShip: FriendShipType, role: RoleType, friendRoleId: string) { - let param = new FriendListParam(role, friendRoleId, friendShip); - let hisOnlineInfo = await getRoleOnlineInfo(role.roleId); - param.setOnline(hisOnlineInfo.isOnline); - - let { serverId } = role; - let serverName = await getServerName(serverId); - param.setServerName(serverId, serverName); - - param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); - return param; -} - -/** - * 增加双方好友数 - * @param role1 我方 - * @param role2 对方 - * @returns 是否添加成功 - */ -export async function increaseFrdCnt(role1: RoleType, role2: RoleType, originalFriendCnt: number) { - - let { roleId, lv, friendCnt } = role1; - let dicFriend = getDicFriendByLv(lv); - if(friendCnt >= dicFriend.frdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX); - - let { roleId: _roleId, lv: _lv, friendCnt: _friendCnt } = role2; - let _dicFriend = getDicFriendByLv(_lv); - if(_friendCnt >= _dicFriend.frdCnt) return getResStr(STATUS.FRIEND_THEY_CNT_MAX); - - let incMyFrdCnt = await RoleModel.increaseFriendCnt(roleId, 1, dicFriend.frdCnt); - if(!incMyFrdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX); - let incHisFrdCnt = await RoleModel.increaseFriendCnt(_roleId, 1, _dicFriend.frdCnt); - if(!incHisFrdCnt) { // 回滚 - await RoleModel.increaseFriendCnt(roleId, -1, dicFriend.frdCnt); - return getResStr(STATUS.FRIEND_THEY_CNT_MAX); - } - originalFriendCnt = incMyFrdCnt.friendCnt; - role1.friendCnt = incMyFrdCnt.friendCnt; - role2.friendCnt = incHisFrdCnt.friendCnt; - - return ''; -} - -export async function getFriendRelationType(myRoleId: string, roleId: string) { - let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); - return getRecommendType(myFriendRelation, roleId, myRoleId); -} - -export function getRecommendType(myFriendRelation: FriendRelationType, myRoleId: string, roleId: string) { - if(myRoleId == roleId) { - return FRIEND_RELATION_TYPE.MYSELF; - } - let friendList = myFriendRelation? myFriendRelation.friends: []; - let blackList = myFriendRelation? myFriendRelation.blacklist: []; - let hasFriend = friendList.find(cur => cur.roleId == roleId); - if(hasFriend) { - return FRIEND_RELATION_TYPE.HAS_FRIEND; - } - let hasBlcklist = blackList.find(cur => cur.roleId == roleId); - if(hasBlcklist) { - return FRIEND_RELATION_TYPE.HAS_BLOCKED; - } - return FRIEND_RELATION_TYPE.NORMAL; -} - -/** - * 根据收到的新及时间排序 - * - * @param roleId 自己的玩家id - * @param list 需要排序列表 - */ -export async function sortByBeSentHeart(roleId: string, list: Relation[]) { - - let result = new Array(); - for(let cur of list) { - let json = getSentHeart(roleId, cur); - let friendRole = cur.role; - let friendShip = cur.friendShip; - let isOnline = await isRoleOnline(friendRole.roleId); - result.push({...cur, ...json, isOnline, quitTime: friendRole.quitTime, friendValue: friendShip.friendValue}); - } - - result.sort((a, b) => { - if(a.beSentHeart && b.beSentHeart) { // 只要有一方送过 - if(a.beSentHeart == b.beSentHeart) { - return a.beSentHeartTime - b.beSentHeartTime; - } else { - return b.beSentHeart - a.beSentHeart; - } - } else { // 都没送过的情况 - if(a.isOnline != b.isOnline) { - return a.isOnline?1:-1 - } - if(a.quitTime != b.quitTime) { - return b.quitTime - a.quitTime - } - return a.friendValue - b.friendValue; - } - }); - return result -} - -function getSentHeart(roleId: string, relation: Relation) { - let friendShip = relation.friendShip; - let json = outputCnt(roleId, friendShip); - if(!json) { - return { - beSentHeart: 0, - beSentHeartTime: 0 - } - } - return { - beSentHeart: json.beSentHeart, - beSentHeartTime: json.beSentHeartTime - } -} - -export async function getFriendLvAdd(roleId: string, hisRoleId: string) { - let friendShip = await FriendShipModel.getFriendLv(roleId, hisRoleId); - if(!friendShip) { - return 0 - } - let dic = gameData.roleFriendLv.get(friendShip.friendLv); - if(!dic) { - return 0 - } - return dic.comBattleAdd -} \ No newline at end of file +import { gameData, getDicFriendByLv } from "@pubUtils/data"; +import { RoleType, RoleModel } from "@db/Role"; +import { FriendRelationType, Relation, FriendRelationModel } from "@db/FriendRelation"; +import { getResStr, shouldRefresh } from "@pubUtils/util"; +import { STATUS, FRIEND_RELATION_TYPE, POPULATE_TYPE, FRIEND_DROP_TYPE } from "@consts"; +import { FriendShipType, FriendShipModel } from "@db/FriendShip"; +import { outputCnt } from '@pubUtils/friendUtil'; +import { isRoleOnline, getServerName, getRoleOnlineInfo } from "./redisService"; +import { FriendApplyModel } from "@db/FriendApply"; +import { FriendApplyParams, FriendListParam } from "@domain/roleField/friend"; +import { FRIEND } from "@pubUtils/dicParam"; +import { FriendPointModel } from "@db/FriendPoint"; + +export async function getFriendList(role: RoleType) { + let { roleId } = role; + let list = new Array(); + let myRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.FRIEND); + let friendList = myRelation ? myRelation.friends : []; + + for (let friend of friendList) { + let friendRole = friend.role; + let friendShip = friend.friendShip; + if (!friendRole || !friendShip) continue; + + let fs = friend.friendShip; + let ref = shouldRefresh(fs.refTime, new Date()); + if (ref) { + friendShip = await FriendShipModel.refreshSendAndReceive(roleId, friendRole.roleId); + } + + let param = new FriendListParam(friendRole, roleId, friendShip); + let { serverId } = friendRole; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + let isOnline = await isRoleOnline(friendRole.roleId); + param.setOnline(isOnline); + + param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); + + list.push(param); + } + + list.sort((a, b) => { + if (a.isOnline != b.isOnline) { + return a.isOnline ? 1 : -1 + } + if (a.quitTime != b.quitTime) { + return b.quitTime - a.quitTime + } + return a.friendValue - b.friendValue; + }); + + let { friendCnt = 0, blockCnt = 0 } = role; + let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT); + let { cnt: todayReceiveCnt = 0, sendCnt: todaySendCnt = 0 } = frdPointRec || {}; + + return { + todayReceiveCnt, + todaySendCnt, + list, + friendCnt, blockCnt + } +} + +/** + * 获取玩家申请列表 + * @param roleId 玩家id + */ +export async function getApplyList(roleId: string) { + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + let list = await FriendApplyModel.getApplyList(roleId); + let result = new Array(); + let delApplyCodeList = new Array(); + for (let apply of list) { + let friend = apply.friend; + let type = getRecommendType(myFriendRelation, roleId, friend.roleId); + + let param = new FriendApplyParams(apply.applyCode, friend); + + let { serverId } = friend; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + param.setType(type); + if (type != FRIEND_RELATION_TYPE.NORMAL) { + delApplyCodeList.push(apply.applyCode); + continue; + } + + result.push(param); + } + let deleteCount = await FriendApplyModel.deleteApply(delApplyCodeList); + await RoleModel.increaseFriendApplyCnt(roleId, -1 * deleteCount, FRIEND.FRIEND_MANAGE_APPLICATION); + return result; +} + +export async function getMyApplyParam(applyCode: string, role: RoleType) { + let param = new FriendApplyParams(applyCode, role); + + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + param.setType(FRIEND_RELATION_TYPE.NORMAL); + return param; +} + + +export async function getMyParamAsFriend(friendShip: FriendShipType, role: RoleType, friendRoleId: string) { + let param = new FriendListParam(role, friendRoleId, friendShip); + let hisOnlineInfo = await getRoleOnlineInfo(role.roleId); + param.setOnline(hisOnlineInfo.isOnline); + + let { serverId } = role; + let serverName = await getServerName(serverId); + param.setServerName(serverId, serverName); + + param.setType(FRIEND_RELATION_TYPE.HAS_FRIEND); + return param; +} + +/** + * 增加双方好友数 + * @param role1 我方 + * @param role2 对方 + * @returns 是否添加成功 + */ +export async function increaseFrdCnt(role1: RoleType, role2: RoleType, originalFriendCnt: number) { + + let { roleId, lv, friendCnt } = role1; + let dicFriend = getDicFriendByLv(lv); + if(friendCnt >= dicFriend.frdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX); + + let { roleId: _roleId, lv: _lv, friendCnt: _friendCnt } = role2; + let _dicFriend = getDicFriendByLv(_lv); + if(_friendCnt >= _dicFriend.frdCnt) return getResStr(STATUS.FRIEND_THEY_CNT_MAX); + + let incMyFrdCnt = await RoleModel.increaseFriendCnt(roleId, 1, dicFriend.frdCnt); + if(!incMyFrdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX); + let incHisFrdCnt = await RoleModel.increaseFriendCnt(_roleId, 1, _dicFriend.frdCnt); + if(!incHisFrdCnt) { // 回滚 + await RoleModel.increaseFriendCnt(roleId, -1, dicFriend.frdCnt); + return getResStr(STATUS.FRIEND_THEY_CNT_MAX); + } + originalFriendCnt = incMyFrdCnt.friendCnt; + role1.friendCnt = incMyFrdCnt.friendCnt; + role2.friendCnt = incHisFrdCnt.friendCnt; + + return ''; +} + +export async function getFriendRelationType(myRoleId: string, roleId: string) { + let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, POPULATE_TYPE.NOT); + return getRecommendType(myFriendRelation, roleId, myRoleId); +} + +export function getRecommendType(myFriendRelation: FriendRelationType, myRoleId: string, roleId: string) { + if(myRoleId == roleId) { + return FRIEND_RELATION_TYPE.MYSELF; + } + let friendList = myFriendRelation? myFriendRelation.friends: []; + let blackList = myFriendRelation? myFriendRelation.blacklist: []; + let hasFriend = friendList.find(cur => cur.roleId == roleId); + if(hasFriend) { + return FRIEND_RELATION_TYPE.HAS_FRIEND; + } + let hasBlcklist = blackList.find(cur => cur.roleId == roleId); + if(hasBlcklist) { + return FRIEND_RELATION_TYPE.HAS_BLOCKED; + } + return FRIEND_RELATION_TYPE.NORMAL; +} + +/** + * 根据收到的新及时间排序 + * + * @param roleId 自己的玩家id + * @param list 需要排序列表 + */ +export async function sortByBeSentHeart(roleId: string, list: Relation[]) { + + let result = new Array(); + for(let cur of list) { + let json = getSentHeart(roleId, cur); + let friendRole = cur.role; + let friendShip = cur.friendShip; + let isOnline = await isRoleOnline(friendRole.roleId); + result.push({...cur, ...json, isOnline, quitTime: friendRole.quitTime, friendValue: friendShip.friendValue}); + } + + result.sort((a, b) => { + if(a.beSentHeart && b.beSentHeart) { // 只要有一方送过 + if(a.beSentHeart == b.beSentHeart) { + return a.beSentHeartTime - b.beSentHeartTime; + } else { + return b.beSentHeart - a.beSentHeart; + } + } else { // 都没送过的情况 + if(a.isOnline != b.isOnline) { + return a.isOnline?1:-1 + } + if(a.quitTime != b.quitTime) { + return b.quitTime - a.quitTime + } + return a.friendValue - b.friendValue; + } + }); + return result +} + +function getSentHeart(roleId: string, relation: Relation) { + let friendShip = relation.friendShip; + let json = outputCnt(roleId, friendShip); + if(!json) { + return { + beSentHeart: 0, + beSentHeartTime: 0 + } + } + return { + beSentHeart: json.beSentHeart, + beSentHeartTime: json.beSentHeartTime + } +} + +export async function getFriendLvAdd(roleId: string, hisRoleId: string) { + let friendShip = await FriendShipModel.getFriendLv(roleId, hisRoleId); + if(!friendShip) { + return 0 + } + let dic = gameData.roleFriendLv.get(friendShip.friendLv); + if(!dic) { + return 0 + } + return dic.comBattleAdd +} diff --git a/game-server/app/services/getui/getuiService.ts b/game-server/app/services/getui/getuiService.ts index c8ff8c0a1..425d4f249 100644 --- a/game-server/app/services/getui/getuiService.ts +++ b/game-server/app/services/getui/getuiService.ts @@ -1,183 +1,183 @@ -import { ACTIVITY_TYPE, HTTP_METHOD } from '../../consts'; -import { httpRequest } from '../../pubUtils/httpUtil'; -import { ServerTempModel } from '../../db/ServerTemp'; -import { GetuiMessagesModel } from '../../db/GetuiMessages'; - -const crypto = require('crypto'); -const APP_ID = "T5QiUVuzjw5nNT2kwjZpD2" -const APP_KEY = "IoP3lJYAgO63UWKSx6JyV2" -const APP_SECRET = "K9tGNJBnOt7iUBjXZ13hd4" -const PACKAGE_NAME = "com.getui.demo" -const MASTER_SECRET = "VVVRlJDaog7RWbLffpHzAA" -const BASE_URL = `https://restapi.getui.com/v2/${APP_ID}` - - -/** - * 获取token - * - * - */ -export async function GTAuth() { - let url = `${BASE_URL}/auth`; - let headers = { - 'content-type': 'application/json;charset=utf-8', - }; - const timestamp = new Date().getTime(); - let body = { - sign: getSign(timestamp), - timestamp, - appkey: APP_KEY, - }; - let result = await httpRequest(url, HTTP_METHOD.POST, body, headers) - if (result.code == 0) { - console.log('GETUI_TOKEN', result.data.token) - return await ServerTempModel.updateGetuiData(result.data.token, result.data.expire_time); - } - return null; -} - -/** - * 执行cid单推 - * - * @param {number} ttl 离线时间1-3天,单位毫秒 - * @param {string} cid 玩家cid - * @param {string} title 信息标题 - * @param {string} bodyStr 信息内容 - * - */ -export async function GTPushSingleCidMessage(cid: string, ttl: number, title: string, bodyStr: string,) { - let url = `${BASE_URL}/push/single/cid`; - let body = { - "request_id": uuid(),//唯一标识 - "settings": { - "ttl": ttl,//259200000//1-3天,单位毫秒 - }, - "audience": { - "cid": [ - cid - ] - }, - "push_message": {//个推通道消息内容 - "notification": {//仅支持安卓系统,iOS系统不展示个推通道下发的通知消息 - "title": title, - "body": bodyStr, - "click_type": "none", - "url": "" - } - } - } - let result = await request(url, HTTP_METHOD.POST, {}, body) - //{"msg":"success","code":0,"data":{"RASS_0630_a35e791ba3f04c84b741b9e5f17963ae":{"ba64ee9a9d516bbd341267d685baceb4":"successed_online"}}} - //successed_online在线 successed_offline离线 - if (result.code == 0) { - await GetuiMessagesModel.insertSingleMessage(body.request_id, JSON.stringify(body), 'GTPushSingleCidMessage', true) - return true; - } - return false; -} - -/** - * 执行cid批量推 - * - * @param {string} taskid 任务id - * @param {string[]} cid cid数组 - * @param {boolean} isAsync 是否异步 - * - */ -export async function GTPushListCidMessage(taskid: string, cid: string[], isAsync: boolean = true) { - let url = `${BASE_URL}/push/list/cid`; - let body = { - "taskid": taskid, - "audience": { - "cid": cid, - }, - "is_async": isAsync,//是否异步 - } - let result = await request(url, HTTP_METHOD.POST, {}, body) - if (result.code == 0) { - await GetuiMessagesModel.pushMessageSuccess(taskid, true); - return true; - } - return false; -} - -/** - * 创建消息,此接口用来创建消息体,并返回taskid,为批量推的前置步骤 - * - * @param {number} ttl 离线时间1-3天,单位毫秒 - * @param {string} group_name 任务组名 - * @param {string} title 信息标题 - * @param {string} bodyStr 信息内容 - * - */ -export async function GTCreateListMessage(group_name: string, ttl: number, title: string, bodyStr: string,) { - let url = `${BASE_URL}/push/list/message`; - let body = { - "request_id": uuid(),//唯一标识 - "group_name": group_name,//"请填写任务组名", - "settings": { - "ttl": ttl,//259200000//1-3天,单位毫秒 - }, - "push_message": {//个推通道消息内容 - "notification": {//仅支持安卓系统,iOS系统不展示个推通道下发的通知消息 - "title": title, - "body": bodyStr, - "click_type": "none", - "url": "" - } - } - } - let result = await request(url, HTTP_METHOD.POST, {}, body) - //{"msg":"success","code":0,"data":{"taskid":"RASL_0630_da707a0c484d4ee39f2d462d5f52984c"}} - //taskid 任务编号,用于执行cid批量推和执行别名批量推,此taskid可以多次使用,有效期为用户设置的离线时间 - if (result.code == 0) { - await GetuiMessagesModel.insertListMessage(body.request_id, result.data.taskid, JSON.stringify(body), 'GTCreateListMessage', false) - return result.data.taskid; - } - return false; -} - -export async function request(url: string, method: string, headers: any, body: any) { - const timestamp = new Date().getTime(); - let tokenData = await ServerTempModel.findGetuiData(); - - if (!tokenData || (!tokenData.getuiTokenExpireTime) || timestamp > tokenData.getuiTokenExpireTime) { - tokenData = await GTAuth() - if (tokenData) { - console.log('token success') - } else { - console.log('token fail......') - } - } - - headers = { ...headers, 'content-type': 'application/json;charset=utf-8', 'token': tokenData.getuiToken }; - let result = await httpRequest(url, method, body, headers) - if (result.code == 10001) { - if (await GTAuth()) { - console.log('token success11') - } else { - console.log('token fail......') - } - } - return result; -} - - -/** - * 获取签名 - * @param timestamp 时间戳 - */ -function getSign(timestamp: number) { - let stringToSign = `${APP_KEY}${timestamp}${MASTER_SECRET}`; - return crypto.createHash('sha256').update(stringToSign).digest('hex'); -} - -function uuid() { - var d = new Date().getTime(); - var uuid = d + '-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = (d + Math.random() * 16) % 16 | 0; - d = Math.floor(d / 16); - return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16); - }); - return uuid; -}; \ No newline at end of file +import { ACTIVITY_TYPE, HTTP_METHOD } from '@consts'; +import { httpRequest } from '@pubUtils/httpUtil'; +import { ServerTempModel } from '@db/ServerTemp'; +import { GetuiMessagesModel } from '@db/GetuiMessages'; + +const crypto = require('crypto'); +const APP_ID = "T5QiUVuzjw5nNT2kwjZpD2" +const APP_KEY = "IoP3lJYAgO63UWKSx6JyV2" +const APP_SECRET = "K9tGNJBnOt7iUBjXZ13hd4" +const PACKAGE_NAME = "com.getui.demo" +const MASTER_SECRET = "VVVRlJDaog7RWbLffpHzAA" +const BASE_URL = `https://restapi.getui.com/v2/${APP_ID}` + + +/** + * 获取token + * + * + */ +export async function GTAuth() { + let url = `${BASE_URL}/auth`; + let headers = { + 'content-type': 'application/json;charset=utf-8', + }; + const timestamp = new Date().getTime(); + let body = { + sign: getSign(timestamp), + timestamp, + appkey: APP_KEY, + }; + let result = await httpRequest(url, HTTP_METHOD.POST, body, headers) + if (result.code == 0) { + console.log('GETUI_TOKEN', result.data.token) + return await ServerTempModel.updateGetuiData(result.data.token, result.data.expire_time); + } + return null; +} + +/** + * 执行cid单推 + * + * @param {number} ttl 离线时间1-3天,单位毫秒 + * @param {string} cid 玩家cid + * @param {string} title 信息标题 + * @param {string} bodyStr 信息内容 + * + */ +export async function GTPushSingleCidMessage(cid: string, ttl: number, title: string, bodyStr: string,) { + let url = `${BASE_URL}/push/single/cid`; + let body = { + "request_id": uuid(),//唯一标识 + "settings": { + "ttl": ttl,//259200000//1-3天,单位毫秒 + }, + "audience": { + "cid": [ + cid + ] + }, + "push_message": {//个推通道消息内容 + "notification": {//仅支持安卓系统,iOS系统不展示个推通道下发的通知消息 + "title": title, + "body": bodyStr, + "click_type": "none", + "url": "" + } + } + } + let result = await request(url, HTTP_METHOD.POST, {}, body) + //{"msg":"success","code":0,"data":{"RASS_0630_a35e791ba3f04c84b741b9e5f17963ae":{"ba64ee9a9d516bbd341267d685baceb4":"successed_online"}}} + //successed_online在线 successed_offline离线 + if (result.code == 0) { + await GetuiMessagesModel.insertSingleMessage(body.request_id, JSON.stringify(body), 'GTPushSingleCidMessage', true) + return true; + } + return false; +} + +/** + * 执行cid批量推 + * + * @param {string} taskid 任务id + * @param {string[]} cid cid数组 + * @param {boolean} isAsync 是否异步 + * + */ +export async function GTPushListCidMessage(taskid: string, cid: string[], isAsync: boolean = true) { + let url = `${BASE_URL}/push/list/cid`; + let body = { + "taskid": taskid, + "audience": { + "cid": cid, + }, + "is_async": isAsync,//是否异步 + } + let result = await request(url, HTTP_METHOD.POST, {}, body) + if (result.code == 0) { + await GetuiMessagesModel.pushMessageSuccess(taskid, true); + return true; + } + return false; +} + +/** + * 创建消息,此接口用来创建消息体,并返回taskid,为批量推的前置步骤 + * + * @param {number} ttl 离线时间1-3天,单位毫秒 + * @param {string} group_name 任务组名 + * @param {string} title 信息标题 + * @param {string} bodyStr 信息内容 + * + */ +export async function GTCreateListMessage(group_name: string, ttl: number, title: string, bodyStr: string,) { + let url = `${BASE_URL}/push/list/message`; + let body = { + "request_id": uuid(),//唯一标识 + "group_name": group_name,//"请填写任务组名", + "settings": { + "ttl": ttl,//259200000//1-3天,单位毫秒 + }, + "push_message": {//个推通道消息内容 + "notification": {//仅支持安卓系统,iOS系统不展示个推通道下发的通知消息 + "title": title, + "body": bodyStr, + "click_type": "none", + "url": "" + } + } + } + let result = await request(url, HTTP_METHOD.POST, {}, body) + //{"msg":"success","code":0,"data":{"taskid":"RASL_0630_da707a0c484d4ee39f2d462d5f52984c"}} + //taskid 任务编号,用于执行cid批量推和执行别名批量推,此taskid可以多次使用,有效期为用户设置的离线时间 + if (result.code == 0) { + await GetuiMessagesModel.insertListMessage(body.request_id, result.data.taskid, JSON.stringify(body), 'GTCreateListMessage', false) + return result.data.taskid; + } + return false; +} + +export async function request(url: string, method: string, headers: any, body: any) { + const timestamp = new Date().getTime(); + let tokenData = await ServerTempModel.findGetuiData(); + + if (!tokenData || (!tokenData.getuiTokenExpireTime) || timestamp > tokenData.getuiTokenExpireTime) { + tokenData = await GTAuth() + if (tokenData) { + console.log('token success') + } else { + console.log('token fail......') + } + } + + headers = { ...headers, 'content-type': 'application/json;charset=utf-8', 'token': tokenData.getuiToken }; + let result = await httpRequest(url, method, body, headers) + if (result.code == 10001) { + if (await GTAuth()) { + console.log('token success11') + } else { + console.log('token fail......') + } + } + return result; +} + + +/** + * 获取签名 + * @param timestamp 时间戳 + */ +function getSign(timestamp: number) { + let stringToSign = `${APP_KEY}${timestamp}${MASTER_SECRET}`; + return crypto.createHash('sha256').update(stringToSign).digest('hex'); +} + +function uuid() { + var d = new Date().getTime(); + var uuid = d + '-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16); + }); + return uuid; +}; diff --git a/game-server/app/services/gmService.ts b/game-server/app/services/gmService.ts index 79fe282a0..300539b07 100644 --- a/game-server/app/services/gmService.ts +++ b/game-server/app/services/gmService.ts @@ -1,403 +1,403 @@ -import { MarqueeType, MarqueeModel } from "../db/Marquee"; -import { ACTIVITY_TYPE, MARQUEE_SHOW_TYPE, MARQUEE_TIME_TYPE, REDIS_KEY, SURVEY_SELECT } from "../consts"; -import { scheduleJob, scheduledJobs, Job } from 'node-schedule'; -import { createMarqueeMsg as sysCreateMarqueeMsg, pushMarqueeMsg as sysPushMarqueeMsg } from './sysChatService'; -import { GroupMessageType } from "../db/GroupMessage"; -import { pinus } from "pinus"; -import { ServerlistModel, ServerlistType } from "../db/Serverlist"; -import { sendMailsByGmMail } from "./mailService"; -import GMMail, { GMMailModel, GMMailType, Receiver } from '../db/GMMail'; -import { getPastTime, nowSeconds } from "../pubUtils/timeUtil"; -import { CreateServerParam } from "../domain/backEndField/params"; -import { SignInData } from "../domain/activityField/signInField"; -import { RegionModel, RegionType } from "../db/Region"; -import { GMMail as StategyMail } from "../db/ServerStategy"; -import { uniq } from "underscore"; -import { ActivityModel, ActivityModelType } from "../db/Activity"; -import { dicRMB } from "../pubUtils/dictionary/DicRMB"; -import { LimitShopData } from "../domain/activityField/limitShopField"; -import { YuanBaoShopData } from "../domain/activityField/yuanBaoShopField"; -import { MonthlyTicketData } from "../domain/activityField/monthlyTicketField"; -import { DailyRMBGiftsData } from "../domain/activityField/dailyRMBGiftsField"; -import { PopShopItem, PopUpShopData, PopUpShopPackage } from "../domain/activityField/popUpShopField"; -import { GrowthFundData } from "../domain/activityField/growthFundField"; -import { TreasureHuntData } from "../domain/activityField/treasureHuntField"; -import { RefreshShopData } from "../domain/activityField/refreshShopField"; -import { RoleType } from "../db/Role"; -import { MonopolyData } from "../domain/activityField/monopolyField"; -import { ActivityPopUpShopModel, PopUpShopItem } from "../db/ActivityPopUpShop"; -import { getActivitiesByType } from "./activity/activityService"; -import { SurveyModel } from "../db/Survery"; -import { SurveyRecModel } from "../db/SurveyRec"; -import { getPopUpShopData } from "./activity/popUpShopService"; -import { TaskPassData } from "../domain/activityField/taskPassField"; -import { ActivityGroupModel } from "../db/ActivityGroup"; -import { redisClient } from "./redisService"; -import { gameData } from "../pubUtils/data"; -import { GuildModel } from "../db/Guild"; -import { GuildTrainModel } from "../db/GuildTrain"; -import { unlockTrain } from "./guildTrainService"; -import { HiddenDataModel, HiddenDataModelType } from "../db/HiddenData"; -import { HiddenDataByIdModel } from "../db/HiddenDataById"; -import moment = require("moment"); - -// —————————————— 跑马灯 —————————————— // -// 初始 -export async function initMarquee() { - const marquees = await MarqueeModel.findEffectiveMarque(pinus.app.get('env')); - for(let marquee of marquees) { - await generateMarqueeSchedule(marquee); - } -} - -export async function setMarquee(marquee: MarqueeType) { - console.log('******', marquee.timeType, marquee) - if(marquee.timeType == MARQUEE_TIME_TYPE.INSTANT) { - await startMarquee(marquee); - return true; - } else { - return await generateMarqueeSchedule(marquee); - } -} - -async function generateMarqueeSchedule(marquee: MarqueeType) { - // 定时发送 - let setSecondsMarquee = scheduledJobs[`setSeconds${marquee.code}`]; - if(setSecondsMarquee) return false; // 已经在运行中了 - - if(marquee.timeType != MARQUEE_TIME_TYPE.SCHEDULE) return false; - if(marquee.endTime && marquee.endTime < nowSeconds()) return false; - let startJob = scheduleJob(`start${marquee.code}`, marquee.startTime * 1000, async () => { - await startMarquee(marquee, startJob) - }); - return true; -} - -async function startMarquee(marquee: MarqueeType, startJob?: Job) { - console.log('************', `跑马灯定时器 ${marquee.code}开始`, '************'); - let msgDatas = await createMarqueeMsg(marquee); - if(marquee.showType == MARQUEE_SHOW_TYPE.ONCE) { // 一次性发送 - await pushMarqueeMsg(msgDatas); - if(startJob) { - startJob.cancel(); - startJob = undefined; - } - } else { - if(marquee.endTime > nowSeconds()) { - await pushMarqueeMsg(msgDatas); - let secondsJob = scheduleJob(`setSeconds${marquee.code}`, `*/${marquee.interval} * * * * *`, async () => { - console.log(`*****setSeconds${marquee.code}****`) - await pushMarqueeMsg(msgDatas); - }); - let endJob = scheduleJob(`end${marquee.code}`, marquee.endTime * 1000, async () => { - if(startJob) { - startJob.cancel(); - startJob = undefined; - } - if(secondsJob) { - secondsJob.cancel(); - secondsJob = undefined; - } - if(endJob) { - endJob.cancel(); - endJob = undefined; - } - }); - } else { - if(startJob) { - startJob.cancel(); - startJob = undefined; - } - } - } -} - -async function createMarqueeMsg(marquee: MarqueeType) { - let { receivers, content } = marquee; - let msgDatas: GroupMessageType[] = []; - let serverIds: number[] = []; - for(let { env, serverId } of receivers) { - if(serverId == 0) { - let servers = await ServerlistModel.findByEnv(env); - for(let { id } of servers) { - serverIds.push(id); - } - } else { - serverIds.push(serverId); - } - } - for(let serverId of uniq(serverIds)) { - let msgData = await sysCreateMarqueeMsg('', '系统', serverId, content); - msgDatas.push(msgData); - } - - return msgDatas; -} - -async function pushMarqueeMsg(msgDatas: GroupMessageType[]) { - for(let msgData of msgDatas) { - await sysPushMarqueeMsg(msgData); - } -} - -export async function cancelMarquee(code: string) { - let startMarquee = scheduledJobs[`start${code}`]; - let setSecondsMarquee = scheduledJobs[`setSeconds${code}`]; - let endMarquee = scheduledJobs[`end${code}`]; - if(startMarquee) startMarquee.cancel(); - if(setSecondsMarquee) setSecondsMarquee.cancel(); - if(endMarquee) endMarquee.cancel(); - return true -} - -export async function sendOpenServerMail(type: 'openMail'|'circleMail', mail: StategyMail, newServer: ServerlistType, uid: number) { - let addParam = new GMMail(); - addParam.setByRegionStategy(type, mail, newServer, uid); - let gmmail = await GMMailModel.addMail(addParam, uid); - - await sendMailsByGmMail([gmmail]); - return true; -} - -export function setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { - let maintenServers = pinus.app.get('maintenServers')||new Map(); - for(let id of serverIds) { - if(!maintenServers.has(id)) { - maintenServers.set(id, { startTime, endTime, version }); - } else { - maintenServers.get(id).startTime = startTime; - maintenServers.get(id).endTime = endTime; - maintenServers.get(id).version = version; - } - } - pinus.app.set('maintenServers', maintenServers); -} - - -export function stopServerMainten(serverIds: number[]) { - let maintenServers = pinus.app.get('maintenServers')||new Map(); - for(let id of serverIds) { - if(maintenServers.has(id)) { - maintenServers.delete(id); - } - } - pinus.app.set('maintenServers', maintenServers); -} - -export function getServerMainten(serverId: number) { - let maintenServers = pinus.app.get('maintenServers')||new Map(); - return maintenServers.get(serverId); -} - -function getDicRMB(productID: string) { - let dic = dicRMB.get(productID); - if(!dic) return null - return { - value: dic.productID, - label: `${dic.message}(${dic.productID})`, - } -}; - -export function getActivityProducts(activity: ActivityModelType) { - switch(activity.type) { - case ACTIVITY_TYPE.SIGN_IN_VIP: // 高级签到 - { - let data = new SignInData(activity, 0, 0); - return [getDicRMB(data.productID)]; - } - case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: // 新手限定RMB购买礼包 - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: // 日限购 - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: // 周限购 - { - let data = new LimitShopData(activity, 0, 0); - return data.list.map(item => { - return getDicRMB(item.productID); - }); - } - case ACTIVITY_TYPE.YUAN_BAO_SHOP: // 元宝 - { - let data = new YuanBaoShopData(activity, 0, 0); - return data.list.map(item => { - return getDicRMB(item.productID); - }); - } - case ACTIVITY_TYPE.MONTHLY_TICKET_1: - case ACTIVITY_TYPE.MONTHLY_TICKET_2: - { - let data = new MonthlyTicketData(activity, 0, 0); - return [getDicRMB(data.productID)]; - } - case ACTIVITY_TYPE.DAILY_RMB_GIFTS: - { - let data = new DailyRMBGiftsData(activity, 0, 0); - return [getDicRMB(data.productID)]; - } - case ACTIVITY_TYPE.POP_UP_SHOP://弹出礼包 - { - let products: { label: string, value: string }[] = []; - let data = new PopUpShopData(activity); - for(let { items } of data.packages) { - for(let item of items) { - products.push(getDicRMB(item.productID)); - } - } - return products; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) - { - let data = new GrowthFundData(activity, 0, 0); - return data.list.map(item => { - return getDicRMB(item.productID); - }); - } - case ACTIVITY_TYPE.TREASURE_HUNT: - { - let data = new TreasureHuntData(activity, 0, 0); - let shop = data.shop; - return shop.list.map(item => { - return getDicRMB(item.productID); - }); - } - case ACTIVITY_TYPE.REFRESH_SHOP: - { - let data = new RefreshShopData(activity, 0, 0); - let products: { label: string, value: string }[] = []; - for(let shop of data.list) { - for(let item of shop.items) { - products.push(getDicRMB(item.productID)); - } - } - return products; - } - case ACTIVITY_TYPE.TASK_PASS: - { - let data = new TaskPassData(activity, 0, 0); - let products: { label: string, value: string }[] = []; - for(let reward of data.rewards) { - products.push(getDicRMB(reward.productID)); - } - return products; - } - - } - return false -} - -export async function getParamStr(activity: ActivityModelType, productID: string, role: RoleType) { - let param = {}; - switch(activity.type) { - case ACTIVITY_TYPE.POP_UP_SHOP: - const roleId = role.roleId; - let serverId = role.serverId; - let playerData = await getPopUpShopData(activity.activityId, serverId, roleId, role); - let item: PopShopItem, pkg: PopUpShopPackage; - for(let _pkg of playerData.packages) { - let _item = _pkg.findItemByProductID(productID); - if(_item) { - pkg = _pkg; item = _item; - } - } - if(item.isPushing) { - param['code'] = item.code; - } else { - let popUpShopRec = await ActivityPopUpShopModel.createRecord({ - serverId, activityId: activity.activityId, roleId, id: pkg.id, - ...await pkg.getEffectTime(), - items: pkg.items.map(item => new PopUpShopItem(item)) - }); - param['code'] = popUpShopRec.code; - } - - - // let playerRecords = await ActivityPopUpShopModel.findAllOpenData(role.serverId, activity.activityId, role.roleId); - // let playerRecord: ActivityPopUpShopModelType; - // for(let record of playerRecords) { - // let playerData = new PopUpShopData(task, activity.activityId); - // playerData.setPlayerRecords(record); - // if (record && playerData.buyCount < task.count) { - // playerRecord = record; break; - // } - // } - // console.log('####', playerRecord, task) - // if(!playerRecord) { - // let beginTime = new Date(); - // let endTime = moment(new Date()).add(task.duration, 'h').toDate(); - // playerRecord = await ActivityPopUpShopModel.addTaskPushMessage(role.serverId, activity.activityId, role.roleId, task.id, task.taskType, task.condition, beginTime, endTime); - // } - - // param['beginTimeStamp'] = playerRecord.beginTime.getTime(); - break; - case ACTIVITY_TYPE.REFRESH_SHOP: - let monopolyActivitys = await getActivitiesByType(role.serverId, ACTIVITY_TYPE.MONOPOLY); - let parentActivity = monopolyActivitys.find(activity => { - let data = new MonopolyData(activity, 0, 0); - let curShop = data.list.find(land => { // 找到关联活动 - return land.shopActivityId == activity.activityId; - }); - return !!curShop; - }); - - if(parentActivity) { - param['monopolyActivityId'] = parentActivity.activityId; - } - break; - } - return JSON.stringify(param); -} - - -export async function getSurvey(roleId: string, lv: number) { - let surveys = await SurveyModel.findEnableSurvey(lv, SURVEY_SELECT.FIND); - let recs = await SurveyRecModel.findByRole(roleId); - return surveys.filter(survey => { - let index = recs.findIndex(rec => rec.surveyId == survey.surveyId); - return index == -1 - }); -} - -export async function setTrainLv(guildCode: string, trainLv: string) { - let [_lv, _id] = trainLv.split('-'); - let lv = parseInt(_lv), id = parseInt(_id); - if(!isNaN(lv) && !isNaN(id)) { - let structure = gameData.trainBase.get(lv); - let trainIds = structure?.trainIds||[]; - let trainId = trainIds[id - 1]; - if(trainId) { - await GuildModel.updateInfo(guildCode, { trainId, trainLv: lv }); - await GuildTrainModel.resetGuildTrain(guildCode); - await unlockTrain(guildCode, trainId); - } - } -} - -export async function calHiddenData(uid: number) { - let result = await HiddenDataByIdModel.findAllData(); - // console.log('####', JSON.stringify(result)) - let heroes: number[] = [], goods: number[] = []; - await HiddenDataModel.clearData(); - for(let { _id, ids } of result) { - await HiddenDataModel.updateHiddenData(_id, heroes, goods, uid); - for(let {type, id} of ids) { - if(type == 1) heroes.push(id); - if(type == 2) goods.push(id); - } - } - await HiddenDataModel.updateHiddenData(getPastTime(), heroes, goods, uid); -} - -export function compaireMailGoods(gmmail: GMMailType, receiver: Receiver) { - if(gmmail.hasGoods == false && (!receiver.rewards || receiver.rewards.length)) return true; - let tmpGoods = gmmail.goods||[]; - let receiverGoods = receiver.rewards||[]; - - if(tmpGoods.length != receiverGoods.length) return false; - tmpGoods.sort((a, b) => a.id - b.id); - receiverGoods.sort((a, b) => a.id - b.id); - for(let i = 0; i < tmpGoods.length; i++) { - if(!receiverGoods[i]) return false; - if(tmpGoods[i].id != receiverGoods[i].id || tmpGoods[i].count != receiverGoods[i].count) return false; - } - return true -} \ No newline at end of file +import { MarqueeType, MarqueeModel } from "@db/Marquee"; +import { ACTIVITY_TYPE, MARQUEE_SHOW_TYPE, MARQUEE_TIME_TYPE, REDIS_KEY, SURVEY_SELECT } from "@consts"; +import { scheduleJob, scheduledJobs, Job } from 'node-schedule'; +import { createMarqueeMsg as sysCreateMarqueeMsg, pushMarqueeMsg as sysPushMarqueeMsg } from './sysChatService'; +import { GroupMessageType } from "@db/GroupMessage"; +import { pinus } from "pinus"; +import { ServerlistModel, ServerlistType } from "@db/Serverlist"; +import { sendMailsByGmMail } from "./mailService"; +import GMMail, { GMMailModel, GMMailType, Receiver } from '@db/GMMail'; +import { getPastTime, nowSeconds } from "@pubUtils/timeUtil"; +import { CreateServerParam } from "@domain/backEndField/params"; +import { SignInData } from "@domain/activityField/signInField"; +import { RegionModel, RegionType } from "@db/Region"; +import { GMMail as StategyMail } from "@db/ServerStategy"; +import { uniq } from "underscore"; +import { ActivityModel, ActivityModelType } from "@db/Activity"; +import { dicRMB } from "@pubUtils/dictionary/DicRMB"; +import { LimitShopData } from "@domain/activityField/limitShopField"; +import { YuanBaoShopData } from "@domain/activityField/yuanBaoShopField"; +import { MonthlyTicketData } from "@domain/activityField/monthlyTicketField"; +import { DailyRMBGiftsData } from "@domain/activityField/dailyRMBGiftsField"; +import { PopShopItem, PopUpShopData, PopUpShopPackage } from "@domain/activityField/popUpShopField"; +import { GrowthFundData } from "@domain/activityField/growthFundField"; +import { TreasureHuntData } from "@domain/activityField/treasureHuntField"; +import { RefreshShopData } from "@domain/activityField/refreshShopField"; +import { RoleType } from "@db/Role"; +import { MonopolyData } from "@domain/activityField/monopolyField"; +import { ActivityPopUpShopModel, PopUpShopItem } from "@db/ActivityPopUpShop"; +import { getActivitiesByType } from "./activity/activityService"; +import { SurveyModel } from "@db/Survery"; +import { SurveyRecModel } from "@db/SurveyRec"; +import { getPopUpShopData } from "./activity/popUpShopService"; +import { TaskPassData } from "@domain/activityField/taskPassField"; +import { ActivityGroupModel } from "@db/ActivityGroup"; +import { redisClient } from "./redisService"; +import { gameData } from "@pubUtils/data"; +import { GuildModel } from "@db/Guild"; +import { GuildTrainModel } from "@db/GuildTrain"; +import { unlockTrain } from "./guildTrainService"; +import { HiddenDataModel, HiddenDataModelType } from "@db/HiddenData"; +import { HiddenDataByIdModel } from "@db/HiddenDataById"; +import moment = require("moment"); + +// —————————————— 跑马灯 —————————————— // +// 初始 +export async function initMarquee() { + const marquees = await MarqueeModel.findEffectiveMarque(pinus.app.get('env')); + for(let marquee of marquees) { + await generateMarqueeSchedule(marquee); + } +} + +export async function setMarquee(marquee: MarqueeType) { + console.log('******', marquee.timeType, marquee) + if(marquee.timeType == MARQUEE_TIME_TYPE.INSTANT) { + await startMarquee(marquee); + return true; + } else { + return await generateMarqueeSchedule(marquee); + } +} + +async function generateMarqueeSchedule(marquee: MarqueeType) { + // 定时发送 + let setSecondsMarquee = scheduledJobs[`setSeconds${marquee.code}`]; + if(setSecondsMarquee) return false; // 已经在运行中了 + + if(marquee.timeType != MARQUEE_TIME_TYPE.SCHEDULE) return false; + if(marquee.endTime && marquee.endTime < nowSeconds()) return false; + let startJob = scheduleJob(`start${marquee.code}`, marquee.startTime * 1000, async () => { + await startMarquee(marquee, startJob) + }); + return true; +} + +async function startMarquee(marquee: MarqueeType, startJob?: Job) { + console.log('************', `跑马灯定时器 ${marquee.code}开始`, '************'); + let msgDatas = await createMarqueeMsg(marquee); + if(marquee.showType == MARQUEE_SHOW_TYPE.ONCE) { // 一次性发送 + await pushMarqueeMsg(msgDatas); + if(startJob) { + startJob.cancel(); + startJob = undefined; + } + } else { + if(marquee.endTime > nowSeconds()) { + await pushMarqueeMsg(msgDatas); + let secondsJob = scheduleJob(`setSeconds${marquee.code}`, `*/${marquee.interval} * * * * *`, async () => { + console.log(`*****setSeconds${marquee.code}****`) + await pushMarqueeMsg(msgDatas); + }); + let endJob = scheduleJob(`end${marquee.code}`, marquee.endTime * 1000, async () => { + if(startJob) { + startJob.cancel(); + startJob = undefined; + } + if(secondsJob) { + secondsJob.cancel(); + secondsJob = undefined; + } + if(endJob) { + endJob.cancel(); + endJob = undefined; + } + }); + } else { + if(startJob) { + startJob.cancel(); + startJob = undefined; + } + } + } +} + +async function createMarqueeMsg(marquee: MarqueeType) { + let { receivers, content } = marquee; + let msgDatas: GroupMessageType[] = []; + let serverIds: number[] = []; + for(let { env, serverId } of receivers) { + if(serverId == 0) { + let servers = await ServerlistModel.findByEnv(env); + for(let { id } of servers) { + serverIds.push(id); + } + } else { + serverIds.push(serverId); + } + } + for(let serverId of uniq(serverIds)) { + let msgData = await sysCreateMarqueeMsg('', '系统', serverId, content); + msgDatas.push(msgData); + } + + return msgDatas; +} + +async function pushMarqueeMsg(msgDatas: GroupMessageType[]) { + for(let msgData of msgDatas) { + await sysPushMarqueeMsg(msgData); + } +} + +export async function cancelMarquee(code: string) { + let startMarquee = scheduledJobs[`start${code}`]; + let setSecondsMarquee = scheduledJobs[`setSeconds${code}`]; + let endMarquee = scheduledJobs[`end${code}`]; + if(startMarquee) startMarquee.cancel(); + if(setSecondsMarquee) setSecondsMarquee.cancel(); + if(endMarquee) endMarquee.cancel(); + return true +} + +export async function sendOpenServerMail(type: 'openMail'|'circleMail', mail: StategyMail, newServer: ServerlistType, uid: number) { + let addParam = new GMMail(); + addParam.setByRegionStategy(type, mail, newServer, uid); + let gmmail = await GMMailModel.addMail(addParam, uid); + + await sendMailsByGmMail([gmmail]); + return true; +} + +export function setServerMainten(serverIds: number[], startTime: number, endTime: number, version: string) { + let maintenServers = pinus.app.get('maintenServers')||new Map(); + for(let id of serverIds) { + if(!maintenServers.has(id)) { + maintenServers.set(id, { startTime, endTime, version }); + } else { + maintenServers.get(id).startTime = startTime; + maintenServers.get(id).endTime = endTime; + maintenServers.get(id).version = version; + } + } + pinus.app.set('maintenServers', maintenServers); +} + + +export function stopServerMainten(serverIds: number[]) { + let maintenServers = pinus.app.get('maintenServers')||new Map(); + for(let id of serverIds) { + if(maintenServers.has(id)) { + maintenServers.delete(id); + } + } + pinus.app.set('maintenServers', maintenServers); +} + +export function getServerMainten(serverId: number) { + let maintenServers = pinus.app.get('maintenServers')||new Map(); + return maintenServers.get(serverId); +} + +function getDicRMB(productID: string) { + let dic = dicRMB.get(productID); + if(!dic) return null + return { + value: dic.productID, + label: `${dic.message}(${dic.productID})`, + } +}; + +export function getActivityProducts(activity: ActivityModelType) { + switch(activity.type) { + case ACTIVITY_TYPE.SIGN_IN_VIP: // 高级签到 + { + let data = new SignInData(activity, 0, 0); + return [getDicRMB(data.productID)]; + } + case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: // 新手限定RMB购买礼包 + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: // 日限购 + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: // 周限购 + { + let data = new LimitShopData(activity, 0, 0); + return data.list.map(item => { + return getDicRMB(item.productID); + }); + } + case ACTIVITY_TYPE.YUAN_BAO_SHOP: // 元宝 + { + let data = new YuanBaoShopData(activity, 0, 0); + return data.list.map(item => { + return getDicRMB(item.productID); + }); + } + case ACTIVITY_TYPE.MONTHLY_TICKET_1: + case ACTIVITY_TYPE.MONTHLY_TICKET_2: + { + let data = new MonthlyTicketData(activity, 0, 0); + return [getDicRMB(data.productID)]; + } + case ACTIVITY_TYPE.DAILY_RMB_GIFTS: + { + let data = new DailyRMBGiftsData(activity, 0, 0); + return [getDicRMB(data.productID)]; + } + case ACTIVITY_TYPE.POP_UP_SHOP://弹出礼包 + { + let products: { label: string, value: string }[] = []; + let data = new PopUpShopData(activity); + for(let { items } of data.packages) { + for(let item of items) { + products.push(getDicRMB(item.productID)); + } + } + return products; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) + { + let data = new GrowthFundData(activity, 0, 0); + return data.list.map(item => { + return getDicRMB(item.productID); + }); + } + case ACTIVITY_TYPE.TREASURE_HUNT: + { + let data = new TreasureHuntData(activity, 0, 0); + let shop = data.shop; + return shop.list.map(item => { + return getDicRMB(item.productID); + }); + } + case ACTIVITY_TYPE.REFRESH_SHOP: + { + let data = new RefreshShopData(activity, 0, 0); + let products: { label: string, value: string }[] = []; + for(let shop of data.list) { + for(let item of shop.items) { + products.push(getDicRMB(item.productID)); + } + } + return products; + } + case ACTIVITY_TYPE.TASK_PASS: + { + let data = new TaskPassData(activity, 0, 0); + let products: { label: string, value: string }[] = []; + for(let reward of data.rewards) { + products.push(getDicRMB(reward.productID)); + } + return products; + } + + } + return false +} + +export async function getParamStr(activity: ActivityModelType, productID: string, role: RoleType) { + let param = {}; + switch(activity.type) { + case ACTIVITY_TYPE.POP_UP_SHOP: + const roleId = role.roleId; + let serverId = role.serverId; + let playerData = await getPopUpShopData(activity.activityId, serverId, roleId, role); + let item: PopShopItem, pkg: PopUpShopPackage; + for(let _pkg of playerData.packages) { + let _item = _pkg.findItemByProductID(productID); + if(_item) { + pkg = _pkg; item = _item; + } + } + if(item.isPushing) { + param['code'] = item.code; + } else { + let popUpShopRec = await ActivityPopUpShopModel.createRecord({ + serverId, activityId: activity.activityId, roleId, id: pkg.id, + ...await pkg.getEffectTime(), + items: pkg.items.map(item => new PopUpShopItem(item)) + }); + param['code'] = popUpShopRec.code; + } + + + // let playerRecords = await ActivityPopUpShopModel.findAllOpenData(role.serverId, activity.activityId, role.roleId); + // let playerRecord: ActivityPopUpShopModelType; + // for(let record of playerRecords) { + // let playerData = new PopUpShopData(task, activity.activityId); + // playerData.setPlayerRecords(record); + // if (record && playerData.buyCount < task.count) { + // playerRecord = record; break; + // } + // } + // console.log('####', playerRecord, task) + // if(!playerRecord) { + // let beginTime = new Date(); + // let endTime = moment(new Date()).add(task.duration, 'h').toDate(); + // playerRecord = await ActivityPopUpShopModel.addTaskPushMessage(role.serverId, activity.activityId, role.roleId, task.id, task.taskType, task.condition, beginTime, endTime); + // } + + // param['beginTimeStamp'] = playerRecord.beginTime.getTime(); + break; + case ACTIVITY_TYPE.REFRESH_SHOP: + let monopolyActivitys = await getActivitiesByType(role.serverId, ACTIVITY_TYPE.MONOPOLY); + let parentActivity = monopolyActivitys.find(activity => { + let data = new MonopolyData(activity, 0, 0); + let curShop = data.list.find(land => { // 找到关联活动 + return land.shopActivityId == activity.activityId; + }); + return !!curShop; + }); + + if(parentActivity) { + param['monopolyActivityId'] = parentActivity.activityId; + } + break; + } + return JSON.stringify(param); +} + + +export async function getSurvey(roleId: string, lv: number) { + let surveys = await SurveyModel.findEnableSurvey(lv, SURVEY_SELECT.FIND); + let recs = await SurveyRecModel.findByRole(roleId); + return surveys.filter(survey => { + let index = recs.findIndex(rec => rec.surveyId == survey.surveyId); + return index == -1 + }); +} + +export async function setTrainLv(guildCode: string, trainLv: string) { + let [_lv, _id] = trainLv.split('-'); + let lv = parseInt(_lv), id = parseInt(_id); + if(!isNaN(lv) && !isNaN(id)) { + let structure = gameData.trainBase.get(lv); + let trainIds = structure?.trainIds||[]; + let trainId = trainIds[id - 1]; + if(trainId) { + await GuildModel.updateInfo(guildCode, { trainId, trainLv: lv }); + await GuildTrainModel.resetGuildTrain(guildCode); + await unlockTrain(guildCode, trainId); + } + } +} + +export async function calHiddenData(uid: number) { + let result = await HiddenDataByIdModel.findAllData(); + // console.log('####', JSON.stringify(result)) + let heroes: number[] = [], goods: number[] = []; + await HiddenDataModel.clearData(); + for(let { _id, ids } of result) { + await HiddenDataModel.updateHiddenData(_id, heroes, goods, uid); + for(let {type, id} of ids) { + if(type == 1) heroes.push(id); + if(type == 2) goods.push(id); + } + } + await HiddenDataModel.updateHiddenData(getPastTime(), heroes, goods, uid); +} + +export function compaireMailGoods(gmmail: GMMailType, receiver: Receiver) { + if(gmmail.hasGoods == false && (!receiver.rewards || receiver.rewards.length)) return true; + let tmpGoods = gmmail.goods||[]; + let receiverGoods = receiver.rewards||[]; + + if(tmpGoods.length != receiverGoods.length) return false; + tmpGoods.sort((a, b) => a.id - b.id); + receiverGoods.sort((a, b) => a.id - b.id); + for(let i = 0; i < tmpGoods.length; i++) { + if(!receiverGoods[i]) return false; + if(tmpGoods[i].id != receiverGoods[i].id || tmpGoods[i].count != receiverGoods[i].count) return false; + } + return true +} diff --git a/game-server/app/services/guildActivity/cityActivityObj.ts b/game-server/app/services/guildActivity/cityActivityObj.ts index 6244d79d6..afbea7e4b 100644 --- a/game-server/app/services/guildActivity/cityActivityObj.ts +++ b/game-server/app/services/guildActivity/cityActivityObj.ts @@ -1,144 +1,144 @@ -// 军团活动蛮夷入侵城门血量等数据存储 - -import { GUILD_ACTIVITY_STATUS } from "../../consts"; -import { CityActivityData } from "../../domain/battleField/guildActivity"; -import { getCityActivityGateHp } from "./guildActivityService"; - -// 军团诸侯混战等数据 -export class CityActivityObject { - data: CityActivityData = new CityActivityData(); - - - public getKey(serverId: number, cityId: number) { - return `${serverId}_${cityId}`; - } - - public decodeKey(key: string) { - let arr = key.split('_'); - return { - serverId: parseInt(arr[0]), - cityId: parseInt(arr[1]) - } - } - - public getObj( serverId: number, cityId: number, guildCode: string) { - let key = this.getKey(serverId, cityId); - return { - gateHp: this.data.gateHp.get(key), - maxHp: this.data.maxHp.get(key), - members: this.data.members.get(guildCode), - city: this.data.cities.get(key), - guild: this.data.guilds.get(guildCode) - } - } - - public startActivity() { - this.data.startTime = Date.now(); - this.data.guildActivityStatus = GUILD_ACTIVITY_STATUS.START; - } - - public endActivity() { - this.data.guildActivityStatus = GUILD_ACTIVITY_STATUS.END; - } - - public getStatus() { - return this.data.guildActivityStatus; - } - - public getTimeGap() { - return Math.floor((Date.now() - this.data.startTime)/1000); - } - - public lockCity(serverId: number, cityId: number) { - if(this.hasSent(serverId, cityId)) return false; - this.unlockCity(serverId, cityId); - return true; - } - - private unlockCity(serverId: number, cityId: number) { - let key = this.getKey(serverId, cityId); - // let guildCodes = this.cities.get(key)||[]; - // for(let guildCode of guildCodes) { - // this.members.delete(guildCode); - // this.guilds.delete(guildCode); - // } - // this.cities.delete(key); - this.data.sentCity.push(key); - } - - public hasSent(serverId: number, cityId: number) { - let key = this.getKey(serverId, cityId); - return this.data.sentCity.indexOf(key) != -1; - } - - public getAllCities() { - let allCities = new Array<{ serverId: number, cityId: number, guildCodes: string[]}>(); - let serverlists = new Array(); - for(let [key, guildCodes] of this.data.cities) { - let { serverId, cityId } = this.decodeKey(key); - if(!this.hasSent(serverId, cityId)) { - allCities.push({ serverId, cityId, guildCodes }); - if(!serverlists.includes(serverId)) serverlists.push(serverId); - } - } - return {cities: allCities, serverlists}; - } - - public getGuildsInCity(serverId: number, cityId: number) { - let key = this.getKey(serverId, cityId); - return this.data.cities.get(key)||[]; - } - - public getMembersOfGuild(guildCode: string) { - return this.data.members.get(guildCode)||[]; - } - - public async getGateHpAndInc(serverId: number, cityId: number, inc: number = 0) { - let key = this.getKey(serverId, cityId); - let gateHp = this.data.gateHp.get(key); - if(!this.data.gateHp.has(key)) { - gateHp = await getCityActivityGateHp(serverId, cityId); - this.data.gateHp.set(key, gateHp); - this.data.maxHp.set(key, gateHp); - } - if(inc != 0) { - gateHp += inc; - this.data.gateHp.set(key, gateHp); - } - if(gateHp <= 0) gateHp = 0; - return { gateHp, maxHp: this.data.maxHp.get(key)||0 } - } - - public pushMembers(guildCode: string, roleId: string, job: number, code: string) { - - if(this.data.members.has(guildCode)) { - let members = this.data.members.get(guildCode); - if(members.findIndex(cur => cur.roleId == roleId) == -1) { - members.push({ roleId, job, code, startActionTime: 0 }); - } - } else { - let arr = new Array(); - arr.push(roleId); - this.data.members.set(guildCode, [{ roleId, job, code, startActionTime: 0 }]); - } - } - - public getMember(guildCode: string, roleId: string) { - let members = this.data.members.get(guildCode)||[]; - let member = members.find(cur => cur.roleId == roleId); - return member; - } - - public pushGuild(guildCode: string, serverId: number, cityId: number) { - let key = this.getKey(serverId, cityId); - if(!this.data.cities.has(key)) { - this.data.cities.set(key, [guildCode]); - } else { - let arr = this.data.cities.get(key); - if(!arr.includes(guildCode)) { - arr.push(guildCode); - } - } - this.data.guilds.set(guildCode, cityId); - } -} \ No newline at end of file +// 军团活动蛮夷入侵城门血量等数据存储 + +import { GUILD_ACTIVITY_STATUS } from "@consts"; +import { CityActivityData } from "@domain/battleField/guildActivity"; +import { getCityActivityGateHp } from "./guildActivityService"; + +// 军团诸侯混战等数据 +export class CityActivityObject { + data: CityActivityData = new CityActivityData(); + + + public getKey(serverId: number, cityId: number) { + return `${serverId}_${cityId}`; + } + + public decodeKey(key: string) { + let arr = key.split('_'); + return { + serverId: parseInt(arr[0]), + cityId: parseInt(arr[1]) + } + } + + public getObj( serverId: number, cityId: number, guildCode: string) { + let key = this.getKey(serverId, cityId); + return { + gateHp: this.data.gateHp.get(key), + maxHp: this.data.maxHp.get(key), + members: this.data.members.get(guildCode), + city: this.data.cities.get(key), + guild: this.data.guilds.get(guildCode) + } + } + + public startActivity() { + this.data.startTime = Date.now(); + this.data.guildActivityStatus = GUILD_ACTIVITY_STATUS.START; + } + + public endActivity() { + this.data.guildActivityStatus = GUILD_ACTIVITY_STATUS.END; + } + + public getStatus() { + return this.data.guildActivityStatus; + } + + public getTimeGap() { + return Math.floor((Date.now() - this.data.startTime)/1000); + } + + public lockCity(serverId: number, cityId: number) { + if(this.hasSent(serverId, cityId)) return false; + this.unlockCity(serverId, cityId); + return true; + } + + private unlockCity(serverId: number, cityId: number) { + let key = this.getKey(serverId, cityId); + // let guildCodes = this.cities.get(key)||[]; + // for(let guildCode of guildCodes) { + // this.members.delete(guildCode); + // this.guilds.delete(guildCode); + // } + // this.cities.delete(key); + this.data.sentCity.push(key); + } + + public hasSent(serverId: number, cityId: number) { + let key = this.getKey(serverId, cityId); + return this.data.sentCity.indexOf(key) != -1; + } + + public getAllCities() { + let allCities = new Array<{ serverId: number, cityId: number, guildCodes: string[]}>(); + let serverlists = new Array(); + for(let [key, guildCodes] of this.data.cities) { + let { serverId, cityId } = this.decodeKey(key); + if(!this.hasSent(serverId, cityId)) { + allCities.push({ serverId, cityId, guildCodes }); + if(!serverlists.includes(serverId)) serverlists.push(serverId); + } + } + return {cities: allCities, serverlists}; + } + + public getGuildsInCity(serverId: number, cityId: number) { + let key = this.getKey(serverId, cityId); + return this.data.cities.get(key)||[]; + } + + public getMembersOfGuild(guildCode: string) { + return this.data.members.get(guildCode)||[]; + } + + public async getGateHpAndInc(serverId: number, cityId: number, inc: number = 0) { + let key = this.getKey(serverId, cityId); + let gateHp = this.data.gateHp.get(key); + if(!this.data.gateHp.has(key)) { + gateHp = await getCityActivityGateHp(serverId, cityId); + this.data.gateHp.set(key, gateHp); + this.data.maxHp.set(key, gateHp); + } + if(inc != 0) { + gateHp += inc; + this.data.gateHp.set(key, gateHp); + } + if(gateHp <= 0) gateHp = 0; + return { gateHp, maxHp: this.data.maxHp.get(key)||0 } + } + + public pushMembers(guildCode: string, roleId: string, job: number, code: string) { + + if(this.data.members.has(guildCode)) { + let members = this.data.members.get(guildCode); + if(members.findIndex(cur => cur.roleId == roleId) == -1) { + members.push({ roleId, job, code, startActionTime: 0 }); + } + } else { + let arr = new Array(); + arr.push(roleId); + this.data.members.set(guildCode, [{ roleId, job, code, startActionTime: 0 }]); + } + } + + public getMember(guildCode: string, roleId: string) { + let members = this.data.members.get(guildCode)||[]; + let member = members.find(cur => cur.roleId == roleId); + return member; + } + + public pushGuild(guildCode: string, serverId: number, cityId: number) { + let key = this.getKey(serverId, cityId); + if(!this.data.cities.has(key)) { + this.data.cities.set(key, [guildCode]); + } else { + let arr = this.data.cities.get(key); + if(!arr.includes(guildCode)) { + arr.push(guildCode); + } + } + this.data.guilds.set(guildCode, cityId); + } +} diff --git a/game-server/app/services/guildActivity/gateActivityObj.ts b/game-server/app/services/guildActivity/gateActivityObj.ts index 8b787f5ed..dc1fdfafc 100644 --- a/game-server/app/services/guildActivity/gateActivityObj.ts +++ b/game-server/app/services/guildActivity/gateActivityObj.ts @@ -1,72 +1,72 @@ - -// 军团活动蛮夷入侵城门血量等数据存储 - -import { Member, GateMembersRec, GateActivityData } from "../../domain/battleField/guildActivity"; - -export class GateActivityObject { - data: GateActivityData = new GateActivityData(); - - public getObj(guildCode: string, serverId: number) { - // console.log(guildCode, serverId) - return { - members: this.data.members.get(guildCode)||[], - memberesRecord: [...this.data.membersRecord], - guilds: this.data.guilds.get(serverId)||[] - } - } - - public startActivity() { - this.data.startTime = Date.now(); - } - - public getTimeGap() { - return Math.floor((Date.now() - this.data.startTime)/1000); - } - - public getGuilds() { - return this.data.guilds; - } - - public pushMembers(guildCode: string, serverId: number, roleId: string, job: number, code: string) { - let member: Member; - if(this.data.members.has(guildCode)) { - let members = this.data.members.get(guildCode); - if(members.findIndex(cur => cur.roleId == roleId) == -1) { - member = { roleId, job, code } - members.push(member); - } - } else { - member = { roleId, job, code } - this.data.members.set(guildCode, [member]); - } - if(this.data.guilds.has(serverId)) { - let arr = this.data.guilds.get(serverId); - if(!arr.includes(guildCode)) arr.push(guildCode); - this.data.guilds.set(serverId, arr); - } else { - this.data.guilds.set(serverId, [guildCode]); - } - return member; - } - - public getMemberRecord(recCode: string, roleId: string) { - return this.data.membersRecord.get(recCode)||new GateMembersRec(roleId) - } - - public setMemberRecord(recCode: string, newMemberRecord: GateMembersRec) { - this.data.membersRecord.set(recCode, newMemberRecord); - } - - public delMemberRecord(recCode: string) { - this.data.membersRecord.delete(recCode); - } - - public delGuildRecord(guildCode: string, serverId: number) { - let guildList = this.data.guilds.get(serverId); - if(guildList) { - let index = guildList.indexOf(guildCode); - guildList.splice(index, 1); - } - this.data.members.delete(guildCode); - } -} \ No newline at end of file + +// 军团活动蛮夷入侵城门血量等数据存储 + +import { Member, GateMembersRec, GateActivityData } from "@domain/battleField/guildActivity"; + +export class GateActivityObject { + data: GateActivityData = new GateActivityData(); + + public getObj(guildCode: string, serverId: number) { + // console.log(guildCode, serverId) + return { + members: this.data.members.get(guildCode)||[], + memberesRecord: [...this.data.membersRecord], + guilds: this.data.guilds.get(serverId)||[] + } + } + + public startActivity() { + this.data.startTime = Date.now(); + } + + public getTimeGap() { + return Math.floor((Date.now() - this.data.startTime)/1000); + } + + public getGuilds() { + return this.data.guilds; + } + + public pushMembers(guildCode: string, serverId: number, roleId: string, job: number, code: string) { + let member: Member; + if(this.data.members.has(guildCode)) { + let members = this.data.members.get(guildCode); + if(members.findIndex(cur => cur.roleId == roleId) == -1) { + member = { roleId, job, code } + members.push(member); + } + } else { + member = { roleId, job, code } + this.data.members.set(guildCode, [member]); + } + if(this.data.guilds.has(serverId)) { + let arr = this.data.guilds.get(serverId); + if(!arr.includes(guildCode)) arr.push(guildCode); + this.data.guilds.set(serverId, arr); + } else { + this.data.guilds.set(serverId, [guildCode]); + } + return member; + } + + public getMemberRecord(recCode: string, roleId: string) { + return this.data.membersRecord.get(recCode)||new GateMembersRec(roleId) + } + + public setMemberRecord(recCode: string, newMemberRecord: GateMembersRec) { + this.data.membersRecord.set(recCode, newMemberRecord); + } + + public delMemberRecord(recCode: string) { + this.data.membersRecord.delete(recCode); + } + + public delGuildRecord(guildCode: string, serverId: number) { + let guildList = this.data.guilds.get(serverId); + if(guildList) { + let index = guildList.indexOf(guildCode); + guildList.splice(index, 1); + } + this.data.members.delete(guildCode); + } +} diff --git a/game-server/app/services/guildActivity/guildActivityService.ts b/game-server/app/services/guildActivity/guildActivityService.ts index 9b77b0a6d..0eff04174 100644 --- a/game-server/app/services/guildActivity/guildActivityService.ts +++ b/game-server/app/services/guildActivity/guildActivityService.ts @@ -1,1032 +1,1032 @@ -import { ServerlistModel, ServerlistType } from "../../db/Serverlist"; -import { RoleModel } from "../../db/Role"; -import { GUILDACTIVITY } from "../../pubUtils/dicParam"; -import { gameData, getBossHpRatio, getCityActivityRewards } from "../../pubUtils/data"; -import { getCurDay, nowSeconds, getTimeFun, getZeroPoint, getZeroPointOfTime } from "../../pubUtils/timeUtil"; -import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE, CITY_STATUS, DEBUG_MAGIC_WORD, GUILD_POINT_WAYS, TASK_TYPE, AUCTION_TIME, CITY_ACTIVITY_DOOR, ABI_TYPE, PUSH_ROUTE, RACE_ACTIVITY_STATUS, SHOP_REFRESH_TYPE, COUNTER, RACE_EVENT_TYPE, BOSS_HP_RATIO_TYPE } from "../../consts"; -import { Record, UserGuildActivityRecModel } from "../../db/UserGuildActivityRec"; -import { GateMembersRec, CityParam, WoodenHorse, RaceActivityRankParam } from "../../domain/battleField/guildActivity"; -import { DicGuildActivity } from "../../pubUtils/dictionary/DicGuildActivity"; -import { getAllServers, getRoleOnlineInfo, getServerCreateTime, redisClient } from "../redisService"; -import { SimpleGuildRankParam, SimpleRoleRankParam, GuildRankInfo, RoleRankInfo } from "../../domain/rank"; -import { pinus } from "pinus"; -import { GuildActivityRecordModel } from "../../db/GuildActivityRec"; -import { genAuction, getGuildAuctionBasicNum, getGuildAuctionRewards, getRewardToDbFromMap, guildAuctionPreview } from "../auctionService"; -import { sendMailByContent } from "../mailService"; -import { GuildActivityCityType, GuildActivityCityModel } from "../../db/GuildActivityCity"; -import { DicCityActivity } from "../../pubUtils/dictionary/DicCityActivity"; -import { Rank } from "../rankService"; -import { BossInstanceModel } from "../../db/BossInstance"; -import { UserGuildModel } from "../../db/UserGuild"; -import { addActive } from "../guildService"; -import { ActivePlayer, GuildRecord, ServerRecordModel } from "../../db/ServerRecords"; -import { getHonourObject } from "../role/rewardService"; -import { sendMessageToCityWithSuc, sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToUserWithSuc } from "../pushService"; -import { saveGuildGateHpLog } from "../../pubUtils/logUtil"; -import { GuildActivityCityDeclareModel } from "../../db/GuildActivityCityDeclare"; -import { getRandSingleEelm } from "../../pubUtils/util"; -import { CounterModel } from "../../db/Counter"; -import { setInterval } from "timers"; -import { dispatch } from "../../pubUtils/dispatcher"; -import { GuildModel } from "../../db/Guild"; -import { getCityActivityObj, getGateActivityObj, getRaceActivityObj } from "../memoryCache/guildActivityData"; -import { getBossHpRatioByServer } from "../guildBossService"; -import { getHeroesAttributes } from "../playerCeService"; - - -/** - * 定时任务,获得前一天的活跃玩家中位数武将战力 - */ -export async function setPreDayActiveData(servers: ServerlistType[]) { - - for (let server of servers) { - let roles = await RoleModel.getActivePlayers(server.id); - let activePlayerCnt = roles.length; - let activePlayerCe = 0, activePlayers: ActivePlayer[] = []; - let activeGuilds: GuildRecord[] = []; - - for(let i = 0; i < roles.length; i++) { - let role = roles[i]; - let activePlayer = new ActivePlayer(role); - if(i < 10) { - activePlayerCe += role.topLineupCe; - activePlayers.push(activePlayer); - } - if(role.hasGuild) { - let guildRecord = activeGuilds.find(cur => cur.guildCode == role.guildCode); - if(!guildRecord) { - activeGuilds.push({ guildCode: role.guildCode, players: [activePlayer] }); - } else { - guildRecord.players.push(activePlayer); - } - } - } - - await ServerRecordModel.updateData(server.id, { activePlayerCnt, activePlayerCe, activePlayers, activeGuilds }); - } - return servers; -} - -/** - * 根据当前时间判断军团活动倒计时 - * @param id 军团活动id - */ -export function getGuildActivityStatus(id: number) { - let dicGuildActivity = gameData.guildActivity.get(id); - if (!dicGuildActivity) return false; - return getGuildActivityByDic(dicGuildActivity); -} - -export async function getAllGuildActivityStatus(guildCode: string, serverId: number) { - let guildActivities: { aid: number, status: number, time: number, isOpen: boolean, isCompleted?: boolean }[] = []; - for(let [ aid, dicGuildActivity ] of gameData.guildActivity) { - let index = getGAIndexInPinus(aid); - let res = getGuildActivityByDic(dicGuildActivity); - let isCompleted = res.isOpen; - if(res.status == GUILD_ACTIVITY_STATUS.START && guildCode) { - let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, aid, index); - if(guildActivityRec) isCompleted = guildActivityRec.isCompleted; - } - guildActivities.push({aid, ...res, isCompleted}); - } - return guildActivities; -} - -export function getGuildActivityByDic(dicGuildActivity: DicGuildActivity) { - let t = getTimeFun(); - // console.log('*********', dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds) - let startTime = t.getTimeWithHour(dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds); - let countdownTime = t.getTimeWithHour(dicGuildActivity.countDown); - let { duringTime, openDay } = dicGuildActivity; - let endTime = startTime + duringTime; - - let status = 0, time = 0; - let now = nowSeconds(); - if (now >= countdownTime && now < startTime) { - status = GUILD_ACTIVITY_STATUS.WAITING; - time = startTime - now; - } else if (now >= startTime && now < endTime) { - status = GUILD_ACTIVITY_STATUS.START; - time = endTime - now; - } else { - status = GUILD_ACTIVITY_STATUS.END; - } - - let day = getCurDay(); - let isOpen = openDay.includes(day); - - return { - status, time, isOpen - } -} - -/** - * 根据每回合上报数据判断军功 - * @param aid - * @param record - * @param memberRecord - */ -export function getRecordScore(aid: number, round: number, record: { round: number, dataId: number }[], memberRecord: GateMembersRec) { - let dicGuildActivity = gameData.guildActivity.get(aid); - if (!dicGuildActivity) return false; - - let dicWarJson = gameData.warJson.get(dicGuildActivity.warid); - if (!dicWarJson) return false; - - let { round: curRound, enemies: historyEnemies } = memberRecord; - let sum = 0, newRecords = new Array(); - for (let { round, dataId } of record) { - if (!historyEnemies.includes(dataId)) { - - let enemy = dicWarJson.find(cur => cur.dataId == dataId); - let enemyType = enemy.enemyType; - let score = gameData.gateActivityPoint.get(enemyType); - newRecords.push({ round, dataId, score, enemyType }); - sum += score; - - historyEnemies.push(dataId); - } - } - - for (let i = curRound + 1; i <= round; i++) { - sum += gameData.gateActivityPoint.get(GET_POINT_WAYS.ROUND_START); - memberRecord.round = i; - } - - return { score: sum, newRecords, memberRecord } -} - -export async function getGateActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { - - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); - r.setGenerFieldsFun(generGuildActivityRankField); - let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); - if (!myGuildRank) { - myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); - } - - let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); - myR.setGenerFieldsFun(generGuildActivityMemberRankField); - let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId }); - if (roleName && !myMemberRank) { - myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0); - } - - return { guildRank, myGuildRank, memberRank, myMemberRank } -} - -export async function getCityActivityRank(guildCode: string, serverId: number, cityId: number, roleId?: string, roleName?: string) { - - if(!cityId) { - return { guildRank: [], myGuildRank: undefined, memberRank: [], myMemberRank: undefined } - } - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); - r.setGenerFieldsFun(generGuildActivityRankField); - let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); - if (!myGuildRank) { - myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); - } - - let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); - myR.setGenerFieldsFun(generGuildActivityMemberRankField); - let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId }); - if (roleName && !myMemberRank) { - myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0); - } - - return { guildRank, myGuildRank, memberRank, myMemberRank } -} -/** - * 获取和自己同屏的5个木牛流马 - * @param guildCode - * @param serverId - */ -export async function getWoodenHorseList(guildCode: string, serverId: number) { - let obj = getRaceActivityObj(); - let { myGuildRank, guildRank } = await obj.getRanks(serverId, guildCode); - - let myRank = myGuildRank?.rank||0; - let startRank = myRank - 2 > 0 ? myRank - 2 : 1; - let endRank = startRank + 4; - let woodenHorseList = new Array(); - for (let { rank, code } of guildRank) { - if(rank >= startRank && rank <= endRank) { - let woodenHorse = await obj.getWoodenHorse(code, serverId); - if (woodenHorse) { - woodenHorseList.push(woodenHorse); - } - } - } - return woodenHorseList; -} - -function generGuildActivityRankField(param: GuildRankInfo) { - let { rank, code, name, num } = param; - return new SimpleGuildRankParam(rank, code, name, num); -} - -function generGuildActivityMemberRankField(param: RoleRankInfo) { - let { rank, roleId, roleName, num } = param; - return new SimpleRoleRankParam(rank, roleId, roleName, num); -} - -/** - * 对这个guild服内所有军团发排行榜信息 - * @param aid 活动类型 - */ -export async function sendAllGuildRanks(aid: number) { - if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - let obj = getGateActivityObj(); - let guilds = obj.getGuilds(); - for (let [serverId, guildCodes] of guilds) { - for (let guildCode of guildCodes) { - let ranks = await getGateActivityRank(guildCode, serverId); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GATE_ACT_RANK, ranks); - } - } - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - let obj = getCityActivityObj(); - let { cities } = obj.getAllCities(); - // console.log(JSON.stringify(cities)); - for (let { serverId, cityId, guildCodes } of cities) { - for (let guildCode of guildCodes) { - let ranks = await getCityActivityRank(guildCode, serverId, cityId); - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.CITY_ACT_RANK, ranks); - } - } - } -} - -export async function sendCityGuildRankToUser(serverId: number, cityId: number, guildCode: string, roleId: string) { - let ranks = await getCityActivityRank(guildCode, serverId, cityId); - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.CITY_ACT_RANK, ranks); -} - -/** - * 活动结算奖励 - * @param aid 活动类型 - */ -export async function settleGuildActivityReward(aid: number) { - - if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - let obj = getGateActivityObj(); - let guilds = obj.getGuilds(); - for (let [serverId, guildCodes] of guilds) { - // console.log('***** serverId', serverId, 'guildCodes', guildCodes); - for (let guildCode of guildCodes) { - await gateActivitySettleReward(guildCode, serverId); - } - } - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - let obj = getCityActivityObj(); - obj.endActivity(); - let { cities } = obj.getAllCities(); - for (let { serverId, cityId } of cities) { - await cityActivitySettleReward(cityId, serverId); - } - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - let obj = getRaceActivityObj(); - obj.stopRace(); - - for (let { guildCode, serverId } of obj.getGuilds()) { - let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); - if (woodenHorse && woodenHorse.distance > 0 && !obj.hasSend(guildCode)) { - await raceActivitySettleReward(guildCode, woodenHorse); - } - } - } -} - -// 全服发送结束新号 -export async function sendEndMsgToAllServer() { - let serverlist = await getAllServers(); - for (let serverId of serverlist) { - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); - await sendGuildActivityStatus(serverId); - } -} - -export async function sendGuildActivityStatus(serverId: number) { - let guildActivities: { aid: number, status: number, time: number, isOpen: boolean }[] = []; - gameData.guildActivity.forEach((dicGuildActivity, aid) => { - let res = getGuildActivityByDic(dicGuildActivity); - guildActivities.push({aid ,...res}); - }); - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_STATUS, { guildActivities }); -} - - -/** - * 单个城池城门血条破了之后给他发奖励 - * @param guildCode 军团code - */ -export async function sendSingleCityActEndMsg(cityId: number, serverId: number) { - let obj = getCityActivityObj(); - let guildCodes = obj.getGuildsInCity(serverId, cityId); - for (let guildCode of guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); - } - await cityActivitySettleReward(cityId, serverId); -} - - -/** - * 单个军团抵达赛道之后给他发奖励 - * @param guildCode 军团code - */ -export async function sendSingleRaceActEndMsg(guildCode: string, woodenHorse: WoodenHorse) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); - await raceActivitySettleReward(guildCode, woodenHorse); -} - - -/** - * 结算蛮夷入侵奖励 - * @param guildCode 军团code - * @param serverId 服务器id - */ -export async function gateActivitySettleReward(guildCode: string, serverId: number) { - console.log('gateActivitySettleReward', guildCode, serverId); - let obj = getGateActivityObj(); - let { members } = obj.getObj(guildCode, serverId); - // console.log('***** gateHp', gateHp, 'members', members); - - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); - let rank = await r.getMyRank({ guildCode }); - let guildScore = await r.getMyScore({ guildCode }); - // console.log('****** ranks', rank, 'guildScore', guildScore); - - let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); - let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank, guild?.lv); - // console.log('***** rewards', JSON.stringify(rewards)); - - members = members.filter(member => { - return guild.members?.find(roleId => roleId == member.roleId); - }); - let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, index, { - isSuccess: true, - isCompleted: true, - rank, score: guildScore, - members, memberCnt: members.length, - auctionType: AUCTION_SOURCE.GATE, - rewards: getRewardToDbFromMap(rewards) - }); - // 结算功勋等奖励 - let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - - let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); - - let hasSentMember: string[] = []; - let ranks = await myR.getRankByRange(); - for (let { rank, roleId, num: myScore } of ranks) { - if(hasSentMember.indexOf(roleId) == -1) { - let honour = dic.honour + myScore * GUILDACTIVITY.GATEACTIVITY_HONOUR_RATIO; - await updateUserRecAndSendHonour(honour, myScore, rank, roleId); - hasSentMember.push(roleId); - } - } - for (let { roleId } of members) { - // 只参加了,没有分数的人 - if(hasSentMember.indexOf(roleId) == -1) { - await updateUserRecAndSendHonour(dic.honour, 0, 0, roleId); - hasSentMember.push(roleId); - } - // 发放活跃 - await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 - } - - // 加入拍卖行 - await genAuction(guildCode, AUCTION_SOURCE.GATE, rec.code, serverId, rewards); - - // obj.delGuildRecord(guildCode, serverId); -} - -async function updateUserRecAndSendHonour(honour: number, myScore: number, rank: number, roleId: string) { - let honourObj = getHonourObject(Math.floor(honour)); - await sendMailByContent(MAIL_TYPE.GUILD_ACTIVITY_REWARD, roleId, { goods: [honourObj] }) - - await UserGuildActivityRecModel.updateInfoByRoleId(roleId, { score: myScore, rank }); -} - - -/** - * 结算诸侯入侵奖励 - * @param cityId 城镇id - * @param serverId 服务器id - */ -export async function cityActivitySettleReward(cityId: number, serverId: number) { - console.log('###### cityActivitySettleReward 0') - let obj = getCityActivityObj(); - if(!obj.lockCity(serverId, cityId)) return; - - let dicCity = gameData.cityActivity.get(cityId); - if (!dicCity) return; - let {gateHp} = await obj.getGateHpAndInc(serverId, cityId); - let isSuccess = gateHp <= 0; // 血条未击破则没有占领军团 - - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); - let ranks = await r.getRankByRange(); - console.log('###### cityActivitySettleReward 1', JSON.stringify(ranks)); - for (let { rank: guildRank, code: guildCode, name, num } of ranks) { - if (guildRank == 1) { - if (isSuccess) { - await GuildActivityCityModel.guard(serverId, cityId, guildCode, name, index + 1); // 占领 - if(getCurDay(true) != 6) { - await declareCity(serverId, "", guildCode, dicCity.nextCity, true, index + 1); - } - } else { - await GuildActivityCityModel.guard(serverId, cityId, "", "", index + 1); // 无人能占领 - } - } - let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); - let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, guildRank, guild?.lv, cityId); - let members = obj.getMembersOfGuild(guildCode); - members = members.filter(member => { - return guild.members?.find(roleId => roleId == member.roleId); - }); - let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, index, { - members, memberCnt: members.length, - isSuccess, isCompleted: true, - rank: guildRank, damage: num, remainGateHp: gateHp, - rewards: getRewardToDbFromMap(rewards), - auctionType: AUCTION_SOURCE.CITY, - }, cityId); - - // 奖励加入拍卖行 - await genAuction(guildCode, AUCTION_SOURCE.CITY, rec.code, serverId, rewards); - - let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); - let ranks = await myR.getRankByRange(); - let userRank = 0; - let hasSentMember: string[] = []; - for (let { rank, roleId, num: myScore } of ranks) { - if(hasSentMember.indexOf(roleId) == -1) { - let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, rank); - await updateUserRecAndSendHonour(honour, myScore, rank, roleId); - hasSentMember.push(roleId); - } - userRank = rank; - } - for (let { roleId } of members) { // 只参加了,没有分数的人 - if(hasSentMember.indexOf(roleId) == -1) { - let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, userRank); - await updateUserRecAndSendHonour(honour, 0, 0, roleId); - hasSentMember.push(roleId); - } - // 发放活跃 - await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 - } - } -} - -// export async function autoDeclare() { -// for(let [ cityId ] of gameData.cityActivity) { -// let msg = { cityId, declareGuildCode: "", declareCount: 0 }; -// await sendMessageToCityWithSuc(cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); -// } -// } - -/** - * 获取活动参加者 - * @param guildCode 军团code - * @param sourceType 拍卖类型 AUCTION_SOURCE - * @param sourceCode 活动唯一code - */ -export async function participants(guildCode: string, sourceType: number, sourceCode: string) { - if(sourceCode == DEBUG_MAGIC_WORD) { - let userGuilds = await UserGuildModel.getListByGuild(guildCode); - return userGuilds.map(cur => { - return { roleId: cur.roleId, job: cur.job, baseNum: 0 } - }) - } - - if (sourceType == AUCTION_SOURCE.BOSS) { - let rec = await BossInstanceModel.findBySourceCode(guildCode, sourceCode); - if (!rec) return []; - let dic = gameData.bossBaseByBossLv.get(rec.bossLv); - return rec.ranks.map(cur => { - return { roleId: cur.roleId, job: cur.job, baseNum: dic?.basicDividend||0 } - }); - } else { - let rec = await GuildActivityRecordModel.findBySourceCode(guildCode, sourceType, sourceCode); - if (!rec) return []; - - let guild = await GuildModel.findByCode(guildCode, null, 'lv'); - let baseNum = getGuildAuctionBasicNum(rec.aid, rec.rank, guild?.lv, rec.challengeCityId); - let members = rec.members || []; - return members.map(cur => { - return { roleId: cur.roleId, job: cur.job, baseNum } - }) - } -} - -/** - * 获取诸侯入侵各个城池状态 - * @param guildCode 我方军团 - * @param dbCities 所有城池 - */ -export function getCities(guildCode: string, dbCities: GuildActivityCityType[]) { - - let cities = new Array(); - for (let [cityId, dic] of gameData.cityActivity) { - let param = new CityParam(cityId); - let curCity = dbCities.find(cur => cur.cityId == cityId); - - if (curCity) { - param.guardGuildCode = curCity.guardGuildCode || ""; - param.guardGuildName = curCity.guardGuildName || ""; - param.declareCount = curCity.declareCount || 0; - } - - param.status = getCityStatus(guildCode, cityId, dic, dbCities); - cities.push(param); - } - return cities -} - -/** - * 诸侯混战 获取城池状态 - * @param guildCode - * @param cityId - * @param dic - * @param dbCities - */ -export function getCityStatus(guildCode: string, cityId: number, dic: DicCityActivity, dbCities: GuildActivityCityType[]) { - let status = CITY_STATUS.NOT_OPEN; - let d = getCurDay(true); - let { week, preCity } = dic; - let activityStatus = getGuildActivityStatus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - if (!activityStatus) { - return CITY_STATUS.NOT_OPEN - } - - let dicGuildActivity = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let { openDay } = dicGuildActivity; - let curIndex = openDay.indexOf(week[0]); - let startDay = openDay[curIndex - 1] || 0; - let endDay = openDay[openDay.length - 1] || 0; - if (d >= startDay && d <= endDay) status = CITY_STATUS.CAN_DECLARE; - if (d == startDay && activityStatus.status != GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN; - if (d == endDay && activityStatus.status == GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN; - - let curCity = dbCities.find(cur => cur.cityId == cityId); - if (curCity) { - if (curCity.declareGuilds?.includes(guildCode)) { - status = CITY_STATUS.DECLARED; - } else if (curCity.guardGuildCode == guildCode) { - status = CITY_STATUS.GUARD; - } - } - // let hasGuard = false, hasDeclared = false; - // for(let { cityId: _cityId, guardGuildCode, declareGuilds } of dbCities) { - // let dicCity = gameData.cityActivity.get(_cityId); - // if(dicCity.type == dic.type) { - // if(guardGuildCode == guildCode) hasGuard = true; - // if(declareGuilds.includes(guildCode)) hasDeclared = true; - // } - // } - // if(status == CITY_STATUS.CAN_DECLARE && !hasDeclared && preCity.length > 0) { - // status = CITY_STATUS.NOT_OPEN; - // } - - return status; -} - -export async function sendGuildCityDeclare(serverId: number, cityId: number, declareGuildCode: string, declareCount: number) { - let msg = { cityId, declareGuildCode, declareCount }; - await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); - await sendMessageToGuildWithSuc(declareGuildCode, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); -} - -/** - * 每秒计算木牛流马状态并下发 - * @param serverId 区id - */ -export async function calWoodenHorseAndSend(serverId: number) { - // console.log('calWoodenHorseAndSend'); - let obj = getRaceActivityObj(); - return await obj.calServerHorses(serverId); -} - -/** - * 木牛流马活动开始信号 - */ -export async function sendRaceStartMsg(serverId: number) { - let obj = getRaceActivityObj(); - obj.startRace(); // 设置开启活动 - - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.RACE_START, {}); - await calWoodenHorseAndSend(serverId); -} - -export async function guildActivityStart(aid: number) { - if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - let obj = getGateActivityObj(); - obj.startActivity(); - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - let obj = getCityActivityObj(); - obj.startActivity(); - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - } -} - -/** - * 结算粮草先行奖励 - * @param cityId 城镇id - * @param serverId 服务器id - */ -export async function raceActivitySettleReward(guildCode: string, woodenHorse: WoodenHorse) { - let { serverId, durability, distance, isRobot } = woodenHorse; - if(isRobot) return; - let obj = getRaceActivityObj(); - // 已发送 - obj.send(guildCode); - // 计算排名,计算耐久,发送奖励 - let { guildRank, myGuildRank } = await obj.getRanks(serverId, guildCode); - let rank = myGuildRank?.rank||0; - - let joinIndex = getJoinIndex(); - console.log('##### raceActivitySettleReward', joinIndex, serverId, guildCode); - let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId, index: joinIndex }); - await r.setRankWithGuildInfo2(guildCode, myGuildRank.num, myGuildRank.sortTime, myGuildRank.durability); - let nextWeek = getTimeFun().getAfterDayWithHour(7); - await r.setExpire(nextWeek); - - let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团 - let members = obj.getMembersOfGuild(guildCode); - - let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); - members = members.filter(member => { - return guild.members?.find(roleId => roleId == member.roleId); - }); - - let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, rank, guild?.lv); - let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex, { - memberCnt: members.length, members, - isSuccess, isCompleted: true, rank, - rewards: getRewardToDbFromMap(rewards), - woodenHorse: woodenHorse.getTreatTime(), - }); - if (rec) { - // 奖励加入拍卖行 - await genAuction(guildCode, AUCTION_SOURCE.RACE, rec.code, serverId, rewards); - - let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); - let honour = dic.honour + Math.floor(durability * GUILDACTIVITY.RACEACTIVITY_DURABILITY_REWARD); - - let hasSentMember: string[] = []; - for(let { roleId } of members) { - if(hasSentMember.indexOf(roleId) == -1) { - await updateUserRecAndSendHonour(honour, 0, rank, roleId); - // 发放活跃 - await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 - hasSentMember.push(roleId); - } - } - } - -} - -/** - * !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 - * 改变字典表中的军团活动开始时间&持续时间 - * @param {number} aid 活动 - * @param {number} startSeconds 从现在开始几秒后开启活动 - * @param {number} endSeconds 从开始之后几秒后结束活动 - */ -export async function setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { - let startTime = new Date(now + startSeconds * 1000); - if(aid != 0) { - let guildActivity = gameData.guildActivity; - let cur = guildActivity.get(aid); - - cur.startMinute = startTime.getMinutes(); - cur.startTime = startTime.getHours(); - cur.startSeconds = startTime.getSeconds(); - cur.duringTime = endSeconds; - } - return startTime.getTime(); -} - -export async function setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { - - // console.log('********* setDicAuctionTime', startTime, endActivity, startGuild, endGuild, startWorld, endWorld); - let startGuildDate = new Date(startTime + endActivity * 1000 + startGuild * 1000); - let endGuildDate = new Date(startGuildDate.getTime() + endGuild * 1000); - let startWorldDate = new Date(endGuildDate.getTime() + startWorld * 1000); - let endWorldDate = new Date(startWorldDate.getTime() + endWorld * 1000); - let startDividendData = new Date(startWorldDate.getTime() + 3 * 60 * 1000) - - - // console.log('********* setDicAuctionTime', startGuildDate, endGuildDate, startWorldDate, endWorldDate); - - gameData.auctionTime.set(AUCTION_TIME.GUILD_PREVIEW, formatTime(new Date(startTime))); - gameData.auctionTime.set(AUCTION_TIME.GUILD_OPEN, formatTime(startGuildDate)); - gameData.auctionTime.set(AUCTION_TIME.GUILD_CLOSE, formatTime(endGuildDate)); - gameData.auctionTime.set(AUCTION_TIME.WORLD_PREVIEW, formatTime(endGuildDate)); - gameData.auctionTime.set(AUCTION_TIME.WORLD_OPEN, formatTime(startWorldDate)); - gameData.auctionTime.set(AUCTION_TIME.WORLD_CLOSE, formatTime(endWorldDate)); - gameData.auctionTime.set(AUCTION_TIME.DIVIDEND_START, formatTime(startDividendData)); - - // console.log('*********** setDicAuctionTime', gameData.auctionTime) -} - -function formatTime(date: Date) { - return { hour: date.getHours(), minute: date.getMinutes(), seconds: date.getSeconds() } -} - -export async function getCityActivityGateHp(serverId: number, cityId: number) { - let dicCityActivity = gameData.cityActivity.get(cityId); - let playerResult = await getPlayerCnt(serverId); - if (!playerResult) return dicCityActivity.hp - let { activePlayerCnt, activeGuildCnt, activePlayerCe, activeTopPlayerCnt, activePlayers } = playerResult; - - // 倍数按开服天数变化 - let ratio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.CITY_RATIO, serverId); - // 单个玩家的平均攻击力 - let playerAtkResult = await getPlayerAtkAvg(activePlayers); - if (!playerAtkResult) return dicCityActivity.hp; - let { playerAtkAvg, playerAtkSum, playerCnt } = playerAtkResult; - - // *单个玩家5回合造成的总伤害=单个玩家的平均攻击力*倍数*5(综合技能次级属性算出的倍数) - let player5Damage = playerAtkAvg * ratio * 5; - - // *平均一个军团的玩家人数=前一天参与军团活动的玩家/前一天参与军团活动的军团数量, - let guildPlayerCntAvg = await getGuildPlayerCntAvg(serverId, activePlayerCnt, activeGuildCnt); - - // 城池倍数 - let cityRatio = Math.max(Math.floor(activeGuildCnt/6), dicCityActivity.hpN); - - // 城门血量=单个玩家5回合造成的总伤害*平均一个军团的玩家人数*城池倍数 - let gateHp = Math.floor(player5Damage * guildPlayerCntAvg * cityRatio); - if(gateHp <= dicCityActivity.hp) { - gateHp = dicCityActivity.hp; - } - - saveGuildGateHpLog(serverId, cityId, { activePlayerCnt, activePlayerCe, activeTopPlayerCnt, activeGuildCnt, ratio, playerAtkSum, playerCnt, playerAtkAvg, player5Damage, guildPlayerCntAvg, cityRatio, gateHp }); - - return gateHp; -} - -// *单个玩家的平均攻击力=本服活跃玩家中最强6人排名前10的玩家的最强6人的攻击之和/10 -async function getPlayerAtkAvg(activePlayers: ActivePlayer[]) { - if (!activePlayers || activePlayers.length <= 0) return false; - let playerAtkSum = 0, playerCnt = 0; - activePlayers.sort((a, b) => b.ce - a.ce); - for (let i = 0; i < 10; i++) { - if (!activePlayers[i]) break; - let onePlayerAtkSum = 0, heroCnt = 0; - let { roleId, topLineup = [] } = activePlayers[i]; - let attrByHid = await getHeroesAttributes(roleId); - for (let { hid } of topLineup) { - let atk = attrByHid.get(hid)?.getAtk() || 0; - onePlayerAtkSum += atk; - heroCnt++; - } - if (heroCnt == 0) continue; // 基本不可能,但是以防NaN - playerAtkSum += onePlayerAtkSum / heroCnt * 6; - playerCnt++; - } - if (playerCnt == 0) return false; - let playerAtkAvg = playerAtkSum / playerCnt; - return { playerAtkSum, playerAtkAvg, playerCnt }; -} - -async function getGuildPlayerCntAvg (serverId: number, activePlayerCnt: number, activeGuildCnt: number) { - let minRatio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.CITY_PLAYER_RATIO, serverId); - let guildPlayerCntAvg = Math.floor(activePlayerCnt / activeGuildCnt); - if (guildPlayerCntAvg < minRatio) return minRatio; - return guildPlayerCntAvg -} - -async function getPlayerCnt(serverId: number) { - - let serverRecord = await ServerRecordModel.findTodayData(serverId); - if(!serverRecord) return false; - - let activePlayerCnt = 50; // 前一天参与军团活动的玩家 - let activeGuildCnt = 5; // 前一天参与军团活动的军团 - let activePlayerCe = 0; // 前一天前十玩家的最强战力和 - let activeTopPlayerCnt = 1; // 前一天最强玩家数量 - let activePlayers: ActivePlayer[] = []; - if(serverRecord) { - if(serverRecord.activePlayerCe > 0) activePlayerCe = serverRecord.activePlayerCe; - if(serverRecord.activePlayers?.length > 0) { - activeTopPlayerCnt = serverRecord.activePlayers?.length; - activePlayers = serverRecord.activePlayers||[]; - } - if(serverRecord.activeGuildCodes?.length > 0) activeGuildCnt = serverRecord.activeGuildCodes?.length; - if(serverRecord.activeGuildMembers?.length > 0) activePlayerCnt = serverRecord.activeGuildMembers?.length; - } - return { activePlayerCnt, activeGuildCnt, activePlayerCe, activeTopPlayerCnt, activePlayers } -} - -export async function declareCity(serverId: number, roleId: string, guildCode: string, cityId: number, isAutoDeclare: boolean, declareIndex: number) { - let declareTime = Date.now(); - let declareInfo = await GuildActivityCityDeclareModel.declareIfNot(serverId, guildCode, cityId, roleId, declareTime, isAutoDeclare, declareIndex); - if(!!declareInfo && declareInfo.declareTime == declareTime) { // 确实没有人宣战过,自己是第一个 - let cityRec = await GuildActivityCityModel.declare(serverId, cityId, guildCode, declareIndex); - await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, declareIndex, {}, cityId); - await sendGuildCityDeclare(serverId, cityId, guildCode, cityRec.declareCount); - return true; - } - return false; -} - -// 非军团长的团员自动宣战 -export async function autoDeclareMyCity(serverId: number, roleId: string, guildCode: string, declareIndex: number) { - let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); - if(checkResult) return false - - let cityIds = gameData.juniorCities; - let cities = await GuildActivityCityModel.findMinDeclareCountCity(serverId, cityIds, declareIndex); - let notDeclaredCitites = cityIds.filter(curCityId => { - return cities.findIndex(city => city.cityId == curCityId) == -1; - }); - let cityId = notDeclaredCitites.length > 0? getRandSingleEelm(notDeclaredCitites): cities[0].cityId; - if(!cityId) return false; - - return declareCity(serverId, roleId, guildCode, cityId, true, declareIndex); -} - -function getCounterName(aid: GUILD_ACTIVITY_TYPE) { - switch(aid) { - case GUILD_ACTIVITY_TYPE.GATE_ACTIVITY: - return COUNTER.GATE_ACTIVITY; - case GUILD_ACTIVITY_TYPE.CITY_ACTIVITY: - return COUNTER.CITY_ACTIVITY; - case GUILD_ACTIVITY_TYPE.RACE_ACTIVITY: - return COUNTER.RACE_ACTIVITY; - } -} - -export async function incCurGuildActivityIndex(aid: number) { - let name = getCounterName(aid); - let index = await CounterModel.getNewCounter(name); - setGuildActivityIndexInPinus(aid, index); // systime - pinus.app.rpc.guild.guildActivityRemote.setGuildActivityIndex.broadcast(aid, index); -} - -export async function initGuildActivityIndexInPinus() { - for(let aid = GUILD_ACTIVITY_TYPE.GATE_ACTIVITY; aid <= GUILD_ACTIVITY_TYPE.RACE_ACTIVITY; aid++){ - let index = await getCurGuildActivityIndexByDb(aid); - setGuildActivityIndexInPinus(aid, index); - } -} - -export async function getCurGuildActivityIndexByDb(aid: number) { - let name = getCounterName(aid); - return await CounterModel.getCounter(name); -} - -export function getGAPinusName(aid: number) { - return `guildact${aid}`; -} - -export function setGuildActivityIndexInPinus(aid: number, index: number) { - pinus.app.set(getGAPinusName(aid), index); -} - -export function getGAIndexInPinus(aid: number) { - return pinus.app.get(getGAPinusName(aid)); -} - -export function getDeclareIndex() { - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let obj = getCityActivityObj(); - if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) return index; - return index + 1; -} - -export function getJoinIndex() { - let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); - let obj = getRaceActivityObj(); - if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START || obj.getStatus() == GUILD_ACTIVITY_STATUS.END) return index; - return index + 1; -} - - -export async function resetJoinWoodenHorse() { - let obj = getRaceActivityObj(); - let joinIndex = getJoinIndex(); - - let guild = pinus.app.getServersByType('guild'); - let recs = await GuildActivityRecordModel.findRecs(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex); - for(let { serverId, guildCode, joinMember } of recs) { - let server = await dispatch(redisClient(), `${serverId}`, guild, 'guild'); - if(server.id != pinus.app.getServerId()) continue; - - for(let { roleId, roleName, job, code} of joinMember) { - let hasJoin = !!obj.getMember(guildCode, roleId); - if (hasJoin) continue; - await obj.joinWoodenHorse(guildCode, roleId, roleName, serverId, '', job, code); - } - } - return true -} - -export async function debugSendGateHp(serverId: number, cityId: number) { - let obj = getCityActivityObj(); - let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); - await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_ACT_HP, { cityId, gateHp: gateHp + 1000, maxHp }); -} - -export async function debugAddHorse(serverId: number, guildCode: string, memberCnt: number, itemInterval: number) { - - let obj = getRaceActivityObj(); - - let dicItem = gameData.raceTypes.get(RACE_EVENT_TYPE.DEFAULT); - let items: number[] = []; - for(let [_, arr] of dicItem) { - items.push(...arr); - }; - - for(let i = 0; i < memberCnt; i++) { - let roleId = `roleId${i}`; - await obj.joinWoodenHorse(guildCode, roleId, 'roleName', serverId, null, 6, 'code', true); - - } - - if(itemInterval >= 100) { - let members = obj.getMembersOfGuild(guildCode); - let timer = setInterval(async () => { - await obj.useItem(serverId, members[0]?.roleId, '', guildCode, guildCode, getRandSingleEelm(items), 1, true); - let woodenHorse = await obj.getWoodenHorse(guildCode, serverId, true); - if(woodenHorse.status == RACE_ACTIVITY_STATUS.END) { - clearInterval(timer); - } - }, itemInterval); - setTimeout(() => { - clearInterval(timer); - }, 10 * 60 * 1000); - } -} - -export async function leaveRaceActivity(serverId: number, guildCode: string, roleId: string ) { - if(!guildCode) return; - let obj = getRaceActivityObj(); - await obj.memberLeave(guildCode, serverId, roleId); -} - -export async function leaveRaceActivityToRemote(serverId: number, guildCode: string, roleId: string) { - let guildServers = pinus.app.getServersByType('guild')||[]; - let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); - if(server) { - await pinus.app.rpc.guild.guildActivityRemote.leaveRaceActivity.toServer(server.id, serverId, guildCode, roleId); - } -} - -export async function leaveRaceWhenQuitGuild(serverId: number, guildCode: string, roleId: string) { - if(!guildCode) return; - let obj = getRaceActivityObj(); - await obj.memberQuit(guildCode, serverId, roleId); - let joinIndex = getJoinIndex(); - await GuildActivityRecordModel.removeMember(guildCode, serverId, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex, roleId); -} - -export async function leaveRaceWhenQuitGuildToRemote(serverId: number, guildCode: string, roleId: string) { - let guildServers = pinus.app.getServersByType('guild')||[]; - let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); - if(server) { - await pinus.app.rpc.guild.guildActivityRemote.leaveRaceWhenQuitGuild.toServer(server.id, serverId, guildCode, roleId); - } - let index1 = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - let gateR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index: index1 }, true); - gateR.removeFromRank({ roleId }); - - - let index2 = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - let declareIndex = getDeclareIndex(); - - let obj = getCityActivityObj(); - if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { - await autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); - } - - let city = await GuildActivityCityDeclareModel.findDeclartion(serverId, guildCode, declareIndex) - if (city) { - let cityR = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId: city.cityId, index: index2 }, true); - cityR.removeFromRank({ roleId }); - } -} - -export async function leaveRaceWhenDismiss(guildCode: string, serverId: number) { - if(!guildCode) return; - let obj = getRaceActivityObj(); - obj.dismiss(guildCode); - let joinIndex = getJoinIndex(); - await GuildActivityRecordModel.dismiss(guildCode, serverId, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex); -} - -export async function leaveRaceWhenDismissToRemote(serverId: number, guildCode: string) { - let guildServers = pinus.app.getServersByType('guild')||[]; - let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); - if(server) { - await pinus.app.rpc.guild.guildActivityRemote.leaveRaceWhenDismiss.toServer(server.id, guildCode, serverId); - } -} \ No newline at end of file +import { ServerlistModel, ServerlistType } from "@db/Serverlist"; +import { RoleModel } from "@db/Role"; +import { GUILDACTIVITY } from "@pubUtils/dicParam"; +import { gameData, getBossHpRatio, getCityActivityRewards } from "@pubUtils/data"; +import { getCurDay, nowSeconds, getTimeFun, getZeroPoint, getZeroPointOfTime } from "@pubUtils/timeUtil"; +import { GUILD_ACTIVITY_STATUS, GET_POINT_WAYS, GUILD_ACTIVITY_TYPE, REDIS_KEY, AUCTION_SOURCE, MAIL_TYPE, CITY_STATUS, DEBUG_MAGIC_WORD, GUILD_POINT_WAYS, TASK_TYPE, AUCTION_TIME, CITY_ACTIVITY_DOOR, ABI_TYPE, PUSH_ROUTE, RACE_ACTIVITY_STATUS, SHOP_REFRESH_TYPE, COUNTER, RACE_EVENT_TYPE, BOSS_HP_RATIO_TYPE } from "@consts"; +import { Record, UserGuildActivityRecModel } from "@db/UserGuildActivityRec"; +import { GateMembersRec, CityParam, WoodenHorse, RaceActivityRankParam } from "@domain/battleField/guildActivity"; +import { DicGuildActivity } from "@pubUtils/dictionary/DicGuildActivity"; +import { getAllServers, getRoleOnlineInfo, getServerCreateTime, redisClient } from "../redisService"; +import { SimpleGuildRankParam, SimpleRoleRankParam, GuildRankInfo, RoleRankInfo } from "@domain/rank"; +import { pinus } from "pinus"; +import { GuildActivityRecordModel } from "@db/GuildActivityRec"; +import { genAuction, getGuildAuctionBasicNum, getGuildAuctionRewards, getRewardToDbFromMap, guildAuctionPreview } from "../auctionService"; +import { sendMailByContent } from "../mailService"; +import { GuildActivityCityType, GuildActivityCityModel } from "@db/GuildActivityCity"; +import { DicCityActivity } from "@pubUtils/dictionary/DicCityActivity"; +import { Rank } from "../rankService"; +import { BossInstanceModel } from "@db/BossInstance"; +import { UserGuildModel } from "@db/UserGuild"; +import { addActive } from "../guildService"; +import { ActivePlayer, GuildRecord, ServerRecordModel } from "@db/ServerRecords"; +import { getHonourObject } from "../role/rewardService"; +import { sendMessageToCityWithSuc, sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToUserWithSuc } from "../pushService"; +import { saveGuildGateHpLog } from "@pubUtils/logUtil"; +import { GuildActivityCityDeclareModel } from "@db/GuildActivityCityDeclare"; +import { getRandSingleEelm } from "@pubUtils/util"; +import { CounterModel } from "@db/Counter"; +import { setInterval } from "timers"; +import { dispatch } from "@pubUtils/dispatcher"; +import { GuildModel } from "@db/Guild"; +import { getCityActivityObj, getGateActivityObj, getRaceActivityObj } from "../memoryCache/guildActivityData"; +import { getBossHpRatioByServer } from "../guildBossService"; +import { getHeroesAttributes } from "../playerCeService"; + + +/** + * 定时任务,获得前一天的活跃玩家中位数武将战力 + */ +export async function setPreDayActiveData(servers: ServerlistType[]) { + + for (let server of servers) { + let roles = await RoleModel.getActivePlayers(server.id); + let activePlayerCnt = roles.length; + let activePlayerCe = 0, activePlayers: ActivePlayer[] = []; + let activeGuilds: GuildRecord[] = []; + + for(let i = 0; i < roles.length; i++) { + let role = roles[i]; + let activePlayer = new ActivePlayer(role); + if(i < 10) { + activePlayerCe += role.topLineupCe; + activePlayers.push(activePlayer); + } + if(role.hasGuild) { + let guildRecord = activeGuilds.find(cur => cur.guildCode == role.guildCode); + if(!guildRecord) { + activeGuilds.push({ guildCode: role.guildCode, players: [activePlayer] }); + } else { + guildRecord.players.push(activePlayer); + } + } + } + + await ServerRecordModel.updateData(server.id, { activePlayerCnt, activePlayerCe, activePlayers, activeGuilds }); + } + return servers; +} + +/** + * 根据当前时间判断军团活动倒计时 + * @param id 军团活动id + */ +export function getGuildActivityStatus(id: number) { + let dicGuildActivity = gameData.guildActivity.get(id); + if (!dicGuildActivity) return false; + return getGuildActivityByDic(dicGuildActivity); +} + +export async function getAllGuildActivityStatus(guildCode: string, serverId: number) { + let guildActivities: { aid: number, status: number, time: number, isOpen: boolean, isCompleted?: boolean }[] = []; + for(let [ aid, dicGuildActivity ] of gameData.guildActivity) { + let index = getGAIndexInPinus(aid); + let res = getGuildActivityByDic(dicGuildActivity); + let isCompleted = res.isOpen; + if(res.status == GUILD_ACTIVITY_STATUS.START && guildCode) { + let guildActivityRec = await GuildActivityRecordModel.getRecord(guildCode, serverId, aid, index); + if(guildActivityRec) isCompleted = guildActivityRec.isCompleted; + } + guildActivities.push({aid, ...res, isCompleted}); + } + return guildActivities; +} + +export function getGuildActivityByDic(dicGuildActivity: DicGuildActivity) { + let t = getTimeFun(); + // console.log('*********', dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds) + let startTime = t.getTimeWithHour(dicGuildActivity.startTime, dicGuildActivity.startMinute, dicGuildActivity.startSeconds); + let countdownTime = t.getTimeWithHour(dicGuildActivity.countDown); + let { duringTime, openDay } = dicGuildActivity; + let endTime = startTime + duringTime; + + let status = 0, time = 0; + let now = nowSeconds(); + if (now >= countdownTime && now < startTime) { + status = GUILD_ACTIVITY_STATUS.WAITING; + time = startTime - now; + } else if (now >= startTime && now < endTime) { + status = GUILD_ACTIVITY_STATUS.START; + time = endTime - now; + } else { + status = GUILD_ACTIVITY_STATUS.END; + } + + let day = getCurDay(); + let isOpen = openDay.includes(day); + + return { + status, time, isOpen + } +} + +/** + * 根据每回合上报数据判断军功 + * @param aid + * @param record + * @param memberRecord + */ +export function getRecordScore(aid: number, round: number, record: { round: number, dataId: number }[], memberRecord: GateMembersRec) { + let dicGuildActivity = gameData.guildActivity.get(aid); + if (!dicGuildActivity) return false; + + let dicWarJson = gameData.warJson.get(dicGuildActivity.warid); + if (!dicWarJson) return false; + + let { round: curRound, enemies: historyEnemies } = memberRecord; + let sum = 0, newRecords = new Array(); + for (let { round, dataId } of record) { + if (!historyEnemies.includes(dataId)) { + + let enemy = dicWarJson.find(cur => cur.dataId == dataId); + let enemyType = enemy.enemyType; + let score = gameData.gateActivityPoint.get(enemyType); + newRecords.push({ round, dataId, score, enemyType }); + sum += score; + + historyEnemies.push(dataId); + } + } + + for (let i = curRound + 1; i <= round; i++) { + sum += gameData.gateActivityPoint.get(GET_POINT_WAYS.ROUND_START); + memberRecord.round = i; + } + + return { score: sum, newRecords, memberRecord } +} + +export async function getGateActivityRank(guildCode: string, serverId: number, roleId?: string, roleName?: string) { + + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); + r.setGenerFieldsFun(generGuildActivityRankField); + let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); + if (!myGuildRank) { + myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); + } + + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); + myR.setGenerFieldsFun(generGuildActivityMemberRankField); + let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId }); + if (roleName && !myMemberRank) { + myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0); + } + + return { guildRank, myGuildRank, memberRank, myMemberRank } +} + +export async function getCityActivityRank(guildCode: string, serverId: number, cityId: number, roleId?: string, roleName?: string) { + + if(!cityId) { + return { guildRank: [], myGuildRank: undefined, memberRank: [], myMemberRank: undefined } + } + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); + r.setGenerFieldsFun(generGuildActivityRankField); + let { ranks: guildRank, myRank: myGuildRank } = await r.getRankListWithMyRank({ guildCode }); + if (!myGuildRank) { + myGuildRank = await r.generMyRankWithGuild(guildCode, 0, 0); + } + + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); + myR.setGenerFieldsFun(generGuildActivityMemberRankField); + let { ranks: memberRank, myRank: myMemberRank } = await myR.getRankListWithMyRank({ roleId }); + if (roleName && !myMemberRank) { + myMemberRank = await myR.generMyRankWithRole(roleId, 0, 0); + } + + return { guildRank, myGuildRank, memberRank, myMemberRank } +} +/** + * 获取和自己同屏的5个木牛流马 + * @param guildCode + * @param serverId + */ +export async function getWoodenHorseList(guildCode: string, serverId: number) { + let obj = getRaceActivityObj(); + let { myGuildRank, guildRank } = await obj.getRanks(serverId, guildCode); + + let myRank = myGuildRank?.rank||0; + let startRank = myRank - 2 > 0 ? myRank - 2 : 1; + let endRank = startRank + 4; + let woodenHorseList = new Array(); + for (let { rank, code } of guildRank) { + if(rank >= startRank && rank <= endRank) { + let woodenHorse = await obj.getWoodenHorse(code, serverId); + if (woodenHorse) { + woodenHorseList.push(woodenHorse); + } + } + } + return woodenHorseList; +} + +function generGuildActivityRankField(param: GuildRankInfo) { + let { rank, code, name, num } = param; + return new SimpleGuildRankParam(rank, code, name, num); +} + +function generGuildActivityMemberRankField(param: RoleRankInfo) { + let { rank, roleId, roleName, num } = param; + return new SimpleRoleRankParam(rank, roleId, roleName, num); +} + +/** + * 对这个guild服内所有军团发排行榜信息 + * @param aid 活动类型 + */ +export async function sendAllGuildRanks(aid: number) { + if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + let obj = getGateActivityObj(); + let guilds = obj.getGuilds(); + for (let [serverId, guildCodes] of guilds) { + for (let guildCode of guildCodes) { + let ranks = await getGateActivityRank(guildCode, serverId); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GATE_ACT_RANK, ranks); + } + } + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + let obj = getCityActivityObj(); + let { cities } = obj.getAllCities(); + // console.log(JSON.stringify(cities)); + for (let { serverId, cityId, guildCodes } of cities) { + for (let guildCode of guildCodes) { + let ranks = await getCityActivityRank(guildCode, serverId, cityId); + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.CITY_ACT_RANK, ranks); + } + } + } +} + +export async function sendCityGuildRankToUser(serverId: number, cityId: number, guildCode: string, roleId: string) { + let ranks = await getCityActivityRank(guildCode, serverId, cityId); + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.CITY_ACT_RANK, ranks); +} + +/** + * 活动结算奖励 + * @param aid 活动类型 + */ +export async function settleGuildActivityReward(aid: number) { + + if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + let obj = getGateActivityObj(); + let guilds = obj.getGuilds(); + for (let [serverId, guildCodes] of guilds) { + // console.log('***** serverId', serverId, 'guildCodes', guildCodes); + for (let guildCode of guildCodes) { + await gateActivitySettleReward(guildCode, serverId); + } + } + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + let obj = getCityActivityObj(); + obj.endActivity(); + let { cities } = obj.getAllCities(); + for (let { serverId, cityId } of cities) { + await cityActivitySettleReward(cityId, serverId); + } + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + let obj = getRaceActivityObj(); + obj.stopRace(); + + for (let { guildCode, serverId } of obj.getGuilds()) { + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId); + if (woodenHorse && woodenHorse.distance > 0 && !obj.hasSend(guildCode)) { + await raceActivitySettleReward(guildCode, woodenHorse); + } + } + } +} + +// 全服发送结束新号 +export async function sendEndMsgToAllServer() { + let serverlist = await getAllServers(); + for (let serverId of serverlist) { + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); + await sendGuildActivityStatus(serverId); + } +} + +export async function sendGuildActivityStatus(serverId: number) { + let guildActivities: { aid: number, status: number, time: number, isOpen: boolean }[] = []; + gameData.guildActivity.forEach((dicGuildActivity, aid) => { + let res = getGuildActivityByDic(dicGuildActivity); + guildActivities.push({aid ,...res}); + }); + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.GUILD_ACTIVITY_STATUS, { guildActivities }); +} + + +/** + * 单个城池城门血条破了之后给他发奖励 + * @param guildCode 军团code + */ +export async function sendSingleCityActEndMsg(cityId: number, serverId: number) { + let obj = getCityActivityObj(); + let guildCodes = obj.getGuildsInCity(serverId, cityId); + for (let guildCode of guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); + } + await cityActivitySettleReward(cityId, serverId); +} + + +/** + * 单个军团抵达赛道之后给他发奖励 + * @param guildCode 军团code + */ +export async function sendSingleRaceActEndMsg(guildCode: string, woodenHorse: WoodenHorse) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_ACTIVITY_END, {}); + await raceActivitySettleReward(guildCode, woodenHorse); +} + + +/** + * 结算蛮夷入侵奖励 + * @param guildCode 军团code + * @param serverId 服务器id + */ +export async function gateActivitySettleReward(guildCode: string, serverId: number) { + console.log('gateActivitySettleReward', guildCode, serverId); + let obj = getGateActivityObj(); + let { members } = obj.getObj(guildCode, serverId); + // console.log('***** gateHp', gateHp, 'members', members); + + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + let r = new Rank(REDIS_KEY.GATE_ACTIVITY, { serverId, index }, true); + let rank = await r.getMyRank({ guildCode }); + let guildScore = await r.getMyScore({ guildCode }); + // console.log('****** ranks', rank, 'guildScore', guildScore); + + let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); + let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, rank, guild?.lv); + // console.log('***** rewards', JSON.stringify(rewards)); + + members = members.filter(member => { + return guild.members?.find(roleId => roleId == member.roleId); + }); + let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.GATE_ACTIVITY, index, { + isSuccess: true, + isCompleted: true, + rank, score: guildScore, + members, memberCnt: members.length, + auctionType: AUCTION_SOURCE.GATE, + rewards: getRewardToDbFromMap(rewards) + }); + // 结算功勋等奖励 + let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + + let myR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index }, true); + + let hasSentMember: string[] = []; + let ranks = await myR.getRankByRange(); + for (let { rank, roleId, num: myScore } of ranks) { + if(hasSentMember.indexOf(roleId) == -1) { + let honour = dic.honour + myScore * GUILDACTIVITY.GATEACTIVITY_HONOUR_RATIO; + await updateUserRecAndSendHonour(honour, myScore, rank, roleId); + hasSentMember.push(roleId); + } + } + for (let { roleId } of members) { + // 只参加了,没有分数的人 + if(hasSentMember.indexOf(roleId) == -1) { + await updateUserRecAndSendHonour(dic.honour, 0, 0, roleId); + hasSentMember.push(roleId); + } + // 发放活跃 + await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 + } + + // 加入拍卖行 + await genAuction(guildCode, AUCTION_SOURCE.GATE, rec.code, serverId, rewards); + + // obj.delGuildRecord(guildCode, serverId); +} + +async function updateUserRecAndSendHonour(honour: number, myScore: number, rank: number, roleId: string) { + let honourObj = getHonourObject(Math.floor(honour)); + await sendMailByContent(MAIL_TYPE.GUILD_ACTIVITY_REWARD, roleId, { goods: [honourObj] }) + + await UserGuildActivityRecModel.updateInfoByRoleId(roleId, { score: myScore, rank }); +} + + +/** + * 结算诸侯入侵奖励 + * @param cityId 城镇id + * @param serverId 服务器id + */ +export async function cityActivitySettleReward(cityId: number, serverId: number) { + console.log('###### cityActivitySettleReward 0') + let obj = getCityActivityObj(); + if(!obj.lockCity(serverId, cityId)) return; + + let dicCity = gameData.cityActivity.get(cityId); + if (!dicCity) return; + let {gateHp} = await obj.getGateHpAndInc(serverId, cityId); + let isSuccess = gateHp <= 0; // 血条未击破则没有占领军团 + + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let r = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId, index }, true); + let ranks = await r.getRankByRange(); + console.log('###### cityActivitySettleReward 1', JSON.stringify(ranks)); + for (let { rank: guildRank, code: guildCode, name, num } of ranks) { + if (guildRank == 1) { + if (isSuccess) { + await GuildActivityCityModel.guard(serverId, cityId, guildCode, name, index + 1); // 占领 + if(getCurDay(true) != 6) { + await declareCity(serverId, "", guildCode, dicCity.nextCity, true, index + 1); + } + } else { + await GuildActivityCityModel.guard(serverId, cityId, "", "", index + 1); // 无人能占领 + } + } + let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); + let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, guildRank, guild?.lv, cityId); + let members = obj.getMembersOfGuild(guildCode); + members = members.filter(member => { + return guild.members?.find(roleId => roleId == member.roleId); + }); + let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, index, { + members, memberCnt: members.length, + isSuccess, isCompleted: true, + rank: guildRank, damage: num, remainGateHp: gateHp, + rewards: getRewardToDbFromMap(rewards), + auctionType: AUCTION_SOURCE.CITY, + }, cityId); + + // 奖励加入拍卖行 + await genAuction(guildCode, AUCTION_SOURCE.CITY, rec.code, serverId, rewards); + + let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let myR = new Rank(REDIS_KEY.USER_CITY_ACTIVITY, { serverId, guildCode, index }, true); + let ranks = await myR.getRankByRange(); + let userRank = 0; + let hasSentMember: string[] = []; + for (let { rank, roleId, num: myScore } of ranks) { + if(hasSentMember.indexOf(roleId) == -1) { + let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, rank); + await updateUserRecAndSendHonour(honour, myScore, rank, roleId); + hasSentMember.push(roleId); + } + userRank = rank; + } + for (let { roleId } of members) { // 只参加了,没有分数的人 + if(hasSentMember.indexOf(roleId) == -1) { + let honour = dic.honour + getCityActivityRewards(dicCity.type, guildRank, userRank); + await updateUserRecAndSendHonour(honour, 0, 0, roleId); + hasSentMember.push(roleId); + } + // 发放活跃 + await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 + } + } +} + +// export async function autoDeclare() { +// for(let [ cityId ] of gameData.cityActivity) { +// let msg = { cityId, declareGuildCode: "", declareCount: 0 }; +// await sendMessageToCityWithSuc(cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); +// } +// } + +/** + * 获取活动参加者 + * @param guildCode 军团code + * @param sourceType 拍卖类型 AUCTION_SOURCE + * @param sourceCode 活动唯一code + */ +export async function participants(guildCode: string, sourceType: number, sourceCode: string) { + if(sourceCode == DEBUG_MAGIC_WORD) { + let userGuilds = await UserGuildModel.getListByGuild(guildCode); + return userGuilds.map(cur => { + return { roleId: cur.roleId, job: cur.job, baseNum: 0 } + }) + } + + if (sourceType == AUCTION_SOURCE.BOSS) { + let rec = await BossInstanceModel.findBySourceCode(guildCode, sourceCode); + if (!rec) return []; + let dic = gameData.bossBaseByBossLv.get(rec.bossLv); + return rec.ranks.map(cur => { + return { roleId: cur.roleId, job: cur.job, baseNum: dic?.basicDividend||0 } + }); + } else { + let rec = await GuildActivityRecordModel.findBySourceCode(guildCode, sourceType, sourceCode); + if (!rec) return []; + + let guild = await GuildModel.findByCode(guildCode, null, 'lv'); + let baseNum = getGuildAuctionBasicNum(rec.aid, rec.rank, guild?.lv, rec.challengeCityId); + let members = rec.members || []; + return members.map(cur => { + return { roleId: cur.roleId, job: cur.job, baseNum } + }) + } +} + +/** + * 获取诸侯入侵各个城池状态 + * @param guildCode 我方军团 + * @param dbCities 所有城池 + */ +export function getCities(guildCode: string, dbCities: GuildActivityCityType[]) { + + let cities = new Array(); + for (let [cityId, dic] of gameData.cityActivity) { + let param = new CityParam(cityId); + let curCity = dbCities.find(cur => cur.cityId == cityId); + + if (curCity) { + param.guardGuildCode = curCity.guardGuildCode || ""; + param.guardGuildName = curCity.guardGuildName || ""; + param.declareCount = curCity.declareCount || 0; + } + + param.status = getCityStatus(guildCode, cityId, dic, dbCities); + cities.push(param); + } + return cities +} + +/** + * 诸侯混战 获取城池状态 + * @param guildCode + * @param cityId + * @param dic + * @param dbCities + */ +export function getCityStatus(guildCode: string, cityId: number, dic: DicCityActivity, dbCities: GuildActivityCityType[]) { + let status = CITY_STATUS.NOT_OPEN; + let d = getCurDay(true); + let { week, preCity } = dic; + let activityStatus = getGuildActivityStatus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + if (!activityStatus) { + return CITY_STATUS.NOT_OPEN + } + + let dicGuildActivity = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let { openDay } = dicGuildActivity; + let curIndex = openDay.indexOf(week[0]); + let startDay = openDay[curIndex - 1] || 0; + let endDay = openDay[openDay.length - 1] || 0; + if (d >= startDay && d <= endDay) status = CITY_STATUS.CAN_DECLARE; + if (d == startDay && activityStatus.status != GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN; + if (d == endDay && activityStatus.status == GUILD_ACTIVITY_STATUS.END) status = CITY_STATUS.NOT_OPEN; + + let curCity = dbCities.find(cur => cur.cityId == cityId); + if (curCity) { + if (curCity.declareGuilds?.includes(guildCode)) { + status = CITY_STATUS.DECLARED; + } else if (curCity.guardGuildCode == guildCode) { + status = CITY_STATUS.GUARD; + } + } + // let hasGuard = false, hasDeclared = false; + // for(let { cityId: _cityId, guardGuildCode, declareGuilds } of dbCities) { + // let dicCity = gameData.cityActivity.get(_cityId); + // if(dicCity.type == dic.type) { + // if(guardGuildCode == guildCode) hasGuard = true; + // if(declareGuilds.includes(guildCode)) hasDeclared = true; + // } + // } + // if(status == CITY_STATUS.CAN_DECLARE && !hasDeclared && preCity.length > 0) { + // status = CITY_STATUS.NOT_OPEN; + // } + + return status; +} + +export async function sendGuildCityDeclare(serverId: number, cityId: number, declareGuildCode: string, declareCount: number) { + let msg = { cityId, declareGuildCode, declareCount }; + await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); + await sendMessageToGuildWithSuc(declareGuildCode, PUSH_ROUTE.GUILD_CITY_DECLARE, msg); +} + +/** + * 每秒计算木牛流马状态并下发 + * @param serverId 区id + */ +export async function calWoodenHorseAndSend(serverId: number) { + // console.log('calWoodenHorseAndSend'); + let obj = getRaceActivityObj(); + return await obj.calServerHorses(serverId); +} + +/** + * 木牛流马活动开始信号 + */ +export async function sendRaceStartMsg(serverId: number) { + let obj = getRaceActivityObj(); + obj.startRace(); // 设置开启活动 + + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.RACE_START, {}); + await calWoodenHorseAndSend(serverId); +} + +export async function guildActivityStart(aid: number) { + if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + let obj = getGateActivityObj(); + obj.startActivity(); + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + let obj = getCityActivityObj(); + obj.startActivity(); + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + } +} + +/** + * 结算粮草先行奖励 + * @param cityId 城镇id + * @param serverId 服务器id + */ +export async function raceActivitySettleReward(guildCode: string, woodenHorse: WoodenHorse) { + let { serverId, durability, distance, isRobot } = woodenHorse; + if(isRobot) return; + let obj = getRaceActivityObj(); + // 已发送 + obj.send(guildCode); + // 计算排名,计算耐久,发送奖励 + let { guildRank, myGuildRank } = await obj.getRanks(serverId, guildCode); + let rank = myGuildRank?.rank||0; + + let joinIndex = getJoinIndex(); + console.log('##### raceActivitySettleReward', joinIndex, serverId, guildCode); + let r = new Rank(REDIS_KEY.RACE_ACTIVITY, { serverId, index: joinIndex }); + await r.setRankWithGuildInfo2(guildCode, myGuildRank.num, myGuildRank.sortTime, myGuildRank.durability); + let nextWeek = getTimeFun().getAfterDayWithHour(7); + await r.setExpire(nextWeek); + + let isSuccess = distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH; // 血条未击破则没有占领军团 + let members = obj.getMembersOfGuild(guildCode); + + let guild = await GuildModel.findByCode(guildCode, serverId, 'lv members'); + members = members.filter(member => { + return guild.members?.find(roleId => roleId == member.roleId); + }); + + let rewards = getGuildAuctionRewards(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, rank, guild?.lv); + let rec = await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex, { + memberCnt: members.length, members, + isSuccess, isCompleted: true, rank, + rewards: getRewardToDbFromMap(rewards), + woodenHorse: woodenHorse.getTreatTime(), + }); + if (rec) { + // 奖励加入拍卖行 + await genAuction(guildCode, AUCTION_SOURCE.RACE, rec.code, serverId, rewards); + + let dic = gameData.guildActivity.get(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); + let honour = dic.honour + Math.floor(durability * GUILDACTIVITY.RACEACTIVITY_DURABILITY_REWARD); + + let hasSentMember: string[] = []; + for(let { roleId } of members) { + if(hasSentMember.indexOf(roleId) == -1) { + await updateUserRecAndSendHonour(honour, 0, rank, roleId); + // 发放活跃 + await addActive(roleId, serverId, GUILD_POINT_WAYS.ACTIVITY); //获得活跃值 + hasSentMember.push(roleId); + } + } + } + +} + +/** + * !! 注意,这条函数会改变内存中的字典表,仅用于测试中使用 + * 改变字典表中的军团活动开始时间&持续时间 + * @param {number} aid 活动 + * @param {number} startSeconds 从现在开始几秒后开启活动 + * @param {number} endSeconds 从开始之后几秒后结束活动 + */ +export async function setDicGuildActivity(now: number, aid: number, startSeconds: number, endSeconds: number) { + let startTime = new Date(now + startSeconds * 1000); + if(aid != 0) { + let guildActivity = gameData.guildActivity; + let cur = guildActivity.get(aid); + + cur.startMinute = startTime.getMinutes(); + cur.startTime = startTime.getHours(); + cur.startSeconds = startTime.getSeconds(); + cur.duringTime = endSeconds; + } + return startTime.getTime(); +} + +export async function setDicAuctionTime(startTime: number, endActivity: number, startGuild: number, endGuild: number, startWorld: number, endWorld: number) { + + // console.log('********* setDicAuctionTime', startTime, endActivity, startGuild, endGuild, startWorld, endWorld); + let startGuildDate = new Date(startTime + endActivity * 1000 + startGuild * 1000); + let endGuildDate = new Date(startGuildDate.getTime() + endGuild * 1000); + let startWorldDate = new Date(endGuildDate.getTime() + startWorld * 1000); + let endWorldDate = new Date(startWorldDate.getTime() + endWorld * 1000); + let startDividendData = new Date(startWorldDate.getTime() + 3 * 60 * 1000) + + + // console.log('********* setDicAuctionTime', startGuildDate, endGuildDate, startWorldDate, endWorldDate); + + gameData.auctionTime.set(AUCTION_TIME.GUILD_PREVIEW, formatTime(new Date(startTime))); + gameData.auctionTime.set(AUCTION_TIME.GUILD_OPEN, formatTime(startGuildDate)); + gameData.auctionTime.set(AUCTION_TIME.GUILD_CLOSE, formatTime(endGuildDate)); + gameData.auctionTime.set(AUCTION_TIME.WORLD_PREVIEW, formatTime(endGuildDate)); + gameData.auctionTime.set(AUCTION_TIME.WORLD_OPEN, formatTime(startWorldDate)); + gameData.auctionTime.set(AUCTION_TIME.WORLD_CLOSE, formatTime(endWorldDate)); + gameData.auctionTime.set(AUCTION_TIME.DIVIDEND_START, formatTime(startDividendData)); + + // console.log('*********** setDicAuctionTime', gameData.auctionTime) +} + +function formatTime(date: Date) { + return { hour: date.getHours(), minute: date.getMinutes(), seconds: date.getSeconds() } +} + +export async function getCityActivityGateHp(serverId: number, cityId: number) { + let dicCityActivity = gameData.cityActivity.get(cityId); + let playerResult = await getPlayerCnt(serverId); + if (!playerResult) return dicCityActivity.hp + let { activePlayerCnt, activeGuildCnt, activePlayerCe, activeTopPlayerCnt, activePlayers } = playerResult; + + // 倍数按开服天数变化 + let ratio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.CITY_RATIO, serverId); + // 单个玩家的平均攻击力 + let playerAtkResult = await getPlayerAtkAvg(activePlayers); + if (!playerAtkResult) return dicCityActivity.hp; + let { playerAtkAvg, playerAtkSum, playerCnt } = playerAtkResult; + + // *单个玩家5回合造成的总伤害=单个玩家的平均攻击力*倍数*5(综合技能次级属性算出的倍数) + let player5Damage = playerAtkAvg * ratio * 5; + + // *平均一个军团的玩家人数=前一天参与军团活动的玩家/前一天参与军团活动的军团数量, + let guildPlayerCntAvg = await getGuildPlayerCntAvg(serverId, activePlayerCnt, activeGuildCnt); + + // 城池倍数 + let cityRatio = Math.max(Math.floor(activeGuildCnt/6), dicCityActivity.hpN); + + // 城门血量=单个玩家5回合造成的总伤害*平均一个军团的玩家人数*城池倍数 + let gateHp = Math.floor(player5Damage * guildPlayerCntAvg * cityRatio); + if(gateHp <= dicCityActivity.hp) { + gateHp = dicCityActivity.hp; + } + + saveGuildGateHpLog(serverId, cityId, { activePlayerCnt, activePlayerCe, activeTopPlayerCnt, activeGuildCnt, ratio, playerAtkSum, playerCnt, playerAtkAvg, player5Damage, guildPlayerCntAvg, cityRatio, gateHp }); + + return gateHp; +} + +// *单个玩家的平均攻击力=本服活跃玩家中最强6人排名前10的玩家的最强6人的攻击之和/10 +async function getPlayerAtkAvg(activePlayers: ActivePlayer[]) { + if (!activePlayers || activePlayers.length <= 0) return false; + let playerAtkSum = 0, playerCnt = 0; + activePlayers.sort((a, b) => b.ce - a.ce); + for (let i = 0; i < 10; i++) { + if (!activePlayers[i]) break; + let onePlayerAtkSum = 0, heroCnt = 0; + let { roleId, topLineup = [] } = activePlayers[i]; + let attrByHid = await getHeroesAttributes(roleId); + for (let { hid } of topLineup) { + let atk = attrByHid.get(hid)?.getAtk() || 0; + onePlayerAtkSum += atk; + heroCnt++; + } + if (heroCnt == 0) continue; // 基本不可能,但是以防NaN + playerAtkSum += onePlayerAtkSum / heroCnt * 6; + playerCnt++; + } + if (playerCnt == 0) return false; + let playerAtkAvg = playerAtkSum / playerCnt; + return { playerAtkSum, playerAtkAvg, playerCnt }; +} + +async function getGuildPlayerCntAvg (serverId: number, activePlayerCnt: number, activeGuildCnt: number) { + let minRatio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.CITY_PLAYER_RATIO, serverId); + let guildPlayerCntAvg = Math.floor(activePlayerCnt / activeGuildCnt); + if (guildPlayerCntAvg < minRatio) return minRatio; + return guildPlayerCntAvg +} + +async function getPlayerCnt(serverId: number) { + + let serverRecord = await ServerRecordModel.findTodayData(serverId); + if(!serverRecord) return false; + + let activePlayerCnt = 50; // 前一天参与军团活动的玩家 + let activeGuildCnt = 5; // 前一天参与军团活动的军团 + let activePlayerCe = 0; // 前一天前十玩家的最强战力和 + let activeTopPlayerCnt = 1; // 前一天最强玩家数量 + let activePlayers: ActivePlayer[] = []; + if(serverRecord) { + if(serverRecord.activePlayerCe > 0) activePlayerCe = serverRecord.activePlayerCe; + if(serverRecord.activePlayers?.length > 0) { + activeTopPlayerCnt = serverRecord.activePlayers?.length; + activePlayers = serverRecord.activePlayers||[]; + } + if(serverRecord.activeGuildCodes?.length > 0) activeGuildCnt = serverRecord.activeGuildCodes?.length; + if(serverRecord.activeGuildMembers?.length > 0) activePlayerCnt = serverRecord.activeGuildMembers?.length; + } + return { activePlayerCnt, activeGuildCnt, activePlayerCe, activeTopPlayerCnt, activePlayers } +} + +export async function declareCity(serverId: number, roleId: string, guildCode: string, cityId: number, isAutoDeclare: boolean, declareIndex: number) { + let declareTime = Date.now(); + let declareInfo = await GuildActivityCityDeclareModel.declareIfNot(serverId, guildCode, cityId, roleId, declareTime, isAutoDeclare, declareIndex); + if(!!declareInfo && declareInfo.declareTime == declareTime) { // 确实没有人宣战过,自己是第一个 + let cityRec = await GuildActivityCityModel.declare(serverId, cityId, guildCode, declareIndex); + await GuildActivityRecordModel.updateInfo(guildCode, GUILD_ACTIVITY_TYPE.CITY_ACTIVITY, declareIndex, {}, cityId); + await sendGuildCityDeclare(serverId, cityId, guildCode, cityRec.declareCount); + return true; + } + return false; +} + +// 非军团长的团员自动宣战 +export async function autoDeclareMyCity(serverId: number, roleId: string, guildCode: string, declareIndex: number) { + let checkResult = await GuildActivityCityDeclareModel.checkDeclartion(serverId, guildCode, declareIndex); + if(checkResult) return false + + let cityIds = gameData.juniorCities; + let cities = await GuildActivityCityModel.findMinDeclareCountCity(serverId, cityIds, declareIndex); + let notDeclaredCitites = cityIds.filter(curCityId => { + return cities.findIndex(city => city.cityId == curCityId) == -1; + }); + let cityId = notDeclaredCitites.length > 0? getRandSingleEelm(notDeclaredCitites): cities[0].cityId; + if(!cityId) return false; + + return declareCity(serverId, roleId, guildCode, cityId, true, declareIndex); +} + +function getCounterName(aid: GUILD_ACTIVITY_TYPE) { + switch(aid) { + case GUILD_ACTIVITY_TYPE.GATE_ACTIVITY: + return COUNTER.GATE_ACTIVITY; + case GUILD_ACTIVITY_TYPE.CITY_ACTIVITY: + return COUNTER.CITY_ACTIVITY; + case GUILD_ACTIVITY_TYPE.RACE_ACTIVITY: + return COUNTER.RACE_ACTIVITY; + } +} + +export async function incCurGuildActivityIndex(aid: number) { + let name = getCounterName(aid); + let index = await CounterModel.getNewCounter(name); + setGuildActivityIndexInPinus(aid, index); // systime + pinus.app.rpc.guild.guildActivityRemote.setGuildActivityIndex.broadcast(aid, index); +} + +export async function initGuildActivityIndexInPinus() { + for(let aid = GUILD_ACTIVITY_TYPE.GATE_ACTIVITY; aid <= GUILD_ACTIVITY_TYPE.RACE_ACTIVITY; aid++){ + let index = await getCurGuildActivityIndexByDb(aid); + setGuildActivityIndexInPinus(aid, index); + } +} + +export async function getCurGuildActivityIndexByDb(aid: number) { + let name = getCounterName(aid); + return await CounterModel.getCounter(name); +} + +export function getGAPinusName(aid: number) { + return `guildact${aid}`; +} + +export function setGuildActivityIndexInPinus(aid: number, index: number) { + pinus.app.set(getGAPinusName(aid), index); +} + +export function getGAIndexInPinus(aid: number) { + return pinus.app.get(getGAPinusName(aid)); +} + +export function getDeclareIndex() { + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let obj = getCityActivityObj(); + if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) return index; + return index + 1; +} + +export function getJoinIndex() { + let index = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); + let obj = getRaceActivityObj(); + if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START || obj.getStatus() == GUILD_ACTIVITY_STATUS.END) return index; + return index + 1; +} + + +export async function resetJoinWoodenHorse() { + let obj = getRaceActivityObj(); + let joinIndex = getJoinIndex(); + + let guild = pinus.app.getServersByType('guild'); + let recs = await GuildActivityRecordModel.findRecs(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex); + for(let { serverId, guildCode, joinMember } of recs) { + let server = await dispatch(redisClient(), `${serverId}`, guild, 'guild'); + if(server.id != pinus.app.getServerId()) continue; + + for(let { roleId, roleName, job, code} of joinMember) { + let hasJoin = !!obj.getMember(guildCode, roleId); + if (hasJoin) continue; + await obj.joinWoodenHorse(guildCode, roleId, roleName, serverId, '', job, code); + } + } + return true +} + +export async function debugSendGateHp(serverId: number, cityId: number) { + let obj = getCityActivityObj(); + let { gateHp, maxHp } = await obj.getGateHpAndInc(serverId, cityId); + await sendMessageToCityWithSuc(serverId, cityId, PUSH_ROUTE.GUILD_CITY_ACT_HP, { cityId, gateHp: gateHp + 1000, maxHp }); +} + +export async function debugAddHorse(serverId: number, guildCode: string, memberCnt: number, itemInterval: number) { + + let obj = getRaceActivityObj(); + + let dicItem = gameData.raceTypes.get(RACE_EVENT_TYPE.DEFAULT); + let items: number[] = []; + for(let [_, arr] of dicItem) { + items.push(...arr); + }; + + for(let i = 0; i < memberCnt; i++) { + let roleId = `roleId${i}`; + await obj.joinWoodenHorse(guildCode, roleId, 'roleName', serverId, null, 6, 'code', true); + + } + + if(itemInterval >= 100) { + let members = obj.getMembersOfGuild(guildCode); + let timer = setInterval(async () => { + await obj.useItem(serverId, members[0]?.roleId, '', guildCode, guildCode, getRandSingleEelm(items), 1, true); + let woodenHorse = await obj.getWoodenHorse(guildCode, serverId, true); + if(woodenHorse.status == RACE_ACTIVITY_STATUS.END) { + clearInterval(timer); + } + }, itemInterval); + setTimeout(() => { + clearInterval(timer); + }, 10 * 60 * 1000); + } +} + +export async function leaveRaceActivity(serverId: number, guildCode: string, roleId: string ) { + if(!guildCode) return; + let obj = getRaceActivityObj(); + await obj.memberLeave(guildCode, serverId, roleId); +} + +export async function leaveRaceActivityToRemote(serverId: number, guildCode: string, roleId: string) { + let guildServers = pinus.app.getServersByType('guild')||[]; + let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); + if(server) { + await pinus.app.rpc.guild.guildActivityRemote.leaveRaceActivity.toServer(server.id, serverId, guildCode, roleId); + } +} + +export async function leaveRaceWhenQuitGuild(serverId: number, guildCode: string, roleId: string) { + if(!guildCode) return; + let obj = getRaceActivityObj(); + await obj.memberQuit(guildCode, serverId, roleId); + let joinIndex = getJoinIndex(); + await GuildActivityRecordModel.removeMember(guildCode, serverId, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex, roleId); +} + +export async function leaveRaceWhenQuitGuildToRemote(serverId: number, guildCode: string, roleId: string) { + let guildServers = pinus.app.getServersByType('guild')||[]; + let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); + if(server) { + await pinus.app.rpc.guild.guildActivityRemote.leaveRaceWhenQuitGuild.toServer(server.id, serverId, guildCode, roleId); + } + let index1 = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + let gateR = new Rank(REDIS_KEY.USER_GATE_ACTIVITY, { serverId, guildCode, index: index1 }, true); + gateR.removeFromRank({ roleId }); + + + let index2 = getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + let declareIndex = getDeclareIndex(); + + let obj = getCityActivityObj(); + if(obj.getStatus() == GUILD_ACTIVITY_STATUS.START) { + await autoDeclareMyCity(serverId, roleId, guildCode, declareIndex); + } + + let city = await GuildActivityCityDeclareModel.findDeclartion(serverId, guildCode, declareIndex) + if (city) { + let cityR = new Rank(REDIS_KEY.CITY_ACTIVITY, { serverId, cityId: city.cityId, index: index2 }, true); + cityR.removeFromRank({ roleId }); + } +} + +export async function leaveRaceWhenDismiss(guildCode: string, serverId: number) { + if(!guildCode) return; + let obj = getRaceActivityObj(); + obj.dismiss(guildCode); + let joinIndex = getJoinIndex(); + await GuildActivityRecordModel.dismiss(guildCode, serverId, GUILD_ACTIVITY_TYPE.RACE_ACTIVITY, joinIndex); +} + +export async function leaveRaceWhenDismissToRemote(serverId: number, guildCode: string) { + let guildServers = pinus.app.getServersByType('guild')||[]; + let server = await dispatch(redisClient(), `${serverId}`, guildServers, 'guild'); + if(server) { + await pinus.app.rpc.guild.guildActivityRemote.leaveRaceWhenDismiss.toServer(server.id, guildCode, serverId); + } +} diff --git a/game-server/app/services/guildActivity/raceActivityObj.ts b/game-server/app/services/guildActivity/raceActivityObj.ts index 69b2e9c7a..77c81baea 100644 --- a/game-server/app/services/guildActivity/raceActivityObj.ts +++ b/game-server/app/services/guildActivity/raceActivityObj.ts @@ -1,560 +1,560 @@ - -// 军团活动蛮夷入侵城门血量等数据存储 - -import { WoodenHorse, Event, WoodenHorseMember, RaceActivityRankParam, RaceActivityData, MemberInfo, GuildInfo } from "../../domain/battleField/guildActivity"; -import { getRaceEventItems, gameData } from "../../pubUtils/data"; -import { GuildModel } from "../../db/Guild"; -import { sendSingleRaceActEndMsg } from "./guildActivityService"; -import { RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, RACE_EVENT, PUSH_ROUTE, GUILD_ACTIVITY_STATUS, RACE_ACTIVITY_STATUS } from "../../consts"; -import { getRandEelm, sortArrRandom, getRandResultByMember } from "../../pubUtils/util"; -import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService"; -import { GUILDACTIVITY } from "../../pubUtils/dicParam"; - -// 粮草先行 -export class RaceActivityObject { - data: RaceActivityData = new RaceActivityData(); - - public getStatus() { - return this.data.status; - } - - public getItem(roleId: string) { - return this.data.items.get(roleId)||[] - } - - // 是否加入过 - public getMember(guildCode: string, roleId: string) { - let member = this.data.members.get(guildCode)||[]; - return member.find(cur => cur.roleId == roleId); - } - - public async updateMemberSid(guildCode: string, serverId: number, roleId: string, sid: string) { - let member = this.getMember(guildCode, roleId); - if(!member) return member; - let wh = await this.getWoodenHorse(guildCode, serverId); - let index = wh.members.findIndex(cur => cur.roleId == roleId); - if(index != -1) { - wh.members[index].updateSid(sid); - } - - return member - } - - public async memberLeave(guildCode: string, serverId: number, roleId: string) { - let member = this.getMember(guildCode, roleId); - if(!member) return member; - let wh = await this.getWoodenHorse(guildCode, serverId); - this.leaveMemberSid(wh, roleId); - - return member - } - - public async memberQuit(guildCode: string, serverId: number, roleId: string) { - let member = this.getMember(guildCode, roleId); - if(!member) return; - member.quit(); - let wh = await this.getWoodenHorse(guildCode, serverId); - this.leaveMemberSid(wh, roleId, true); - } - - public dismiss(guildCode: string) { - let guild = this.data.guildList.find(guild => guild.guildCode == guildCode); - if(!guild) return; - guild.dismiss(); - this.data.woodenHorses.delete(guildCode); - } - - // 加入member - private pushMember(guildCode: string, roleId: string, job: number, code: string) { - if(!this.data.members.has(guildCode)) { - this.data.members.set(guildCode, []); - } - this.data.members.get(guildCode).push(new MemberInfo(roleId, job, code)); - } - - public getGuilds() { - return this.data.guildList.filter(cur => !cur.isDissmiss); - } - - public getMembersOfGuild(guildCode: string) { - let members = this.data.members.get(guildCode)||[]; - return members.filter(cur => !cur.isQuit); - } - - public getAllWoodenHorses() { - return this.data.woodenHorses; - } - - public async getRanks(serverId: number, guildCode?: string) { - let myRank: RaceActivityRankParam = null; - let ranks: RaceActivityRankParam[] = []; - let myIndex = -1; - for(let [_, _wh] of this.data.woodenHorses) { - if(_wh.serverId == serverId && _wh.status != GUILD_ACTIVITY_STATUS.WAITING) { - let wh = await this.getWoodenHorse(_wh.guildCode, _wh.serverId); - if(wh) { - ranks.push(new RaceActivityRankParam(wh)); - } - } - } - ranks.sort((a, b) => { - if(a.sortDistance == b.sortDistance) { - return a.sortTime - b.sortTime; - } else { - return b.sortDistance - a.sortDistance; - } - }).map((wh, index) => { - wh.setRank(index + 1); - if(guildCode && wh.code == guildCode) { - myRank = wh; - myIndex = index; - } - return wh - }); - - if(!myRank && guildCode) { - let myWoodenHorse = await this.getWoodenHorse(guildCode, serverId); - if(myWoodenHorse) myRank = new RaceActivityRankParam(myWoodenHorse); - } - - return { guildRank: ranks, myGuildRank: myRank, myIndex } - } - - public async joinWoodenHorse(guildCode: string, roleId: string, roleName: string, serverId: number, sid: string, job: number, code: string, isDebug = false) { - let woodenHorse = await this.getWoodenHorse(guildCode, serverId, isDebug); - if(!woodenHorse) return false; - this.joinMember(woodenHorse, roleId, roleName, sid, code) - this.pushMember(guildCode, roleId, job, code); - - if(this.data.status == GUILD_ACTIVITY_STATUS.START) { - // this.sendRandItemsToMembers([member], woodenHorse, woodenHorse.remainItems); - this.woodenHorseStartRace(woodenHorse); - } - return await this.getWoodenHorse(guildCode, serverId); - } - - // 获取某个军团的木马状态 - public async getWoodenHorse(guildCode: string, serverId: number, isDebug: boolean = false) { - if(!this.data.woodenHorses.has(guildCode)) { - this.initEvents(guildCode); - if(isDebug) { - this.data.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildCode, 0, serverId, this.data.allStartTime, false)); - this.data.guildList.push(new GuildInfo(serverId, guildCode)); - } else { - let guild = await GuildModel.findByCode(guildCode, serverId); - if(!guild) return undefined; - let { name: guildName, guildCe } = guild; - this.data.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildName, guildCe, serverId, this.data.allStartTime, false)); - this.data.guildList.push(new GuildInfo(serverId, guildCode)); - } - } - let woodenHorse = this.data.woodenHorses.get(guildCode); - let events = this.data.events.get(guildCode)||[]; - let needSendEnd = this.calCurWoodenHorse(woodenHorse, events); - if (needSendEnd) { // 抵达后发送奖励,发送消息,结算 - await sendSingleRaceActEndMsg(guildCode, woodenHorse); - } - - this.handleItemsByWoodenHorse(woodenHorse); - return woodenHorse; - } - - public async useItem(serverId: number, fromRoleId: string, sid: string, fromGuild: string, toGuild: string, id: number, count: number, debug = false) { - if(!debug) { - let rec = this.handleItems(fromRoleId, sid, [{id, count: -1 * count}]); - if(!rec) return false; - } - let event = new Event(id, fromGuild, toGuild, count); - if(!this.data.events.has(toGuild)) { - this.data.events.set(toGuild, [event]); - } else { - let events = this.data.events.get(toGuild)||[]; - events.push(event); - this.data.events.set(toGuild, events); - } - let { guildRank, myGuildRank, myIndex } = await this.getRanks(serverId, toGuild); - if(myGuildRank) { - let ranks = this.getScreenHorseRanks(guildRank, myIndex); - for(let rank of ranks||[]) { - if(rank) await sendMessageToGuildWithSuc(rank.code, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] }); - } - let timeout = setTimeout(async () => { - await this.getScreenHorses(serverId, guildRank, myIndex, true); - clearTimeout(timeout); - }, event.startTime - Date.now()) - } else { - await sendMessageToGuildWithSuc(toGuild, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] }); - } - return event; - } - - // 定时任务到,开始比赛,设置开始赛道,发放初始道具 - public startRace() { - this.data.status = GUILD_ACTIVITY_STATUS.START; - if(this.data.allStartTime == 0) this.data.allStartTime = Date.now(); - let guildCodes = new Array(); - for(let [code, woodenHorse] of this.data.woodenHorses) { - if(woodenHorse.memberCnt > 0) { - this.woodenHorseStartRace(woodenHorse); - guildCodes.push(code); - } - } - return guildCodes; - } - - public stopRace() { - this.data.status = GUILD_ACTIVITY_STATUS.END; - for(let [_, woodenHorse] of this.data.woodenHorses) { - woodenHorse.status = RACE_ACTIVITY_STATUS.END; - } - } - - private woodenHorseStartRace(woodenHorse: WoodenHorse) { - woodenHorse.status = RACE_ACTIVITY_STATUS.START; - woodenHorse.time = Date.now(); - woodenHorse.startTime = Date.now(); - woodenHorse.allStartTime = this.data.allStartTime; - - let members = woodenHorse.members; - let normalItems = getRaceEventItems(); - this.sendRandItemsToMembers(members, woodenHorse, normalItems); - } - - private sendRandItemsToMembers(members: WoodenHorseMember[], woodenHorse: WoodenHorse, items: Map) { - let notReceiveMembers = members.filter(member => !member.isReceived() && member.isOnline); - let memberCnt = notReceiveMembers.length; - console.log('##### SEND_START', memberCnt, notReceiveMembers) - let addItems: Map = new Map(); - for(let [id, {total, max}] of items) { - let randResult = getRandResultByMember(total, max, memberCnt); - for(let i = 0; i < memberCnt; i++) { - let member = notReceiveMembers[i]; - let count = randResult.arr[i]||0; - if(count > 0) { - if(!addItems.has(member.roleId)) { - addItems.set(member.roleId, { member: member, items: [] }); - } - addItems.get(member.roleId).items.push({ id, count }); - } - } - this.setRemainItem(woodenHorse, id, randResult.remain, max); - } - for(let [_roleId, {member, items}] of addItems) { - member.setReceived(true); - this.handleItems(member.roleId, member.sid, items); - } - } - - // 初始进入就随机9个灵球事件 - public initEvents(guildCode: string) { - if(!this.data.events.get(guildCode)) { - this.data.events.set(guildCode, []); - } - let dicEncounter = gameData.raceActivityEncounter; // 距离=>事件类型 - let goodEventNum = Math.floor(dicEncounter.eventNum/2); - let badEventNum = dicEncounter.eventNum - goodEventNum; - - let dicRaceTypes = gameData.raceTypes.get(RACE_EVENT_TYPE.EVENT); - let goodEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.GOOD), goodEventNum); - let badEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.BAD), badEventNum); - let events = sortArrRandom(goodEvents.concat(badEvents)); - let index = 0; - - for(let [distance, type] of dicEncounter.events) { - if(type == RACE_EVENT_TYPE.ITEM) { - let event = new Event(RACE_EVENT.ITEM, guildCode, guildCode, 1, distance); - this.data.events.get(guildCode).push(event); - } else if (type == RACE_EVENT_TYPE.EVENT) { - let event = new Event(events[index], guildCode, guildCode, 1, distance); - this.data.events.get(guildCode).push(event); - index ++; - } - } - } - - public getEvents(guildCode: string, distance: number) { - let events = this.data.events.get(guildCode)||[]; - let result = new Array(); - for(let event of events) { - let { endTime, endDistance } = event; - if(!event.useDistance() && endTime) { - if(Date.now() > endTime) continue; - } - if(event.useDistance() && endDistance) { - if(distance > endDistance) continue; - } - result.push(event); - } - return result; - } - - private handleItemsByWoodenHorse(woodenHorse: WoodenHorse) { - let { members } = woodenHorse; - for(let curMember of members) { - let { roleId, sid, items = [] } = curMember; - if(items.length > 0) this.handleItems(roleId, sid, items); - curMember.items = []; - } - } - - private handleItems(roleId: string, sid: string, incItems: {id: number, count: number}[]) { - let items = this.data.items.get(roleId)||[]; - let sendItems = new Array<{id: number, count: number}>(); - for(let {id, count: inc} of incItems) { - let curItem = items.find(cur => cur.id == id); - if(!curItem) { - curItem = { id, count: 0 }; - items.push(curItem); - } - if(curItem.count + inc < 0 ) return false; - if(inc != 0) { - curItem.count += inc; - sendItems.push({ id, count: curItem.count }); - } - } - this.data.items.set(roleId, items); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.RACE_ITEM_UPDATE, { items: sendItems }, sid); - return items; - } - - public send(guildCode: string) { - this.data.hasSentGuild.push(guildCode); - } - - public hasSend(guildCode: string) { - return this.data.hasSentGuild.indexOf(guildCode) != -1; - } - - public async calServerHorses(serverId: number) { - let { guildRank: ranks } = await this.getRanks(serverId); - // 找到往前和往后2艘船 - for (let i = 0; i < ranks.length; i++) { - await this.getScreenHorses(serverId, ranks, i, true); - } - - } - - private getScreenHorseRanks(ranks: RaceActivityRankParam[], i: number) { - let curRank = ranks[i]; - if(!curRank || curRank.durability == 0) return; - - let beforeHorses: RaceActivityRankParam[] = [], afterHorses: RaceActivityRankParam[] = [], beforeCnt = 0, afterCnt = 0; - for(let j = i - 1; j >= 0; j--) { - if(ranks[j]) { - beforeHorses.push(ranks[j]); - if(ranks[j].durability > 0) beforeCnt ++ - } - if(beforeCnt >= 2) break; - } - for(let j = i + 1; j < ranks.length; j++) { - if(ranks[j]) { - afterHorses.push(ranks[j]); - if(ranks[j].durability > 0) afterCnt++; - } - if(afterCnt >= 2) break; - } - // 发送 - // console.log('send', woodenHorseList.length); - return [...beforeHorses.reverse(), curRank, ...afterHorses] - } - - private async getScreenHorses(serverId: number, ranks: RaceActivityRankParam[], i: number, needSend: boolean) { - let curRank = ranks[i]; - if(!curRank) return; - // 发送 - // console.log('send', woodenHorseList.length); - let wh = await this.getWoodenHorse(curRank.code, serverId); - let screenRank = this.getScreenHorseRanks(ranks, i); - let woodenHorseList: WoodenHorse[] = []; - if(curRank.durability != 0) { - for(let rank of screenRank) { - if(rank.code == curRank.code) { - woodenHorseList.push(wh); - } else { - let wh = await this.getWoodenHorse(rank.code, serverId); - woodenHorseList.push(wh); - } - } - } - - if(needSend) { - let events = this.getEvents(curRank.code, wh ? wh.distance : 0); - await sendMessageToGuildWithSuc(curRank.code, PUSH_ROUTE.GUILD_RACE_UPDATE, { timestamp: Date.now(), woodenHorseList, guildRank: ranks, myGuildRank: curRank, events }); - } - return woodenHorseList - } - - - /** - * 根据时间计算当前木马速度距离耐久等 - * @param events - * @returns {boolean} needSendEnd 是否跑到终点发送结束新号 - */ - public calCurWoodenHorse(woodenHorse: WoodenHorse, events: Event[]): boolean { - if(woodenHorse.status == RACE_ACTIVITY_STATUS.END) return false; - - if(woodenHorse.status == RACE_ACTIVITY_STATUS.START) { - if(woodenHorse.distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH) { - woodenHorse.distance = GUILDACTIVITY.RACEACTIVITY_LENGTH; - woodenHorse.status = RACE_ACTIVITY_STATUS.END; - woodenHorse.speed = 0; - return true; - } - - woodenHorse.distance = Math.floor((woodenHorse.distance + (Date.now() - woodenHorse.time)/1000 * woodenHorse.speed ) * 1000)/1000; // 1位小数点 - woodenHorse.time = Date.now(); - } - let effectiveEvents = new Array(); - for(let i = 0; i < events.length; i++) { - let event = events[i]; - if(event.useDistance() && event.startDistance && woodenHorse.distance > event.startDistance) { - let startTime = Date.now() - Math.floor((woodenHorse.distance - event.startDistance) / woodenHorse.speed); - event.setStartTime(startTime); // 距离生效的事件的实际生效时间,主要用于速度叠加顺序 - } - let isEffective = false; - if(event.useTime()) { - if(event.startTime <= Date.now() && event.endTime > Date.now()) { - isEffective = true; - } - if(event.endTime < Date.now()) { - if(event.endTime && event.startTime == event.endTime) { - isEffective = true; - } - let index = events.findIndex(cur => cur.id == event.id); - events.splice(index, 1); - } - } - if(event.useDistance()) { - if(event.startDistance <= woodenHorse.distance && event.endDistance > woodenHorse.distance) { - isEffective = true; - } - if(event.endDistance < woodenHorse.distance) { - if(event.endDistance && event.startDistance == event.endDistance) { - isEffective = true; - } - let index = events.findIndex(cur => cur.id == event.id); - events.splice(index, 1); - } - } - - if(isEffective) { - effectiveEvents.push(event); - } - } - - effectiveEvents.sort((a, b) => a.startTime - b.startTime); - woodenHorse.speed = GUILDACTIVITY.RACE_INIT_SPEED + woodenHorse.memberCnt * GUILDACTIVITY.RACE_PER_SPEED; - for(let { id, count, endTime } of effectiveEvents) { - this.calEvent(woodenHorse, id, count, endTime); - } - if(woodenHorse.durability <= 0) { - woodenHorse.status = RACE_ACTIVITY_STATUS.BREAK; - woodenHorse.speed = 0; - } - return false; - } - - private calEvent(woodenHorse: WoodenHorse, id: number, count: number = 1, endTime?: number) { - let { effect } = gameData.raceActivityEvents.get(id); - - switch (id) { - case RACE_EVENT.LIANNU: - if (woodenHorse.shieldTime < Date.now()) { - if (woodenHorse.shield >= count) { - woodenHorse.shield -= count; - } else { - woodenHorse.shield = 0; - woodenHorse.durability -= (count - woodenHorse.shield) * effect[0]; - if(woodenHorse.durability > 100) woodenHorse.durability = 100; - if(woodenHorse.durability < 0) woodenHorse.durability = 0; - } - } - break; - case RACE_EVENT.GUISHOUYINFU: - if (woodenHorse.shieldTime < Date.now()) { - woodenHorse.time = endTime; - woodenHorse.speed = effect[1]||0.1; - } - break; - case RACE_EVENT.FENGCHE: - case RACE_EVENT.WUGUIBANYUNFU: - woodenHorse.speed *= Math.pow(1 + effect[0] / 100, count); break; - case RACE_EVENT.LUDUN: - woodenHorse.shield += count * effect[0]; break; - case RACE_EVENT.TIANSHIDUNFU: - woodenHorse.shieldTime = endTime; break; - case RACE_EVENT.JIASU_1: - woodenHorse.speed *= Math.pow(1 + effect[0] / 100, count); break; - case RACE_EVENT.JIASU_2: - woodenHorse.speed += effect[0]; break; - case RACE_EVENT.HUIFU_1: - woodenHorse.durability += effect[0]; - if(woodenHorse.durability > 100) woodenHorse.durability = 100; - if(woodenHorse.durability < 0) woodenHorse.durability = 0; - break; - case RACE_EVENT.JIANSU_1: - woodenHorse.speed *= Math.pow(1 - effect[0] / 100, count); break; - case RACE_EVENT.JIANSU_2: - woodenHorse.speed -= effect[0]; - if(woodenHorse.speed < 0) woodenHorse.speed = 0; - break; - case RACE_EVENT.SHANGHAI_1: - woodenHorse.durability -= effect[0]; - if(woodenHorse.durability > 100) woodenHorse.durability = 100; - if(woodenHorse.durability < 0) woodenHorse.durability = 0; - break; - case RACE_EVENT.ITEM: - let onlineMembers = woodenHorse.members.filter(member => member.isOnline); - let memberCnt = onlineMembers.length; - console.log('##### HANDLE_ITEM', memberCnt, onlineMembers) - - let ranMember: WoodenHorseMember[] = getRandEelm(onlineMembers, GUILDACTIVITY.RACEACTIVITY_EVENT_MEMBERCNT); - if(ranMember.length <= 0) ranMember = onlineMembers; - for(let member of ranMember) { - let item = gameData.raceEventItems; - member.addTempItems(item); - } - let normalItems = getRaceEventItems(); - - for(let [id, {total, max}] of normalItems) { - let randResult = getRandResultByMember(total, max, memberCnt); - for(let i = 0; i < onlineMembers.length; i++) { - let count = randResult.arr[i]||0; - if(count > 0) { - onlineMembers[i].addTempItem({ id, count }); - normalItems.get(id).total -= count; - } - } - } - break; - } - } - - public joinMember(woodenHorse: WoodenHorse, roleId: string, roleName: string, sid: string, code: string) { - let index = woodenHorse.members.findIndex(cur => cur.roleId == roleId) - if(index == -1) { - let member = new WoodenHorseMember(roleId, roleName, sid, code); - woodenHorse.members.push(member); - woodenHorse.speed++; - woodenHorse.memberCnt++; - return member; - } else { - return woodenHorse.members[index]; - } - } - - public leaveMemberSid(woodenHorse: WoodenHorse, roleId: string, isQuit = false) { - let index = woodenHorse.members.findIndex(cur => cur.roleId == roleId); - if(index != -1) { - woodenHorse.members[index].leave(); - } - if(isQuit) woodenHorse.memberCnt--; - if(woodenHorse.memberCnt < 0) woodenHorse.memberCnt = 0; - } - - public setRemainItem(woodenHorse: WoodenHorse, id: number, remain: number, max: number) { - woodenHorse.remainItems.set(id, { total: remain, max }); - } - -} - + +// 军团活动蛮夷入侵城门血量等数据存储 + +import { WoodenHorse, Event, WoodenHorseMember, RaceActivityRankParam, RaceActivityData, MemberInfo, GuildInfo } from "@domain/battleField/guildActivity"; +import { getRaceEventItems, gameData } from "@pubUtils/data"; +import { GuildModel } from "@db/Guild"; +import { sendSingleRaceActEndMsg } from "./guildActivityService"; +import { RACE_EVENT_TYPE, RACE_EVENT_EFFECT_TYPE, RACE_EVENT, PUSH_ROUTE, GUILD_ACTIVITY_STATUS, RACE_ACTIVITY_STATUS } from "@consts"; +import { getRandEelm, sortArrRandom, getRandResultByMember } from "@pubUtils/util"; +import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService"; +import { GUILDACTIVITY } from "@pubUtils/dicParam"; + +// 粮草先行 +export class RaceActivityObject { + data: RaceActivityData = new RaceActivityData(); + + public getStatus() { + return this.data.status; + } + + public getItem(roleId: string) { + return this.data.items.get(roleId)||[] + } + + // 是否加入过 + public getMember(guildCode: string, roleId: string) { + let member = this.data.members.get(guildCode)||[]; + return member.find(cur => cur.roleId == roleId); + } + + public async updateMemberSid(guildCode: string, serverId: number, roleId: string, sid: string) { + let member = this.getMember(guildCode, roleId); + if(!member) return member; + let wh = await this.getWoodenHorse(guildCode, serverId); + let index = wh.members.findIndex(cur => cur.roleId == roleId); + if(index != -1) { + wh.members[index].updateSid(sid); + } + + return member + } + + public async memberLeave(guildCode: string, serverId: number, roleId: string) { + let member = this.getMember(guildCode, roleId); + if(!member) return member; + let wh = await this.getWoodenHorse(guildCode, serverId); + this.leaveMemberSid(wh, roleId); + + return member + } + + public async memberQuit(guildCode: string, serverId: number, roleId: string) { + let member = this.getMember(guildCode, roleId); + if(!member) return; + member.quit(); + let wh = await this.getWoodenHorse(guildCode, serverId); + this.leaveMemberSid(wh, roleId, true); + } + + public dismiss(guildCode: string) { + let guild = this.data.guildList.find(guild => guild.guildCode == guildCode); + if(!guild) return; + guild.dismiss(); + this.data.woodenHorses.delete(guildCode); + } + + // 加入member + private pushMember(guildCode: string, roleId: string, job: number, code: string) { + if(!this.data.members.has(guildCode)) { + this.data.members.set(guildCode, []); + } + this.data.members.get(guildCode).push(new MemberInfo(roleId, job, code)); + } + + public getGuilds() { + return this.data.guildList.filter(cur => !cur.isDissmiss); + } + + public getMembersOfGuild(guildCode: string) { + let members = this.data.members.get(guildCode)||[]; + return members.filter(cur => !cur.isQuit); + } + + public getAllWoodenHorses() { + return this.data.woodenHorses; + } + + public async getRanks(serverId: number, guildCode?: string) { + let myRank: RaceActivityRankParam = null; + let ranks: RaceActivityRankParam[] = []; + let myIndex = -1; + for(let [_, _wh] of this.data.woodenHorses) { + if(_wh.serverId == serverId && _wh.status != GUILD_ACTIVITY_STATUS.WAITING) { + let wh = await this.getWoodenHorse(_wh.guildCode, _wh.serverId); + if(wh) { + ranks.push(new RaceActivityRankParam(wh)); + } + } + } + ranks.sort((a, b) => { + if(a.sortDistance == b.sortDistance) { + return a.sortTime - b.sortTime; + } else { + return b.sortDistance - a.sortDistance; + } + }).map((wh, index) => { + wh.setRank(index + 1); + if(guildCode && wh.code == guildCode) { + myRank = wh; + myIndex = index; + } + return wh + }); + + if(!myRank && guildCode) { + let myWoodenHorse = await this.getWoodenHorse(guildCode, serverId); + if(myWoodenHorse) myRank = new RaceActivityRankParam(myWoodenHorse); + } + + return { guildRank: ranks, myGuildRank: myRank, myIndex } + } + + public async joinWoodenHorse(guildCode: string, roleId: string, roleName: string, serverId: number, sid: string, job: number, code: string, isDebug = false) { + let woodenHorse = await this.getWoodenHorse(guildCode, serverId, isDebug); + if(!woodenHorse) return false; + this.joinMember(woodenHorse, roleId, roleName, sid, code) + this.pushMember(guildCode, roleId, job, code); + + if(this.data.status == GUILD_ACTIVITY_STATUS.START) { + // this.sendRandItemsToMembers([member], woodenHorse, woodenHorse.remainItems); + this.woodenHorseStartRace(woodenHorse); + } + return await this.getWoodenHorse(guildCode, serverId); + } + + // 获取某个军团的木马状态 + public async getWoodenHorse(guildCode: string, serverId: number, isDebug: boolean = false) { + if(!this.data.woodenHorses.has(guildCode)) { + this.initEvents(guildCode); + if(isDebug) { + this.data.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildCode, 0, serverId, this.data.allStartTime, false)); + this.data.guildList.push(new GuildInfo(serverId, guildCode)); + } else { + let guild = await GuildModel.findByCode(guildCode, serverId); + if(!guild) return undefined; + let { name: guildName, guildCe } = guild; + this.data.woodenHorses.set(guildCode, new WoodenHorse(guildCode, guildName, guildCe, serverId, this.data.allStartTime, false)); + this.data.guildList.push(new GuildInfo(serverId, guildCode)); + } + } + let woodenHorse = this.data.woodenHorses.get(guildCode); + let events = this.data.events.get(guildCode)||[]; + let needSendEnd = this.calCurWoodenHorse(woodenHorse, events); + if (needSendEnd) { // 抵达后发送奖励,发送消息,结算 + await sendSingleRaceActEndMsg(guildCode, woodenHorse); + } + + this.handleItemsByWoodenHorse(woodenHorse); + return woodenHorse; + } + + public async useItem(serverId: number, fromRoleId: string, sid: string, fromGuild: string, toGuild: string, id: number, count: number, debug = false) { + if(!debug) { + let rec = this.handleItems(fromRoleId, sid, [{id, count: -1 * count}]); + if(!rec) return false; + } + let event = new Event(id, fromGuild, toGuild, count); + if(!this.data.events.has(toGuild)) { + this.data.events.set(toGuild, [event]); + } else { + let events = this.data.events.get(toGuild)||[]; + events.push(event); + this.data.events.set(toGuild, events); + } + let { guildRank, myGuildRank, myIndex } = await this.getRanks(serverId, toGuild); + if(myGuildRank) { + let ranks = this.getScreenHorseRanks(guildRank, myIndex); + for(let rank of ranks||[]) { + if(rank) await sendMessageToGuildWithSuc(rank.code, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] }); + } + let timeout = setTimeout(async () => { + await this.getScreenHorses(serverId, guildRank, myIndex, true); + clearTimeout(timeout); + }, event.startTime - Date.now()) + } else { + await sendMessageToGuildWithSuc(toGuild, PUSH_ROUTE.GUILD_RACE_EVENT, { timestamp: Date.now(), events: [event] }); + } + return event; + } + + // 定时任务到,开始比赛,设置开始赛道,发放初始道具 + public startRace() { + this.data.status = GUILD_ACTIVITY_STATUS.START; + if(this.data.allStartTime == 0) this.data.allStartTime = Date.now(); + let guildCodes = new Array(); + for(let [code, woodenHorse] of this.data.woodenHorses) { + if(woodenHorse.memberCnt > 0) { + this.woodenHorseStartRace(woodenHorse); + guildCodes.push(code); + } + } + return guildCodes; + } + + public stopRace() { + this.data.status = GUILD_ACTIVITY_STATUS.END; + for(let [_, woodenHorse] of this.data.woodenHorses) { + woodenHorse.status = RACE_ACTIVITY_STATUS.END; + } + } + + private woodenHorseStartRace(woodenHorse: WoodenHorse) { + woodenHorse.status = RACE_ACTIVITY_STATUS.START; + woodenHorse.time = Date.now(); + woodenHorse.startTime = Date.now(); + woodenHorse.allStartTime = this.data.allStartTime; + + let members = woodenHorse.members; + let normalItems = getRaceEventItems(); + this.sendRandItemsToMembers(members, woodenHorse, normalItems); + } + + private sendRandItemsToMembers(members: WoodenHorseMember[], woodenHorse: WoodenHorse, items: Map) { + let notReceiveMembers = members.filter(member => !member.isReceived() && member.isOnline); + let memberCnt = notReceiveMembers.length; + console.log('##### SEND_START', memberCnt, notReceiveMembers) + let addItems: Map = new Map(); + for(let [id, {total, max}] of items) { + let randResult = getRandResultByMember(total, max, memberCnt); + for(let i = 0; i < memberCnt; i++) { + let member = notReceiveMembers[i]; + let count = randResult.arr[i]||0; + if(count > 0) { + if(!addItems.has(member.roleId)) { + addItems.set(member.roleId, { member: member, items: [] }); + } + addItems.get(member.roleId).items.push({ id, count }); + } + } + this.setRemainItem(woodenHorse, id, randResult.remain, max); + } + for(let [_roleId, {member, items}] of addItems) { + member.setReceived(true); + this.handleItems(member.roleId, member.sid, items); + } + } + + // 初始进入就随机9个灵球事件 + public initEvents(guildCode: string) { + if(!this.data.events.get(guildCode)) { + this.data.events.set(guildCode, []); + } + let dicEncounter = gameData.raceActivityEncounter; // 距离=>事件类型 + let goodEventNum = Math.floor(dicEncounter.eventNum/2); + let badEventNum = dicEncounter.eventNum - goodEventNum; + + let dicRaceTypes = gameData.raceTypes.get(RACE_EVENT_TYPE.EVENT); + let goodEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.GOOD), goodEventNum); + let badEvents = getRandEelm(dicRaceTypes.get(RACE_EVENT_EFFECT_TYPE.BAD), badEventNum); + let events = sortArrRandom(goodEvents.concat(badEvents)); + let index = 0; + + for(let [distance, type] of dicEncounter.events) { + if(type == RACE_EVENT_TYPE.ITEM) { + let event = new Event(RACE_EVENT.ITEM, guildCode, guildCode, 1, distance); + this.data.events.get(guildCode).push(event); + } else if (type == RACE_EVENT_TYPE.EVENT) { + let event = new Event(events[index], guildCode, guildCode, 1, distance); + this.data.events.get(guildCode).push(event); + index ++; + } + } + } + + public getEvents(guildCode: string, distance: number) { + let events = this.data.events.get(guildCode)||[]; + let result = new Array(); + for(let event of events) { + let { endTime, endDistance } = event; + if(!event.useDistance() && endTime) { + if(Date.now() > endTime) continue; + } + if(event.useDistance() && endDistance) { + if(distance > endDistance) continue; + } + result.push(event); + } + return result; + } + + private handleItemsByWoodenHorse(woodenHorse: WoodenHorse) { + let { members } = woodenHorse; + for(let curMember of members) { + let { roleId, sid, items = [] } = curMember; + if(items.length > 0) this.handleItems(roleId, sid, items); + curMember.items = []; + } + } + + private handleItems(roleId: string, sid: string, incItems: {id: number, count: number}[]) { + let items = this.data.items.get(roleId)||[]; + let sendItems = new Array<{id: number, count: number}>(); + for(let {id, count: inc} of incItems) { + let curItem = items.find(cur => cur.id == id); + if(!curItem) { + curItem = { id, count: 0 }; + items.push(curItem); + } + if(curItem.count + inc < 0 ) return false; + if(inc != 0) { + curItem.count += inc; + sendItems.push({ id, count: curItem.count }); + } + } + this.data.items.set(roleId, items); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.RACE_ITEM_UPDATE, { items: sendItems }, sid); + return items; + } + + public send(guildCode: string) { + this.data.hasSentGuild.push(guildCode); + } + + public hasSend(guildCode: string) { + return this.data.hasSentGuild.indexOf(guildCode) != -1; + } + + public async calServerHorses(serverId: number) { + let { guildRank: ranks } = await this.getRanks(serverId); + // 找到往前和往后2艘船 + for (let i = 0; i < ranks.length; i++) { + await this.getScreenHorses(serverId, ranks, i, true); + } + + } + + private getScreenHorseRanks(ranks: RaceActivityRankParam[], i: number) { + let curRank = ranks[i]; + if(!curRank || curRank.durability == 0) return; + + let beforeHorses: RaceActivityRankParam[] = [], afterHorses: RaceActivityRankParam[] = [], beforeCnt = 0, afterCnt = 0; + for(let j = i - 1; j >= 0; j--) { + if(ranks[j]) { + beforeHorses.push(ranks[j]); + if(ranks[j].durability > 0) beforeCnt ++ + } + if(beforeCnt >= 2) break; + } + for(let j = i + 1; j < ranks.length; j++) { + if(ranks[j]) { + afterHorses.push(ranks[j]); + if(ranks[j].durability > 0) afterCnt++; + } + if(afterCnt >= 2) break; + } + // 发送 + // console.log('send', woodenHorseList.length); + return [...beforeHorses.reverse(), curRank, ...afterHorses] + } + + private async getScreenHorses(serverId: number, ranks: RaceActivityRankParam[], i: number, needSend: boolean) { + let curRank = ranks[i]; + if(!curRank) return; + // 发送 + // console.log('send', woodenHorseList.length); + let wh = await this.getWoodenHorse(curRank.code, serverId); + let screenRank = this.getScreenHorseRanks(ranks, i); + let woodenHorseList: WoodenHorse[] = []; + if(curRank.durability != 0) { + for(let rank of screenRank) { + if(rank.code == curRank.code) { + woodenHorseList.push(wh); + } else { + let wh = await this.getWoodenHorse(rank.code, serverId); + woodenHorseList.push(wh); + } + } + } + + if(needSend) { + let events = this.getEvents(curRank.code, wh ? wh.distance : 0); + await sendMessageToGuildWithSuc(curRank.code, PUSH_ROUTE.GUILD_RACE_UPDATE, { timestamp: Date.now(), woodenHorseList, guildRank: ranks, myGuildRank: curRank, events }); + } + return woodenHorseList + } + + + /** + * 根据时间计算当前木马速度距离耐久等 + * @param events + * @returns {boolean} needSendEnd 是否跑到终点发送结束新号 + */ + public calCurWoodenHorse(woodenHorse: WoodenHorse, events: Event[]): boolean { + if(woodenHorse.status == RACE_ACTIVITY_STATUS.END) return false; + + if(woodenHorse.status == RACE_ACTIVITY_STATUS.START) { + if(woodenHorse.distance >= GUILDACTIVITY.RACEACTIVITY_LENGTH) { + woodenHorse.distance = GUILDACTIVITY.RACEACTIVITY_LENGTH; + woodenHorse.status = RACE_ACTIVITY_STATUS.END; + woodenHorse.speed = 0; + return true; + } + + woodenHorse.distance = Math.floor((woodenHorse.distance + (Date.now() - woodenHorse.time)/1000 * woodenHorse.speed ) * 1000)/1000; // 1位小数点 + woodenHorse.time = Date.now(); + } + let effectiveEvents = new Array(); + for(let i = 0; i < events.length; i++) { + let event = events[i]; + if(event.useDistance() && event.startDistance && woodenHorse.distance > event.startDistance) { + let startTime = Date.now() - Math.floor((woodenHorse.distance - event.startDistance) / woodenHorse.speed); + event.setStartTime(startTime); // 距离生效的事件的实际生效时间,主要用于速度叠加顺序 + } + let isEffective = false; + if(event.useTime()) { + if(event.startTime <= Date.now() && event.endTime > Date.now()) { + isEffective = true; + } + if(event.endTime < Date.now()) { + if(event.endTime && event.startTime == event.endTime) { + isEffective = true; + } + let index = events.findIndex(cur => cur.id == event.id); + events.splice(index, 1); + } + } + if(event.useDistance()) { + if(event.startDistance <= woodenHorse.distance && event.endDistance > woodenHorse.distance) { + isEffective = true; + } + if(event.endDistance < woodenHorse.distance) { + if(event.endDistance && event.startDistance == event.endDistance) { + isEffective = true; + } + let index = events.findIndex(cur => cur.id == event.id); + events.splice(index, 1); + } + } + + if(isEffective) { + effectiveEvents.push(event); + } + } + + effectiveEvents.sort((a, b) => a.startTime - b.startTime); + woodenHorse.speed = GUILDACTIVITY.RACE_INIT_SPEED + woodenHorse.memberCnt * GUILDACTIVITY.RACE_PER_SPEED; + for(let { id, count, endTime } of effectiveEvents) { + this.calEvent(woodenHorse, id, count, endTime); + } + if(woodenHorse.durability <= 0) { + woodenHorse.status = RACE_ACTIVITY_STATUS.BREAK; + woodenHorse.speed = 0; + } + return false; + } + + private calEvent(woodenHorse: WoodenHorse, id: number, count: number = 1, endTime?: number) { + let { effect } = gameData.raceActivityEvents.get(id); + + switch (id) { + case RACE_EVENT.LIANNU: + if (woodenHorse.shieldTime < Date.now()) { + if (woodenHorse.shield >= count) { + woodenHorse.shield -= count; + } else { + woodenHorse.shield = 0; + woodenHorse.durability -= (count - woodenHorse.shield) * effect[0]; + if(woodenHorse.durability > 100) woodenHorse.durability = 100; + if(woodenHorse.durability < 0) woodenHorse.durability = 0; + } + } + break; + case RACE_EVENT.GUISHOUYINFU: + if (woodenHorse.shieldTime < Date.now()) { + woodenHorse.time = endTime; + woodenHorse.speed = effect[1]||0.1; + } + break; + case RACE_EVENT.FENGCHE: + case RACE_EVENT.WUGUIBANYUNFU: + woodenHorse.speed *= Math.pow(1 + effect[0] / 100, count); break; + case RACE_EVENT.LUDUN: + woodenHorse.shield += count * effect[0]; break; + case RACE_EVENT.TIANSHIDUNFU: + woodenHorse.shieldTime = endTime; break; + case RACE_EVENT.JIASU_1: + woodenHorse.speed *= Math.pow(1 + effect[0] / 100, count); break; + case RACE_EVENT.JIASU_2: + woodenHorse.speed += effect[0]; break; + case RACE_EVENT.HUIFU_1: + woodenHorse.durability += effect[0]; + if(woodenHorse.durability > 100) woodenHorse.durability = 100; + if(woodenHorse.durability < 0) woodenHorse.durability = 0; + break; + case RACE_EVENT.JIANSU_1: + woodenHorse.speed *= Math.pow(1 - effect[0] / 100, count); break; + case RACE_EVENT.JIANSU_2: + woodenHorse.speed -= effect[0]; + if(woodenHorse.speed < 0) woodenHorse.speed = 0; + break; + case RACE_EVENT.SHANGHAI_1: + woodenHorse.durability -= effect[0]; + if(woodenHorse.durability > 100) woodenHorse.durability = 100; + if(woodenHorse.durability < 0) woodenHorse.durability = 0; + break; + case RACE_EVENT.ITEM: + let onlineMembers = woodenHorse.members.filter(member => member.isOnline); + let memberCnt = onlineMembers.length; + console.log('##### HANDLE_ITEM', memberCnt, onlineMembers) + + let ranMember: WoodenHorseMember[] = getRandEelm(onlineMembers, GUILDACTIVITY.RACEACTIVITY_EVENT_MEMBERCNT); + if(ranMember.length <= 0) ranMember = onlineMembers; + for(let member of ranMember) { + let item = gameData.raceEventItems; + member.addTempItems(item); + } + let normalItems = getRaceEventItems(); + + for(let [id, {total, max}] of normalItems) { + let randResult = getRandResultByMember(total, max, memberCnt); + for(let i = 0; i < onlineMembers.length; i++) { + let count = randResult.arr[i]||0; + if(count > 0) { + onlineMembers[i].addTempItem({ id, count }); + normalItems.get(id).total -= count; + } + } + } + break; + } + } + + public joinMember(woodenHorse: WoodenHorse, roleId: string, roleName: string, sid: string, code: string) { + let index = woodenHorse.members.findIndex(cur => cur.roleId == roleId) + if(index == -1) { + let member = new WoodenHorseMember(roleId, roleName, sid, code); + woodenHorse.members.push(member); + woodenHorse.speed++; + woodenHorse.memberCnt++; + return member; + } else { + return woodenHorse.members[index]; + } + } + + public leaveMemberSid(woodenHorse: WoodenHorse, roleId: string, isQuit = false) { + let index = woodenHorse.members.findIndex(cur => cur.roleId == roleId); + if(index != -1) { + woodenHorse.members[index].leave(); + } + if(isQuit) woodenHorse.memberCnt--; + if(woodenHorse.memberCnt < 0) woodenHorse.memberCnt = 0; + } + + public setRemainItem(woodenHorse: WoodenHorse, id: number, remain: number, max: number) { + woodenHorse.remainItems.set(id, { total: remain, max }); + } + +} + diff --git a/game-server/app/services/guildBossService.ts b/game-server/app/services/guildBossService.ts index 492df9472..c4046d3a5 100644 --- a/game-server/app/services/guildBossService.ts +++ b/game-server/app/services/guildBossService.ts @@ -1,283 +1,283 @@ -import { BossInstanceType, BossInstanceModel } from '../db/BossInstance'; -import { lockData } from '../services/redLockService'; -import { findIndex, pick } from 'underscore'; -import { sismemberAsync, smembersAsync, saddAsync, delAsync, getRoleOnlineInfo, getServerCreateTime } from '../services/redisService'; -import { pinus } from 'pinus'; -import { STATUS } from '../consts/statusCode'; -import { resResult, shouldRefresh } from '../pubUtils/util'; -import { BattleRecordModel } from '../db/BattleRecord'; -import { getArmyBossRank, gameData, getBossHpRatio } from '../pubUtils/data'; -import { sendMailToGuildByContent } from '../services/mailService'; -import { MAIL_TYPE, AUCTION_SOURCE, ABI_TYPE, PUSH_ROUTE, BOSS_HP_RATIO_TYPE } from '../consts'; -import { GUILD_BOSS_STATUS } from '../consts/constModules/guildConst'; -import { genAuction } from './auctionService'; -import { GuildModel, GuildType } from '../db/Guild'; -import { UserGuildModel, UserGuildType } from '../db/UserGuild'; -import { getZeroPoint, getZeroPointOfTime, nowSeconds } from '../pubUtils/timeUtil'; -import { GUILDACTIVITY } from '../pubUtils/dicParam'; -import { GuildRecord, ServerRecordModel } from '../db/ServerRecords'; -import { sendMessageToGuildWithSuc, sendMessageToUsersWithSuc } from './pushService'; -import { AttributeCal } from '../domain/roleField/attribute'; -import { saveGuildBossHpLog } from '../pubUtils/logUtil'; -import { getHeroesAttributes } from './playerCeService'; - -/** - * 获得boss界面 - * @param bossInstance - * @param roleId - */ -export async function getBossInstanceInfo(userGuild: UserGuildType, guild?: GuildType) { - let bossInstance = await BossInstanceModel.findBossInstance(userGuild.guildCode); - - if(!bossInstance) { - bossInstance = await BossInstanceModel.findLastOverBossInstance(userGuild.guildCode); - } - return await getBossInstanceInfoByData(bossInstance, userGuild, guild); -} - -export async function getBossInstanceInfoByData(bossInstance: BossInstanceType, userGuild: UserGuildType, guild?: GuildType) { - if(!guild) guild = await GuildModel.findByCode(userGuild.guildCode, null, 'code refOpenBossTime openBossCnt'); - - let refObj = await getRefBossCnt(guild, userGuild); // 刷新次数 - let status = bossInstance? bossInstance.status: GUILD_BOSS_STATUS.WAIT_OPEN; - if(status == GUILD_BOSS_STATUS.CLEAR) status = GUILD_BOSS_STATUS.WAIT_OPEN; - let bossInfo = null; - - if(bossInstance) { - let { code, warId, ranks, bossHp, bossTotalHp, ratio, bossLv, encourageCnt } = bossInstance; - let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); - let rankInfo = getRanks(ranks, userGuild.roleId); - bossInfo = { bossCode: code, warId, ...rankInfo, bossHp: zoomOutDamage(bossHp), bossTotalHp: zoomOutDamage(bossTotalHp), bossLv, encourageCnt, encourageMax: dicBossBase.encourageSum, ratio }; - } - return { status, bossInfo, ...refObj } -} - -export async function pushBossStatus(guildCode: string, result: any) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_BOSS_OPEN, pick(result, ['status', 'bossInfo', 'leaderOpenCnt'])); -} - -async function getRefBossCnt(guild: GuildType, userGuild: UserGuildType) { - let guildCnt = await refreshGuildOfBoss(guild); - let userGuildCnt = await refreshUserGuildOfBoss(userGuild); - return { ...guildCnt, ...userGuildCnt } -} - -export async function refreshGuildOfBoss(guild: GuildType, inc: number = 0) { - let { refOpenBossTime, openBossCnt, code } = guild; - if(shouldRefresh(refOpenBossTime, new Date())) { - openBossCnt = 0; - } - if(inc != 0) { - guild = await GuildModel.updateInfo(code, { refOpenBossTime: new Date(), openBossCnt: openBossCnt + inc }); - openBossCnt = guild.openBossCnt; - } - return { leaderOpenCnt: openBossCnt } -} -export async function refreshUserGuildOfBoss(userGuild: UserGuildType, incEncourage = 0, incChallenge = 0) { - let { refBossTime, encourageCnt, bossChallengeCnt } = userGuild; - if(shouldRefresh(refBossTime, new Date())) { - encourageCnt = 0, bossChallengeCnt = 0; - } - if(incEncourage != 0 || incChallenge != 0) { - userGuild = await UserGuildModel.updateInfo(userGuild.roleId, { refBossTime: new Date(), encourageCnt: encourageCnt + incEncourage, bossChallengeCnt: bossChallengeCnt + incChallenge }, {}); - encourageCnt = userGuild.encourageCnt; - bossChallengeCnt = userGuild.bossChallengeCnt; - } - return { myChallengeCnt: bossChallengeCnt, myEncourageCnt: encourageCnt } - -} - -export function getRanks(ranks: {roleId: string; score: number; time: number; job: number;}[], roleId: string ) { - ranks.sort(function(a, b) { - return b.score - a.score + a.time - b.time; - }); - - let myRank = {}; - let lastRanks = ranks.map(({roleId: battleRoleId, score }, index) => { - if (roleId == battleRoleId) { - myRank = { roleId, score: zoomOutDamageWithoutRadix(score), rankLv: index + 1 }; - } - return {roleId: battleRoleId, score: zoomOutDamageWithoutRadix(score), rankLv: index + 1}; - }); - return { ranks: lastRanks, myRank } -} - -/** - * 获得排名区间奖励 - * @param rankLv - */ -export function getArmyBossRankReward(rankLv: number) { - let armybossRankReward = getArmyBossRank(); - for (let item of armybossRankReward) { - if (item.rankMin <= rankLv && (rankLv <= item.rankMax || item.rankMax == -1)) { - return item.reward; - } - } -} - /** - * 将玩家加入到正在挑战boss队列中 - * @param code - * @param serverId - * @param roleId - */ -export async function addBossInstance(code: string, serverId:number, roleId: string) { - let hisOnlineInfo = await getRoleOnlineInfo(roleId); - if(hisOnlineInfo.isOnline) { - let key = 'serverId_' + serverId + 'guildCode_' + code; - let value = roleId+ '|' + hisOnlineInfo.sid; - await saddAsync(key, [value]); - } -} - -/** - * 给当前正在挑战的玩家下发血量同步信息 - * @param code - * @param serverId - * @param bossHp - * @param isDelKey - */ -export async function pushBossHpMessage(code: string, serverId:number, bossHp:number, isDelKey?: boolean ) { - let key = 'serverId_' + serverId + 'guildCode_' + code; - let members = await smembersAsync(key); - let uids = members.map(member=>{ - let arr = member.split('|'); - let uid = arr[0]; - let sid = arr[1]; - return {uid, sid}; - }); - sendMessageToUsersWithSuc(PUSH_ROUTE.BOSS_HP_UPDATE, { bossHp: zoomOutDamage(bossHp) }, uids); - if (isDelKey) { - delAsync(key); - } -} -/** - * 检查该玩家当前是否正在挑战boss的队列中 - * @param code - * @param serverId - * @param roleId - * @param battleCode - */ -export async function checkBossBattleMemberExists(code: string, serverId:number, roleId: string, battleCode:string ) { - let hisOnlineInfo = await getRoleOnlineInfo(roleId); - let key = 'serverId_' + serverId + 'guildCode_' + code ; - let value = roleId+ '|' + hisOnlineInfo.sid; - let flag = await sismemberAsync(key, value); - if (!flag) { - const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); - if(!battleRecord || battleRecord.status != 0 || roleId != battleRecord.roleId) { - return false; - } - await addBossInstance(code, serverId, roleId); - flag = true; - } - return flag; -} -/** - * 成员退出,删除boss关排行信息 - * @param guildCode - * @param roleId - */ -export async function removeBossRank(guildCode: string, roleId: string) { - await BossInstanceModel.removeBossRank(guildCode, roleId); -} - -function getBossSubAttrCe(hid: number, secondAttrLevel: number, bossLevel: number) { - let newAttribute = new AttributeCal(); - newAttribute.setLv(bossLevel); - let subAttr = gameData.towerPvpSubAttr.get(secondAttrLevel); - if(subAttr) newAttribute.setByWarJson(hid, subAttr.secondAtr); - let newCe = newAttribute.calCe(); - return newCe; -} - -export async function getBossHp(serverId: number, guildCode: string, dicBossBaseWar: {warId: number, bossHp: number, bossHpRatio: number }, bossLv: number) { - let { warId, bossHp: minBossHp, bossHpRatio } = dicBossBaseWar; - console.log('getBossHp', warId, minBossHp, bossHpRatio) - - let serverRecord = await ServerRecordModel.findTodayData(serverId); - if(!serverRecord) return { ratio: 1, bossHp: zoomInDamage(minBossHp) }; - - let activeGuilds = serverRecord.activeGuilds||[]; - let myGuild = activeGuilds.find(cur => cur.guildCode == guildCode); - - let playerAtkResult = await getPlayerAtkAvg(myGuild); - if (!playerAtkResult) return { ratio: 1, bossHp: zoomInDamage(minBossHp) }; - // *军团的玩家人数=开启前一天军团内登录的玩家数 - // *单个玩家的平均攻击力=军团前一天活跃玩家中最强6人排名前10的玩家的最强6人的攻击之和/10 - let { playerAtkAvg, playerCnt, activeCe, activePlayerCnt, playerAtkSum } = playerAtkResult; - // 倍数按开服天数变化 - let ratio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.BOSS_RATIO, serverId); - // *单个玩家10回合造成的总伤害=单个玩家的平均攻击力*倍数*10 - let player10Damage = playerAtkAvg * ratio * 10; - // boss血量=单个玩家10回合造成的总伤害*军团的玩家人数*2 - let bossHp = Math.floor(player10Damage * activePlayerCnt * 2); - let B = getB(warId, bossLv, activeCe, playerCnt); - if(B < 1) { - B = 1; - bossHp = minBossHp; - } - if(bossHp < minBossHp) { - B = 1; - bossHp = minBossHp; - } - saveGuildBossHpLog(serverId, warId, guildCode, { minBossHp, bossHpRatio, ratio, playerAtkAvg, player10Damage, activeCe, activePlayerCnt, playerAtkSum, playerCnt, B, bossHp }) - return { ratio: B, bossHp: zoomInDamage(bossHp) }; -} - -function getB(warId: number, bossLv: number, activeCe: number, playerCnt: number) { - let dicWar = gameData.war.get(warId); - if (!dicWar) return 1; - let actorId = gameData.heroIdByWar.get(warId); - - let subCe = getBossSubAttrCe(actorId, dicWar.secondAttrLevel, bossLv) - let B = (activeCe/playerCnt/6 - subCe)/GUILDACTIVITY.GATEACTIVITY_ENEMYCE; - return B; -} - -async function getPlayerAtkAvg(myGuild: GuildRecord) { - if (!myGuild) return false; - let playerAtkSum = 0, playerCnt = 0, activeCe = 0, activePlayerCnt = 0; - if (myGuild) { - let activePlayers = myGuild.players || []; - activePlayerCnt = activePlayers.length; - activePlayers.sort((a, b) => b.ce - a.ce); - for (let i = 0; i < 10; i++) { - if (!activePlayers[i]) break; - let onePlayerAtkSum = 0, heroCnt = 0; - let { roleId, topLineup = [], topLineupCe = 0 } = activePlayers[i]; - let attrByHid = await getHeroesAttributes(roleId); - for (let { hid } of topLineup) { - let atk = attrByHid.get(hid)?.getAtk() || 0; - onePlayerAtkSum += atk; - heroCnt++; - } - if (heroCnt == 0) continue; // 基本不可能,但是以防NaN - playerAtkSum += onePlayerAtkSum / heroCnt * 6; - activeCe += topLineupCe; - playerCnt ++; - } - } - if (playerCnt == 0) return false; - let playerAtkAvg = playerAtkSum / playerCnt; - return { playerAtkAvg, playerCnt, activeCe, activePlayerCnt, playerAtkSum }; -} - -export async function getBossHpRatioByServer(type: BOSS_HP_RATIO_TYPE, serverId: number) { - let serverOpenTime = await getServerCreateTime(serverId); - let serverZeroPoint = getZeroPointOfTime(serverOpenTime); - let todayZeroPoint = getZeroPoint(); - let n = Math.floor((todayZeroPoint - serverZeroPoint)/86400) + 1; - return getBossHpRatio(type, n); -} - -export function zoomInDamage(damage: number, ratio = 100) { - return Math.floor(damage * ratio); -} - -export function zoomOutDamage(damage: number, ratio = 100) { - return Math.floor(damage)/ratio; -} - -export function zoomOutDamageWithoutRadix(damage: number, ratio = 100) { - return Math.floor(damage/ratio); -} \ No newline at end of file +import { BossInstanceType, BossInstanceModel } from '@db/BossInstance'; +import { lockData } from '../services/redLockService'; +import { findIndex, pick } from 'underscore'; +import { sismemberAsync, smembersAsync, saddAsync, delAsync, getRoleOnlineInfo, getServerCreateTime } from '../services/redisService'; +import { pinus } from 'pinus'; +import { STATUS } from '@consts/statusCode'; +import { resResult, shouldRefresh } from '@pubUtils/util'; +import { BattleRecordModel } from '@db/BattleRecord'; +import { getArmyBossRank, gameData, getBossHpRatio } from '@pubUtils/data'; +import { sendMailToGuildByContent } from '../services/mailService'; +import { MAIL_TYPE, AUCTION_SOURCE, ABI_TYPE, PUSH_ROUTE, BOSS_HP_RATIO_TYPE } from '@consts'; +import { GUILD_BOSS_STATUS } from '@consts/constModules/guildConst'; +import { genAuction } from './auctionService'; +import { GuildModel, GuildType } from '@db/Guild'; +import { UserGuildModel, UserGuildType } from '@db/UserGuild'; +import { getZeroPoint, getZeroPointOfTime, nowSeconds } from '@pubUtils/timeUtil'; +import { GUILDACTIVITY } from '@pubUtils/dicParam'; +import { GuildRecord, ServerRecordModel } from '@db/ServerRecords'; +import { sendMessageToGuildWithSuc, sendMessageToUsersWithSuc } from './pushService'; +import { AttributeCal } from '@domain/roleField/attribute'; +import { saveGuildBossHpLog } from '@pubUtils/logUtil'; +import { getHeroesAttributes } from './playerCeService'; + +/** + * 获得boss界面 + * @param bossInstance + * @param roleId + */ +export async function getBossInstanceInfo(userGuild: UserGuildType, guild?: GuildType) { + let bossInstance = await BossInstanceModel.findBossInstance(userGuild.guildCode); + + if(!bossInstance) { + bossInstance = await BossInstanceModel.findLastOverBossInstance(userGuild.guildCode); + } + return await getBossInstanceInfoByData(bossInstance, userGuild, guild); +} + +export async function getBossInstanceInfoByData(bossInstance: BossInstanceType, userGuild: UserGuildType, guild?: GuildType) { + if(!guild) guild = await GuildModel.findByCode(userGuild.guildCode, null, 'code refOpenBossTime openBossCnt'); + + let refObj = await getRefBossCnt(guild, userGuild); // 刷新次数 + let status = bossInstance? bossInstance.status: GUILD_BOSS_STATUS.WAIT_OPEN; + if(status == GUILD_BOSS_STATUS.CLEAR) status = GUILD_BOSS_STATUS.WAIT_OPEN; + let bossInfo = null; + + if(bossInstance) { + let { code, warId, ranks, bossHp, bossTotalHp, ratio, bossLv, encourageCnt } = bossInstance; + let dicBossBase = gameData.bossBaseByBossLv.get(bossLv); + let rankInfo = getRanks(ranks, userGuild.roleId); + bossInfo = { bossCode: code, warId, ...rankInfo, bossHp: zoomOutDamage(bossHp), bossTotalHp: zoomOutDamage(bossTotalHp), bossLv, encourageCnt, encourageMax: dicBossBase.encourageSum, ratio }; + } + return { status, bossInfo, ...refObj } +} + +export async function pushBossStatus(guildCode: string, result: any) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_BOSS_OPEN, pick(result, ['status', 'bossInfo', 'leaderOpenCnt'])); +} + +async function getRefBossCnt(guild: GuildType, userGuild: UserGuildType) { + let guildCnt = await refreshGuildOfBoss(guild); + let userGuildCnt = await refreshUserGuildOfBoss(userGuild); + return { ...guildCnt, ...userGuildCnt } +} + +export async function refreshGuildOfBoss(guild: GuildType, inc: number = 0) { + let { refOpenBossTime, openBossCnt, code } = guild; + if(shouldRefresh(refOpenBossTime, new Date())) { + openBossCnt = 0; + } + if(inc != 0) { + guild = await GuildModel.updateInfo(code, { refOpenBossTime: new Date(), openBossCnt: openBossCnt + inc }); + openBossCnt = guild.openBossCnt; + } + return { leaderOpenCnt: openBossCnt } +} +export async function refreshUserGuildOfBoss(userGuild: UserGuildType, incEncourage = 0, incChallenge = 0) { + let { refBossTime, encourageCnt, bossChallengeCnt } = userGuild; + if(shouldRefresh(refBossTime, new Date())) { + encourageCnt = 0, bossChallengeCnt = 0; + } + if(incEncourage != 0 || incChallenge != 0) { + userGuild = await UserGuildModel.updateInfo(userGuild.roleId, { refBossTime: new Date(), encourageCnt: encourageCnt + incEncourage, bossChallengeCnt: bossChallengeCnt + incChallenge }, {}); + encourageCnt = userGuild.encourageCnt; + bossChallengeCnt = userGuild.bossChallengeCnt; + } + return { myChallengeCnt: bossChallengeCnt, myEncourageCnt: encourageCnt } + +} + +export function getRanks(ranks: {roleId: string; score: number; time: number; job: number;}[], roleId: string ) { + ranks.sort(function(a, b) { + return b.score - a.score + a.time - b.time; + }); + + let myRank = {}; + let lastRanks = ranks.map(({roleId: battleRoleId, score }, index) => { + if (roleId == battleRoleId) { + myRank = { roleId, score: zoomOutDamageWithoutRadix(score), rankLv: index + 1 }; + } + return {roleId: battleRoleId, score: zoomOutDamageWithoutRadix(score), rankLv: index + 1}; + }); + return { ranks: lastRanks, myRank } +} + +/** + * 获得排名区间奖励 + * @param rankLv + */ +export function getArmyBossRankReward(rankLv: number) { + let armybossRankReward = getArmyBossRank(); + for (let item of armybossRankReward) { + if (item.rankMin <= rankLv && (rankLv <= item.rankMax || item.rankMax == -1)) { + return item.reward; + } + } +} + /** + * 将玩家加入到正在挑战boss队列中 + * @param code + * @param serverId + * @param roleId + */ +export async function addBossInstance(code: string, serverId:number, roleId: string) { + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + if(hisOnlineInfo.isOnline) { + let key = 'serverId_' + serverId + 'guildCode_' + code; + let value = roleId+ '|' + hisOnlineInfo.sid; + await saddAsync(key, [value]); + } +} + +/** + * 给当前正在挑战的玩家下发血量同步信息 + * @param code + * @param serverId + * @param bossHp + * @param isDelKey + */ +export async function pushBossHpMessage(code: string, serverId:number, bossHp:number, isDelKey?: boolean ) { + let key = 'serverId_' + serverId + 'guildCode_' + code; + let members = await smembersAsync(key); + let uids = members.map(member=>{ + let arr = member.split('|'); + let uid = arr[0]; + let sid = arr[1]; + return {uid, sid}; + }); + sendMessageToUsersWithSuc(PUSH_ROUTE.BOSS_HP_UPDATE, { bossHp: zoomOutDamage(bossHp) }, uids); + if (isDelKey) { + delAsync(key); + } +} +/** + * 检查该玩家当前是否正在挑战boss的队列中 + * @param code + * @param serverId + * @param roleId + * @param battleCode + */ +export async function checkBossBattleMemberExists(code: string, serverId:number, roleId: string, battleCode:string ) { + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + let key = 'serverId_' + serverId + 'guildCode_' + code ; + let value = roleId+ '|' + hisOnlineInfo.sid; + let flag = await sismemberAsync(key, value); + if (!flag) { + const battleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); + if(!battleRecord || battleRecord.status != 0 || roleId != battleRecord.roleId) { + return false; + } + await addBossInstance(code, serverId, roleId); + flag = true; + } + return flag; +} +/** + * 成员退出,删除boss关排行信息 + * @param guildCode + * @param roleId + */ +export async function removeBossRank(guildCode: string, roleId: string) { + await BossInstanceModel.removeBossRank(guildCode, roleId); +} + +function getBossSubAttrCe(hid: number, secondAttrLevel: number, bossLevel: number) { + let newAttribute = new AttributeCal(); + newAttribute.setLv(bossLevel); + let subAttr = gameData.towerPvpSubAttr.get(secondAttrLevel); + if(subAttr) newAttribute.setByWarJson(hid, subAttr.secondAtr); + let newCe = newAttribute.calCe(); + return newCe; +} + +export async function getBossHp(serverId: number, guildCode: string, dicBossBaseWar: {warId: number, bossHp: number, bossHpRatio: number }, bossLv: number) { + let { warId, bossHp: minBossHp, bossHpRatio } = dicBossBaseWar; + console.log('getBossHp', warId, minBossHp, bossHpRatio) + + let serverRecord = await ServerRecordModel.findTodayData(serverId); + if(!serverRecord) return { ratio: 1, bossHp: zoomInDamage(minBossHp) }; + + let activeGuilds = serverRecord.activeGuilds||[]; + let myGuild = activeGuilds.find(cur => cur.guildCode == guildCode); + + let playerAtkResult = await getPlayerAtkAvg(myGuild); + if (!playerAtkResult) return { ratio: 1, bossHp: zoomInDamage(minBossHp) }; + // *军团的玩家人数=开启前一天军团内登录的玩家数 + // *单个玩家的平均攻击力=军团前一天活跃玩家中最强6人排名前10的玩家的最强6人的攻击之和/10 + let { playerAtkAvg, playerCnt, activeCe, activePlayerCnt, playerAtkSum } = playerAtkResult; + // 倍数按开服天数变化 + let ratio = await getBossHpRatioByServer(BOSS_HP_RATIO_TYPE.BOSS_RATIO, serverId); + // *单个玩家10回合造成的总伤害=单个玩家的平均攻击力*倍数*10 + let player10Damage = playerAtkAvg * ratio * 10; + // boss血量=单个玩家10回合造成的总伤害*军团的玩家人数*2 + let bossHp = Math.floor(player10Damage * activePlayerCnt * 2); + let B = getB(warId, bossLv, activeCe, playerCnt); + if(B < 1) { + B = 1; + bossHp = minBossHp; + } + if(bossHp < minBossHp) { + B = 1; + bossHp = minBossHp; + } + saveGuildBossHpLog(serverId, warId, guildCode, { minBossHp, bossHpRatio, ratio, playerAtkAvg, player10Damage, activeCe, activePlayerCnt, playerAtkSum, playerCnt, B, bossHp }) + return { ratio: B, bossHp: zoomInDamage(bossHp) }; +} + +function getB(warId: number, bossLv: number, activeCe: number, playerCnt: number) { + let dicWar = gameData.war.get(warId); + if (!dicWar) return 1; + let actorId = gameData.heroIdByWar.get(warId); + + let subCe = getBossSubAttrCe(actorId, dicWar.secondAttrLevel, bossLv) + let B = (activeCe/playerCnt/6 - subCe)/GUILDACTIVITY.GATEACTIVITY_ENEMYCE; + return B; +} + +async function getPlayerAtkAvg(myGuild: GuildRecord) { + if (!myGuild) return false; + let playerAtkSum = 0, playerCnt = 0, activeCe = 0, activePlayerCnt = 0; + if (myGuild) { + let activePlayers = myGuild.players || []; + activePlayerCnt = activePlayers.length; + activePlayers.sort((a, b) => b.ce - a.ce); + for (let i = 0; i < 10; i++) { + if (!activePlayers[i]) break; + let onePlayerAtkSum = 0, heroCnt = 0; + let { roleId, topLineup = [], topLineupCe = 0 } = activePlayers[i]; + let attrByHid = await getHeroesAttributes(roleId); + for (let { hid } of topLineup) { + let atk = attrByHid.get(hid)?.getAtk() || 0; + onePlayerAtkSum += atk; + heroCnt++; + } + if (heroCnt == 0) continue; // 基本不可能,但是以防NaN + playerAtkSum += onePlayerAtkSum / heroCnt * 6; + activeCe += topLineupCe; + playerCnt ++; + } + } + if (playerCnt == 0) return false; + let playerAtkAvg = playerAtkSum / playerCnt; + return { playerAtkAvg, playerCnt, activeCe, activePlayerCnt, playerAtkSum }; +} + +export async function getBossHpRatioByServer(type: BOSS_HP_RATIO_TYPE, serverId: number) { + let serverOpenTime = await getServerCreateTime(serverId); + let serverZeroPoint = getZeroPointOfTime(serverOpenTime); + let todayZeroPoint = getZeroPoint(); + let n = Math.floor((todayZeroPoint - serverZeroPoint)/86400) + 1; + return getBossHpRatio(type, n); +} + +export function zoomInDamage(damage: number, ratio = 100) { + return Math.floor(damage * ratio); +} + +export function zoomOutDamage(damage: number, ratio = 100) { + return Math.floor(damage)/ratio; +} + +export function zoomOutDamageWithoutRadix(damage: number, ratio = 100) { + return Math.floor(damage/ratio); +} diff --git a/game-server/app/services/guildRefineService.ts b/game-server/app/services/guildRefineService.ts index 0f7fb7d1c..62ee7b2ab 100644 --- a/game-server/app/services/guildRefineService.ts +++ b/game-server/app/services/guildRefineService.ts @@ -1,45 +1,45 @@ -import { gameData, getArmyDevelopConsumeById } from '../pubUtils/data'; -import { ScienceTree, GuildRefineModel } from '../db/GuildRefine'; -import { UserGuildType } from '../db/UserGuild'; -import { shouldRefresh } from '../pubUtils/util'; -import { Structure } from '../db/Guild'; -import { GUILD_STRUCTURE } from '../consts'; - -export function checkEquipProduceStructureLv(structure: Structure[], developConsumeId: number) { - let curStructure = structure.find(cur => cur.id == GUILD_STRUCTURE.EQUIP_PRODUCE); - if(!curStructure) return curStructure; - - let dicDevelopConsume = getArmyDevelopConsumeById(developConsumeId); - if(dicDevelopConsume.structureLevel > curStructure.lv) return false; - - return true; -} - -/** - * 开启符合条件的科技树 - * @param code - */ -export async function openGuildRefine(code: string) { - let developConsumes = gameData.armyDevelopConsume; - let scienceTrees = new Array(); - developConsumes.forEach(developConsume=>{ - if (developConsume.fundConsume == 0 && developConsume.timeConsume == 0) { - //无前置条件,无研发时间的科技树直接可以点亮 - let scienceTree = new ScienceTree(); - scienceTree.id = developConsume.id; - scienceTree.endTime = 0 - scienceTree.assistRoleIds = []; - scienceTrees.push(scienceTree); - } - }); - let guildRefine = await GuildRefineModel.createScienceTree(code, scienceTrees); - return guildRefine; -} - -export function refreshRefinCnt(userGuild: UserGuildType) { - let { refRefineTime, refineCnt } = userGuild; - if(shouldRefresh(refRefineTime, new Date())) { - refRefineTime = new Date(), refineCnt = []; - } - return { refRefineTime, refineCnt }; -} \ No newline at end of file +import { gameData, getArmyDevelopConsumeById } from '@pubUtils/data'; +import { ScienceTree, GuildRefineModel } from '@db/GuildRefine'; +import { UserGuildType } from '@db/UserGuild'; +import { shouldRefresh } from '@pubUtils/util'; +import { Structure } from '@db/Guild'; +import { GUILD_STRUCTURE } from '@consts'; + +export function checkEquipProduceStructureLv(structure: Structure[], developConsumeId: number) { + let curStructure = structure.find(cur => cur.id == GUILD_STRUCTURE.EQUIP_PRODUCE); + if(!curStructure) return curStructure; + + let dicDevelopConsume = getArmyDevelopConsumeById(developConsumeId); + if(dicDevelopConsume.structureLevel > curStructure.lv) return false; + + return true; +} + +/** + * 开启符合条件的科技树 + * @param code + */ +export async function openGuildRefine(code: string) { + let developConsumes = gameData.armyDevelopConsume; + let scienceTrees = new Array(); + developConsumes.forEach(developConsume=>{ + if (developConsume.fundConsume == 0 && developConsume.timeConsume == 0) { + //无前置条件,无研发时间的科技树直接可以点亮 + let scienceTree = new ScienceTree(); + scienceTree.id = developConsume.id; + scienceTree.endTime = 0 + scienceTree.assistRoleIds = []; + scienceTrees.push(scienceTree); + } + }); + let guildRefine = await GuildRefineModel.createScienceTree(code, scienceTrees); + return guildRefine; +} + +export function refreshRefinCnt(userGuild: UserGuildType) { + let { refRefineTime, refineCnt } = userGuild; + if(shouldRefresh(refRefineTime, new Date())) { + refRefineTime = new Date(), refineCnt = []; + } + return { refRefineTime, refineCnt }; +} diff --git a/game-server/app/services/guildService.ts b/game-server/app/services/guildService.ts index f61fb44c1..62f5d4876 100644 --- a/game-server/app/services/guildService.ts +++ b/game-server/app/services/guildService.ts @@ -1,546 +1,546 @@ -import { gameData, getGuildActiveWeekReward, getGuildActiveByIdAndType, getGoodById } from "../pubUtils/data"; -import { GuildModel, GuildType, GuildUpdateParam } from "../db/Guild"; -import { deltaDays, resResult, shouldRefresh } from "../pubUtils/util"; -import { STATUS, MAIL_TYPE, GUILD_AUTH, GUILD_JOB, REDIS_KEY, CHAT_SERVER, TASK_TYPE, COUNTER, GUILD_REC_TYPE, PUSH_ROUTE, WAR_TYPE, USER_GUILD_STATUS, GUILD_POINT_WAYS } from "../consts"; -import { RoleModel, RoleType } from "../db/Role"; -import { UserGuildModel, UserGuildType, WishGood } from "../db/UserGuild"; -import { UserGuildApplyModel } from "../db/UserGuildApply"; -import { getZeroPointD, getZeroPointOfTime, getZeroPointOfTimeD, nowSeconds } from "../pubUtils/timeUtil"; -import { pinus, BackendSession, FrontendOrBackendSession } from "pinus"; -import { ARMY } from "../pubUtils/dicParam"; -import { sendMailByContent } from "./mailService"; -import { initSingleRank, getRoleOnlineInfo, updateUserInfo, isRoleOnline, getServerCreateTime } from "./redisService"; -import { lockData, lockDataNoRetry } from '../services/redLockService'; -import { ErrLogModel } from '../db/ErrLog'; -import { DATA_NAME } from '../consts/dataName'; -import { addRoleToGuildChannel } from "./chatService"; -import { Rank } from "./rankService"; -import { checkTask } from "./task/taskService"; -import { CounterModel } from "../db/Counter"; -import { getAuction } from "./auctionService"; -import { changeGuildActivity } from "./activity/guildPayService"; -import { GuildRecModel } from "../db/GuildRec"; -import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "./pushService"; -import { delGuildChannel, leaveGuildChannel } from "./chatChannelService"; -import { GuildActiveModel, } from "../db/GuildActive"; -import { RewardInter } from "../pubUtils/interface"; -import { getGuildFundByRefTime } from "./donateService"; -import { BattleRecordModel } from "../db/BattleRecord"; -import { BossInstanceModel } from "../db/BossInstance"; -import { pick } from "underscore"; -import { memberJoinGuildToLeague } from "./gvg/gvgTeamService"; -import { isToday } from '../pubUtils/timeUtil'; -import moment = require("moment"); -import { repaireSendScoreReward } from "./battle/rougeService"; - -export async function getMyGuildInfo(roleId: string, sid: string, userGuild: UserGuildType, guild: GuildType, serverId: number, session: FrontendOrBackendSession) { - - let leader = guild.leader; - let leaderIsOnline = await isRoleOnline(leader.roleId); - - // 打开公会页面,加入channel - if (userGuild.guildCode) { - addRoleToGuildChannel(roleId, sid, guild.code); - session.set('guildCode', guild.code); - session.push('guildCode', () => { }); - } - - // 获取排行榜 - let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - const rank = await r.getMyRank({ guildCode: guild.code }); - - let { lv: guildLv, memberCnt } = guild; - let dicGuild = gameData.centerBase.get(guildLv); - let guildMemberMax = dicGuild && memberCnt >= dicGuild.peopleNum; - - let guildActive = await getTodayGuildActive(guild.code); - - // 返回 - return { hasGuild: true, guildMemberMax, ...guild, activeDaily: guildActive, leader: { ...pick(leader, ['ce', 'lv', 'quitTime', 'roleId', 'roleName', 'head', 'frame', 'spine', 'title', 'isOnline']), isOnline: leaderIsOnline }, rank, myInfo: { ...userGuild } }; -} - -/** - * @description 检查该玩家是否有权限做操作 - * @param func 操作id - * @param auth 权限 - */ -export async function checkAuth(func: number, targetCode: string, guildAuth: number, myGuildCode = targetCode) { - if (targetCode != myGuildCode || !guildAuth) { - guildAuth = GUILD_AUTH.OTHERS; - } - const dicGuildAuth = gameData.guildAuth.get(func); - // console.log('*checkAuth*', func, guildAuth, dicGuildAuth) - if (!dicGuildAuth) return false; - - return dicGuildAuth.includes(guildAuth); -} - -/** - * @description 加入公会 - * @param code 公会code - * @param lv 公会当前等级,判断人数用 - * @param roleId 加入的玩家 - */ -export async function joinGuild(code: string, guildName: string, lv: number, roleId: string, serverId: number, session: BackendSession) { - - // // 周结算锁 - // let weeklySumLock = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code); - // if (!!weeklySumLock.err) { - // weeklySumLock.releaseCallback(); - // return { status: -1, resResult: resResult(STATUS.GUILD_WEEKLY_SUM) }; - // } - // weeklySumLock.releaseCallback(); - - // 人数锁 - let res: any = await lockData(serverId, DATA_NAME.JOIN_GUILD, code);// 加锁 - if (!!res.err) return { status: -1, resResult: resResult(STATUS.REDLOCK_ERR) }; - - let role = await RoleModel.findByRoleId(roleId); - if (role.hasGuild) { - res.releaseCallback();//解锁 - return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) }; - } - const dicCenterBase = gameData.centerBase.get(lv); - if (!dicCenterBase) { - res.releaseCallback();//解锁 - return { status: -1, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; - } - const maxMemberCnt = dicCenterBase.peopleNum; - const guild = await GuildModel.addMember(code, roleId, maxMemberCnt, serverId, role.ce); - if (!guild) { - res.releaseCallback();//解锁 - return { status: -1, resResult: resResult(STATUS.GUILD_MEMBER_MAX) }; - } else { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) - } - - role = await RoleModel.joinGuild(roleId, code, guildName, false); - if (!role) { - await GuildModel.notAddMember(code, roleId, role.ce); - res.releaseCallback();//解锁 - return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) }; - } - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: guildName }]); - await memberJoinGuildToLeague(guild, role); - - const userGuild = await UserGuildModel.createUserGuild(guild.code, role, false); - if (!userGuild) { - res.releaseCallback();//解锁 - return { status: -1, resResult: resResult(STATUS.GUILD_CREATE_ERROR) }; - } - - await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 - - res.releaseCallback();//解锁 - const { sid } = await getRoleOnlineInfo(roleId); - if (sid) { - await addRoleToGuildChannel(roleId, sid, code); - await pinus.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid, [{ roleId, userGuild }]); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.MEMBER_JOIN_GUILD, { hasGuild: true, code }, sid); - session.set('guildCode', code); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AUCTION_UPDATE, {}, sid); - changeGuildActivity(code, serverId, roleId, sid); - } - - //成长任务-加入军团 - if (!isToday(role.quitGuildTime)) { - // 离开军团 和 加入进团 不是同一天,才新建初始化任务(包含首次加入) - await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_JOIN); - } - - return { status: 0, guild, userGuild, roleName: role.roleName, memberCnt: guild.memberCnt, guildCe: guild.guildCe } -} - -export async function getTodayGuildActive(guildCode: string) { - let today = getZeroPointD(); - return await getGuildActiveByRefTime(guildCode, today); -} - -export async function getGuildActiveByRefTime(guildCode: string, refTime: Date) { - let guildActive = await GuildActiveModel.getActive(guildCode, refTime); - return guildActive ? guildActive.active : 0; -} - - -/** - * 获取伤害排名 - * @param code - * @param roleId - * @returns - */ -export async function addBossWarExtendActive(code: string, serverId: number) { - const bossInstance = await BossInstanceModel.findByCode(code); - if (!bossInstance || !bossInstance.ranks || bossInstance.ranks.length == 0) return 0; - let ranks = bossInstance.ranks; - ranks.sort((obj1, obj2) => obj2.score - obj1.score); - - const dicBossRankActivePoint = gameData.bossRankActivePoint; - ranks.forEach(async (ele, index) => { - const rank = index + 1; - const foundEntry = dicBossRankActivePoint.find( - (entry) => rank >= entry.bossRankMin && rank <= entry.bossRankMax - ); - - await addActive(ele.roleId, serverId, GUILD_POINT_WAYS.BOSS_WAR_EXTEND, null, (foundEntry ? foundEntry.activePoint : 0));//获得活跃值 - }); -} - -/** - * 增加活跃 - * @param guildCode 军团唯一code - * @param serverId 区 - * @param id 增加活跃的操作 - * @param type 类型 activePoint内配的type - * @param active debug直接增加的活跃 - */ -export async function addActive(roleId: string, serverId: number, id: number, type: number = 1, active?: number) { - - let dicActiveWay = gameData.guildActiveWays.get(id); - if (id && !dicActiveWay) { - return { status: 0, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; - } - if (!active) { - active = getGuildActiveByIdAndType(id, type); - } - - let userGuild = await getUserGuildWithRefActive(roleId, 'activeRecord receivedActive activeDaily activeWeekly guildCode'); - if (!userGuild) return { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; - - let guildCode = userGuild.guildCode; - // 周结算锁 - let { activeRecord } = userGuild; - if (id != 0) { // 用于debug,传0时直接增加活跃 - let curActiveRecord = activeRecord.find(cur => cur.id == id); - if (curActiveRecord) { - curActiveRecord.count++; - } else { - curActiveRecord = { id, count: 1 }; - activeRecord.push(curActiveRecord); - } - if (curActiveRecord.count > dicActiveWay.count) { // 次数超过时,不增加活跃 - active = 0; - } - } - userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord, activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); - - let guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeWeekly: active }); - let guildActive = await GuildActiveModel.addActive(guildCode, getZeroPointD(), active); - - // 排行榜更新 - let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); - let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await r2.setRankWithGuildInfo2(guildCode, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); - await pushGuildInfoUpdate(guildCode, { activeDaily: guildActive.active, activeWeekly: guild.activeWeekly }); - return { status: 1, guild, userGuild }; -} - -/** - * 获取用户公会表并刷新活跃和每日捐赠以及每日许愿数据 - * @param roleId 用户id - * @param select 筛选字段 - */ -export async function getUserGuildWithRefActive(roleId: string, select?: string) { - let userGuild = await UserGuildModel.getMyGuild(roleId, select ? select + ' wishGoods +refTimeDaily' : '+refTimeDaily'); - // console.log(JSON.stringify(userGuild)) - if (!userGuild) return false; - let { receivedActive, refTimeDaily, guildCode, wishGoods, receiveBoxs } = userGuild; - - const now = new Date(); - let isRefDaily = shouldRefresh(refTimeDaily, now); - // console.log('####### isRefDaily', isRefDaily, refTimeDaily, now) - if (isRefDaily) { - userGuild = await UserGuildModel.resetDailyInfoByRefTimeDaily(roleId, refTimeDaily); - if (refTimeDaily && userGuild) { - await sendUnreceivedWishPool(wishGoods, roleId); - await sendUnreceivedActiveBox(roleId, guildCode, refTimeDaily, receivedActive || []); - await sendUnreceivedDonateBox(roleId, guildCode, refTimeDaily, receiveBoxs || []); - await sendUnreceivedBossWar(roleId, refTimeDaily); - } - if (!userGuild) { - userGuild = await UserGuildModel.getMyGuild(roleId, select ? select + ' wishGoods +refTimeDaily' : '+refTimeDaily'); - if (!userGuild) return false; - }; - - } - - return userGuild; -} - -/** - * 查询我在今天退出的军团中是否许过愿 - * - * @param {string} roleId - * @return {*} - */ -async function isIWishedInMyTodayQuitGuilds(roleId: string): Promise { - const guilds = await UserGuildModel.findMyGuildsOfToday(roleId, 'wishGoods status'); - - const myWishedGuild = guilds.find((guild) => { - return (guild.status != USER_GUILD_STATUS.ON) && (guild.wishGoods && guild.wishGoods.length > 0); - }); - - return !!myWishedGuild; -} -/** - * 今天在军团中是否能许愿 - * - * @export - * @param {string} roleId - */ -export async function canWishToday(roleId: string): Promise { - let role = await RoleModel.findByRoleId(roleId); - if (!role) { - return false; - } - - // 今天退出过军团 & 在退出的军团许过愿 - if (isToday(role.quitGuildTime) && (await isIWishedInMyTodayQuitGuilds(roleId))) { - // 新加入的军团不允许许愿 - return false; - } - - return true; -} - -async function sendUnreceivedWishPool(wishGoods: WishGood[], roleId: string) { - wishGoods.map(async function ({ donateNames, goodId, drawCnt }) { - let goodInfo = getGoodById(goodId) - if (!goodInfo) - return; - for (let i = 0; i < drawCnt; i++) { - let donateName = donateNames[donateNames.length - i - 1]; - await sendMailByContent(MAIL_TYPE.WISH_POOL_REWARD, roleId, { - params: [donateName, goodInfo.name], - goods: [{ id: goodId, count: 1 }] - }); - } - }); -} - -async function sendUnreceivedActiveBox(roleId: string, guildCode: string, refTimeDaily: Date, receiveActiveBox: number[]) { - let refTime = getZeroPointOfTimeD(refTimeDaily); - let guildActive = await getGuildActiveByRefTime(guildCode, refTime); - let goods: RewardInter[] = []; - for (let [id, { activeDayPoint, reward }] of gameData.guildActiveDayReward) { - if (guildActive >= activeDayPoint && receiveActiveBox.indexOf(id) == -1) goods.push(...reward); - } - if (goods.length > 0) { - await sendMailByContent(MAIL_TYPE.GUILD_DAILY_BOX, roleId, { goods }); - } -} - -async function sendUnreceivedDonateBox(roleId: string, guildCode: string, refTimeDaily: Date, receiveBoxs: number[]) { - let refTime = getZeroPointOfTime(refTimeDaily); - let { fund: guildFund, donationLv } = await getGuildFundByRefTime(guildCode, refTime); - let goods: RewardInter[] = []; - for (let [id, { boxRewards, fund, level }] of gameData.armyDonateBox) { - if (level == donationLv && guildFund >= fund && receiveBoxs.indexOf(id) == -1) { - if (boxRewards) goods.push(...boxRewards); - } - } - if (goods.length > 0) { - await sendMailByContent(MAIL_TYPE.GUILD_FUND_BOX, roleId, { goods }); - } -} - -async function sendUnreceivedBossWar(roleId: string, refTimeDaily: Date) { - let beginTime = getZeroPointOfTime(refTimeDaily); - let endTime = beginTime + 24 * 60 * 60; - let battleRecords = await BattleRecordModel.findByWarTypeAndStatus(roleId, WAR_TYPE.BOSS, 0, new Date(beginTime * 1000), new Date(endTime * 1000)); - for (let { battleCode, record = {} } of battleRecords) { - let { bossDamage = 0, bossInstanceCode } = record; - if (bossDamage > 0) { - let bossInstance = await BossInstanceModel.findByCode(bossInstanceCode); - if (!bossInstance) continue; - - let dicBossBase = gameData.bossBaseByBossLv.get(bossInstance.bossLv); - let { basicReward, damageRewardTotal } = dicBossBase; - let damageReward = damageRewardTotal.map(cur => { - return { id: cur.id, count: Math.ceil(cur.count * bossDamage / bossInstance.bossTotalHp) } - }) - let goods = [...basicReward, ...damageReward]; - - if (goods.length > 0) { - await sendMailByContent(MAIL_TYPE.GUILD_BOSS, roleId, { goods }); - } - await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: 1 } }); - } - } -} - - -/** - * 每周结算上周公会周功勋和 活跃并发奖励(未完) - * - */ -export async function settleGuildWeekly() { - console.log('————— settleGuildWeekly —————'); - const guildList = await GuildModel.findAllGuild('code activeWeekly memberCnt serverId'); - - // 周结算时,1. 不能变动memberCnt 2.玩家activeWeekly不能变动 3.公会activeWeekly不能变动 - for (let { code, memberCnt, serverId } of guildList) { - // let res: any = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code);//加锁 - // if (!!res.err) { - // await ErrLogModel.create(`settle guild lock data error: ${res.err}`) - // } - const userGuildList = await UserGuildModel.getListByGuild(code, 'roleId auth activeWeekly', { activeWeekly: -1, activeUpdateTime: 1 }); - - let otherMemberCnt = 0; // 除了大将军以外从活跃高到底成员人数,用户计算活跃排名百分比 - let members = new Map(); - - for (let { roleId, auth, activeWeekly } of userGuildList) { - let job = 0; - - if (auth == GUILD_AUTH.LEADER) { - job = GUILD_JOB.DAJIANGJUN; - } else if (activeWeekly <= ARMY.ARMY_WEEKHONOUR_LIMIT) { - job = GUILD_JOB.SHIBING; - } else { - otherMemberCnt++; - for (let [id, { rankProportion }] of gameData.guildPosition) { - let rankCnt = Math.ceil(memberCnt * rankProportion / 100); - job = id; - if (otherMemberCnt <= rankCnt) break; - } - } - await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }, {}); - - if (activeWeekly > ARMY.ARMY_WEEKHONOUR_LIMIT) { // 低于一定不发奖励 - members.set(roleId, job); - } - } - - // 转换周活跃奖励 - let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); - let rank = await r.getMyRank({ guildCode: code }); - let allWeeklyReward = getGuildActiveWeekReward(rank); - for (let [roleId, job] of members) { - let jobActiveRatio = gameData.guildPosition.get(job).activeRatio; - let reward = allWeeklyReward.map(cur => { - return { - id: cur.id, - count: Math.ceil(cur.count * jobActiveRatio) - } - }); - await sendMailByContent(MAIL_TYPE.GUILD_ACTIVE_REWARD, roleId, { goods: reward }); - // 任务 - await checkTask(serverId, roleId, null, TASK_TYPE.GUILD_JOB, { guildJob: job }); - } - - await GuildModel.updateInfo(code, { activeWeekly: 0 }, {}); - // res.releaseCallback();//解锁 - } - await initSingleRank(REDIS_KEY.GUILD_ACTIVE_RANK); - await initSingleRank(REDIS_KEY.GUILD_LV_RANK); - let curSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM); - - // 发送肉鸽奖励 - await repaireSendScoreReward(); - - console.log('————— settleGuildWeekly结束 —————'); -} - - -export async function getWishPool(userGuild: UserGuildType) { - let { guildCode: code, wishDntCnt, wishGoods, receivedWishPool, refTimeDaily } = userGuild; - - const now = new Date(); - let isRefDaily = shouldRefresh(refTimeDaily, now); - // console.log('####### isRefDaily', isRefDaily, refTimeDaily, now) - if (isRefDaily) { - wishGoods = []; receivedWishPool = [], wishDntCnt = 0; - } - - let userGuilds = await UserGuildModel.getWishPoolGoods(code, ' wishDntCnt wishGoods roleId'); - let list = []; - userGuilds.forEach(({ wishGoods, roleId }) => { - wishGoods.forEach(({ type, goodId, count, receiveCnt, drawCnt, id }) => { - list.push({ type, goodId, count, receiveCnt, drawCnt, id, roleId }) - }); - }); - return { list, wishDntCnt: wishDntCnt || 0, wishGoods, receivedWishPool }; -} - -export function setUserGuildSession(session: FrontendOrBackendSession, myUserGuild: UserGuildType) { - if (myUserGuild) { - session.set('guildCode', myUserGuild.guildCode); - session.set('guildAuth', myUserGuild.auth); - session.push('guildCode', () => { }); - session.push('guildAuth', () => { }); - } else { - session.set('guildCode', null); - session.set('guildAuth', null); - session.push('guildCode', () => { }); - session.push('guildAuth', () => { }); - } -} - -export async function getInvitationList(roleId: string, lastApplyCode = '') { - const result = await UserGuildApplyModel.findInviteByRole(roleId, lastApplyCode); - const list = result.map(cur => { - let guild = cur.guild; - let leader = guild.leader; - delete cur.guild; - return { applyCode: cur.applyCode, ...guild, leader: leader.roleName }; - }); - return list; -} - -// 添加军团动态 -export async function addGuildRecord(roleId: string, guildCode: string, type: GUILD_REC_TYPE, params: string[]) { - const rec = await GuildRecModel.createGuildRec(roleId, guildCode, type, params); - { - let { type, params, createTime } = rec; - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_REC_ADD, { type, params, createTime }); - } -} - -export async function pushGuildInfoUpdate(guildCode: string, info: any) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_INFO_UPDATE, info); -} - -// 更换团长推送 -export async function pushChangeGuildLeader(guildCode: string, managerCnt: number, newLeader: RoleType, oldLeaderId: string) { - let { roleId, roleName, frame, head, spine, lv, quitTime } = newLeader; - await pushGuildInfoUpdate(guildCode, { managerCnt, leader: { roleId, roleName, frame, head, spine, lv, quitTime } }); - // 给旧团长推送 - await sendMessageToUserWithSuc(oldLeaderId, PUSH_ROUTE.DEMOTION, { code: guildCode }); - // 给新团长推送 - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PROMOTION, { code: guildCode }); -} - -/** - * 推送踢出某个成员 - * @param guildCode 军团code - * @param roleId 踢出玩家roleId - * @param guild 军团信息 - * @param sid 玩家sid - */ -export async function pushGuildMemberQuit(roleId: string, guildCode: string, guild: GuildType, sid: string) { - // 被踢出公会 - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.MEMBER_QUIT, { code: guildCode, roleId }, sid); - // 更新人数减少 - await pushGuildInfoUpdate(guildCode, { memberCnt: guild.memberCnt, guildCe: guild.guildCe }); - leaveGuildChannel(roleId, sid, guildCode); -} - -/** - * 推送解散军团 - * @param guildCode 军团code - */ -export async function pushGuildDismiss(guildCode: string) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DISMISS, { code: guildCode }); - delGuildChannel(guildCode); -} - -export async function getGuildQuitCdTime(serverId: number) { - let serverTime = await getServerCreateTime(serverId); - let todayIndex = deltaDays(moment(serverTime * 1000).toDate(), new Date) + 1; - let result = 0; - for (let { day, minute } of gameData.guildQuitCd) { - if (todayIndex > day) result = minute; - } - console.log('####', serverId, serverTime, todayIndex, result) - return result -} \ No newline at end of file +import { gameData, getGuildActiveWeekReward, getGuildActiveByIdAndType, getGoodById } from "@pubUtils/data"; +import { GuildModel, GuildType, GuildUpdateParam } from "@db/Guild"; +import { deltaDays, resResult, shouldRefresh } from "@pubUtils/util"; +import { STATUS, MAIL_TYPE, GUILD_AUTH, GUILD_JOB, REDIS_KEY, CHAT_SERVER, TASK_TYPE, COUNTER, GUILD_REC_TYPE, PUSH_ROUTE, WAR_TYPE, USER_GUILD_STATUS, GUILD_POINT_WAYS } from "@consts"; +import { RoleModel, RoleType } from "@db/Role"; +import { UserGuildModel, UserGuildType, WishGood } from "@db/UserGuild"; +import { UserGuildApplyModel } from "@db/UserGuildApply"; +import { getZeroPointD, getZeroPointOfTime, getZeroPointOfTimeD, nowSeconds } from "@pubUtils/timeUtil"; +import { pinus, BackendSession, FrontendOrBackendSession } from "pinus"; +import { ARMY } from "@pubUtils/dicParam"; +import { sendMailByContent } from "./mailService"; +import { initSingleRank, getRoleOnlineInfo, updateUserInfo, isRoleOnline, getServerCreateTime } from "./redisService"; +import { lockData, lockDataNoRetry } from '../services/redLockService'; +import { ErrLogModel } from '@db/ErrLog'; +import { DATA_NAME } from '@consts/dataName'; +import { addRoleToGuildChannel } from "./chatService"; +import { Rank } from "./rankService"; +import { checkTask } from "./task/taskService"; +import { CounterModel } from "@db/Counter"; +import { getAuction } from "./auctionService"; +import { changeGuildActivity } from "./activity/guildPayService"; +import { GuildRecModel } from "@db/GuildRec"; +import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "./pushService"; +import { delGuildChannel, leaveGuildChannel } from "./chatChannelService"; +import { GuildActiveModel, } from "@db/GuildActive"; +import { RewardInter } from "@pubUtils/interface"; +import { getGuildFundByRefTime } from "./donateService"; +import { BattleRecordModel } from "@db/BattleRecord"; +import { BossInstanceModel } from "@db/BossInstance"; +import { pick } from "underscore"; +import { memberJoinGuildToLeague } from "./gvg/gvgTeamService"; +import { isToday } from '@pubUtils/timeUtil'; +import moment = require("moment"); +import { repaireSendScoreReward } from "./battle/rougeService"; + +export async function getMyGuildInfo(roleId: string, sid: string, userGuild: UserGuildType, guild: GuildType, serverId: number, session: FrontendOrBackendSession) { + + let leader = guild.leader; + let leaderIsOnline = await isRoleOnline(leader.roleId); + + // 打开公会页面,加入channel + if (userGuild.guildCode) { + addRoleToGuildChannel(roleId, sid, guild.code); + session.set('guildCode', guild.code); + session.push('guildCode', () => { }); + } + + // 获取排行榜 + let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + const rank = await r.getMyRank({ guildCode: guild.code }); + + let { lv: guildLv, memberCnt } = guild; + let dicGuild = gameData.centerBase.get(guildLv); + let guildMemberMax = dicGuild && memberCnt >= dicGuild.peopleNum; + + let guildActive = await getTodayGuildActive(guild.code); + + // 返回 + return { hasGuild: true, guildMemberMax, ...guild, activeDaily: guildActive, leader: { ...pick(leader, ['ce', 'lv', 'quitTime', 'roleId', 'roleName', 'head', 'frame', 'spine', 'title', 'isOnline']), isOnline: leaderIsOnline }, rank, myInfo: { ...userGuild } }; +} + +/** + * @description 检查该玩家是否有权限做操作 + * @param func 操作id + * @param auth 权限 + */ +export async function checkAuth(func: number, targetCode: string, guildAuth: number, myGuildCode = targetCode) { + if (targetCode != myGuildCode || !guildAuth) { + guildAuth = GUILD_AUTH.OTHERS; + } + const dicGuildAuth = gameData.guildAuth.get(func); + // console.log('*checkAuth*', func, guildAuth, dicGuildAuth) + if (!dicGuildAuth) return false; + + return dicGuildAuth.includes(guildAuth); +} + +/** + * @description 加入公会 + * @param code 公会code + * @param lv 公会当前等级,判断人数用 + * @param roleId 加入的玩家 + */ +export async function joinGuild(code: string, guildName: string, lv: number, roleId: string, serverId: number, session: BackendSession) { + + // // 周结算锁 + // let weeklySumLock = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code); + // if (!!weeklySumLock.err) { + // weeklySumLock.releaseCallback(); + // return { status: -1, resResult: resResult(STATUS.GUILD_WEEKLY_SUM) }; + // } + // weeklySumLock.releaseCallback(); + + // 人数锁 + let res: any = await lockData(serverId, DATA_NAME.JOIN_GUILD, code);// 加锁 + if (!!res.err) return { status: -1, resResult: resResult(STATUS.REDLOCK_ERR) }; + + let role = await RoleModel.findByRoleId(roleId); + if (role.hasGuild) { + res.releaseCallback();//解锁 + return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) }; + } + const dicCenterBase = gameData.centerBase.get(lv); + if (!dicCenterBase) { + res.releaseCallback();//解锁 + return { status: -1, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; + } + const maxMemberCnt = dicCenterBase.peopleNum; + const guild = await GuildModel.addMember(code, roleId, maxMemberCnt, serverId, role.ce); + if (!guild) { + res.releaseCallback();//解锁 + return { status: -1, resResult: resResult(STATUS.GUILD_MEMBER_MAX) }; + } else { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]) + } + + role = await RoleModel.joinGuild(roleId, code, guildName, false); + if (!role) { + await GuildModel.notAddMember(code, roleId, role.ce); + res.releaseCallback();//解锁 + return { status: -1, resResult: resResult(STATUS.GUILD_HAS_JOIN) }; + } + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: guildName }]); + await memberJoinGuildToLeague(guild, role); + + const userGuild = await UserGuildModel.createUserGuild(guild.code, role, false); + if (!userGuild) { + res.releaseCallback();//解锁 + return { status: -1, resResult: resResult(STATUS.GUILD_CREATE_ERROR) }; + } + + await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请 + + res.releaseCallback();//解锁 + const { sid } = await getRoleOnlineInfo(roleId); + if (sid) { + await addRoleToGuildChannel(roleId, sid, code); + await pinus.app.rpc.connector.connectorRemote.setOtherUserGuildSession.toServer(sid, [{ roleId, userGuild }]); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.MEMBER_JOIN_GUILD, { hasGuild: true, code }, sid); + session.set('guildCode', code); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.AUCTION_UPDATE, {}, sid); + changeGuildActivity(code, serverId, roleId, sid); + } + + //成长任务-加入军团 + if (!isToday(role.quitGuildTime)) { + // 离开军团 和 加入进团 不是同一天,才新建初始化任务(包含首次加入) + await checkTask(serverId, roleId, sid, TASK_TYPE.GUILD_JOIN); + } + + return { status: 0, guild, userGuild, roleName: role.roleName, memberCnt: guild.memberCnt, guildCe: guild.guildCe } +} + +export async function getTodayGuildActive(guildCode: string) { + let today = getZeroPointD(); + return await getGuildActiveByRefTime(guildCode, today); +} + +export async function getGuildActiveByRefTime(guildCode: string, refTime: Date) { + let guildActive = await GuildActiveModel.getActive(guildCode, refTime); + return guildActive ? guildActive.active : 0; +} + + +/** + * 获取伤害排名 + * @param code + * @param roleId + * @returns + */ +export async function addBossWarExtendActive(code: string, serverId: number) { + const bossInstance = await BossInstanceModel.findByCode(code); + if (!bossInstance || !bossInstance.ranks || bossInstance.ranks.length == 0) return 0; + let ranks = bossInstance.ranks; + ranks.sort((obj1, obj2) => obj2.score - obj1.score); + + const dicBossRankActivePoint = gameData.bossRankActivePoint; + ranks.forEach(async (ele, index) => { + const rank = index + 1; + const foundEntry = dicBossRankActivePoint.find( + (entry) => rank >= entry.bossRankMin && rank <= entry.bossRankMax + ); + + await addActive(ele.roleId, serverId, GUILD_POINT_WAYS.BOSS_WAR_EXTEND, null, (foundEntry ? foundEntry.activePoint : 0));//获得活跃值 + }); +} + +/** + * 增加活跃 + * @param guildCode 军团唯一code + * @param serverId 区 + * @param id 增加活跃的操作 + * @param type 类型 activePoint内配的type + * @param active debug直接增加的活跃 + */ +export async function addActive(roleId: string, serverId: number, id: number, type: number = 1, active?: number) { + + let dicActiveWay = gameData.guildActiveWays.get(id); + if (id && !dicActiveWay) { + return { status: 0, resResult: resResult(STATUS.DIC_DATA_NOT_FOUND) }; + } + if (!active) { + active = getGuildActiveByIdAndType(id, type); + } + + let userGuild = await getUserGuildWithRefActive(roleId, 'activeRecord receivedActive activeDaily activeWeekly guildCode'); + if (!userGuild) return { status: 0, resResult: resResult(STATUS.GUILD_NOT_FOUND) }; + + let guildCode = userGuild.guildCode; + // 周结算锁 + let { activeRecord } = userGuild; + if (id != 0) { // 用于debug,传0时直接增加活跃 + let curActiveRecord = activeRecord.find(cur => cur.id == id); + if (curActiveRecord) { + curActiveRecord.count++; + } else { + curActiveRecord = { id, count: 1 }; + activeRecord.push(curActiveRecord); + } + if (curActiveRecord.count > dicActiveWay.count) { // 次数超过时,不增加活跃 + active = 0; + } + } + userGuild = await UserGuildModel.updateInfo(roleId, { activeRecord, activeUpdateTime: nowSeconds() }, { activeDaily: active, activeWeekly: active }); + + let guild = await GuildModel.updateInfo(guildCode, { activeUpdateTime: nowSeconds() }, { activeWeekly: active }); + let guildActive = await GuildActiveModel.addActive(guildCode, getZeroPointD(), active); + + // 排行榜更新 + let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await r.setRankWithGuildInfo(guildCode, guild.activeWeekly, guild.activeUpdateTime, guild); + let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await r2.setRankWithGuildInfo2(guildCode, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); + await pushGuildInfoUpdate(guildCode, { activeDaily: guildActive.active, activeWeekly: guild.activeWeekly }); + return { status: 1, guild, userGuild }; +} + +/** + * 获取用户公会表并刷新活跃和每日捐赠以及每日许愿数据 + * @param roleId 用户id + * @param select 筛选字段 + */ +export async function getUserGuildWithRefActive(roleId: string, select?: string) { + let userGuild = await UserGuildModel.getMyGuild(roleId, select ? select + ' wishGoods +refTimeDaily' : '+refTimeDaily'); + // console.log(JSON.stringify(userGuild)) + if (!userGuild) return false; + let { receivedActive, refTimeDaily, guildCode, wishGoods, receiveBoxs } = userGuild; + + const now = new Date(); + let isRefDaily = shouldRefresh(refTimeDaily, now); + // console.log('####### isRefDaily', isRefDaily, refTimeDaily, now) + if (isRefDaily) { + userGuild = await UserGuildModel.resetDailyInfoByRefTimeDaily(roleId, refTimeDaily); + if (refTimeDaily && userGuild) { + await sendUnreceivedWishPool(wishGoods, roleId); + await sendUnreceivedActiveBox(roleId, guildCode, refTimeDaily, receivedActive || []); + await sendUnreceivedDonateBox(roleId, guildCode, refTimeDaily, receiveBoxs || []); + await sendUnreceivedBossWar(roleId, refTimeDaily); + } + if (!userGuild) { + userGuild = await UserGuildModel.getMyGuild(roleId, select ? select + ' wishGoods +refTimeDaily' : '+refTimeDaily'); + if (!userGuild) return false; + }; + + } + + return userGuild; +} + +/** + * 查询我在今天退出的军团中是否许过愿 + * + * @param {string} roleId + * @return {*} + */ +async function isIWishedInMyTodayQuitGuilds(roleId: string): Promise { + const guilds = await UserGuildModel.findMyGuildsOfToday(roleId, 'wishGoods status'); + + const myWishedGuild = guilds.find((guild) => { + return (guild.status != USER_GUILD_STATUS.ON) && (guild.wishGoods && guild.wishGoods.length > 0); + }); + + return !!myWishedGuild; +} +/** + * 今天在军团中是否能许愿 + * + * @export + * @param {string} roleId + */ +export async function canWishToday(roleId: string): Promise { + let role = await RoleModel.findByRoleId(roleId); + if (!role) { + return false; + } + + // 今天退出过军团 & 在退出的军团许过愿 + if (isToday(role.quitGuildTime) && (await isIWishedInMyTodayQuitGuilds(roleId))) { + // 新加入的军团不允许许愿 + return false; + } + + return true; +} + +async function sendUnreceivedWishPool(wishGoods: WishGood[], roleId: string) { + wishGoods.map(async function ({ donateNames, goodId, drawCnt }) { + let goodInfo = getGoodById(goodId) + if (!goodInfo) + return; + for (let i = 0; i < drawCnt; i++) { + let donateName = donateNames[donateNames.length - i - 1]; + await sendMailByContent(MAIL_TYPE.WISH_POOL_REWARD, roleId, { + params: [donateName, goodInfo.name], + goods: [{ id: goodId, count: 1 }] + }); + } + }); +} + +async function sendUnreceivedActiveBox(roleId: string, guildCode: string, refTimeDaily: Date, receiveActiveBox: number[]) { + let refTime = getZeroPointOfTimeD(refTimeDaily); + let guildActive = await getGuildActiveByRefTime(guildCode, refTime); + let goods: RewardInter[] = []; + for (let [id, { activeDayPoint, reward }] of gameData.guildActiveDayReward) { + if (guildActive >= activeDayPoint && receiveActiveBox.indexOf(id) == -1) goods.push(...reward); + } + if (goods.length > 0) { + await sendMailByContent(MAIL_TYPE.GUILD_DAILY_BOX, roleId, { goods }); + } +} + +async function sendUnreceivedDonateBox(roleId: string, guildCode: string, refTimeDaily: Date, receiveBoxs: number[]) { + let refTime = getZeroPointOfTime(refTimeDaily); + let { fund: guildFund, donationLv } = await getGuildFundByRefTime(guildCode, refTime); + let goods: RewardInter[] = []; + for (let [id, { boxRewards, fund, level }] of gameData.armyDonateBox) { + if (level == donationLv && guildFund >= fund && receiveBoxs.indexOf(id) == -1) { + if (boxRewards) goods.push(...boxRewards); + } + } + if (goods.length > 0) { + await sendMailByContent(MAIL_TYPE.GUILD_FUND_BOX, roleId, { goods }); + } +} + +async function sendUnreceivedBossWar(roleId: string, refTimeDaily: Date) { + let beginTime = getZeroPointOfTime(refTimeDaily); + let endTime = beginTime + 24 * 60 * 60; + let battleRecords = await BattleRecordModel.findByWarTypeAndStatus(roleId, WAR_TYPE.BOSS, 0, new Date(beginTime * 1000), new Date(endTime * 1000)); + for (let { battleCode, record = {} } of battleRecords) { + let { bossDamage = 0, bossInstanceCode } = record; + if (bossDamage > 0) { + let bossInstance = await BossInstanceModel.findByCode(bossInstanceCode); + if (!bossInstance) continue; + + let dicBossBase = gameData.bossBaseByBossLv.get(bossInstance.bossLv); + let { basicReward, damageRewardTotal } = dicBossBase; + let damageReward = damageRewardTotal.map(cur => { + return { id: cur.id, count: Math.ceil(cur.count * bossDamage / bossInstance.bossTotalHp) } + }) + let goods = [...basicReward, ...damageReward]; + + if (goods.length > 0) { + await sendMailByContent(MAIL_TYPE.GUILD_BOSS, roleId, { goods }); + } + await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: 1 } }); + } + } +} + + +/** + * 每周结算上周公会周功勋和 活跃并发奖励(未完) + * + */ +export async function settleGuildWeekly() { + console.log('————— settleGuildWeekly —————'); + const guildList = await GuildModel.findAllGuild('code activeWeekly memberCnt serverId'); + + // 周结算时,1. 不能变动memberCnt 2.玩家activeWeekly不能变动 3.公会activeWeekly不能变动 + for (let { code, memberCnt, serverId } of guildList) { + // let res: any = await lockDataNoRetry(serverId, DATA_NAME.WEEKLY_GUILD_SUM, code);//加锁 + // if (!!res.err) { + // await ErrLogModel.create(`settle guild lock data error: ${res.err}`) + // } + const userGuildList = await UserGuildModel.getListByGuild(code, 'roleId auth activeWeekly', { activeWeekly: -1, activeUpdateTime: 1 }); + + let otherMemberCnt = 0; // 除了大将军以外从活跃高到底成员人数,用户计算活跃排名百分比 + let members = new Map(); + + for (let { roleId, auth, activeWeekly } of userGuildList) { + let job = 0; + + if (auth == GUILD_AUTH.LEADER) { + job = GUILD_JOB.DAJIANGJUN; + } else if (activeWeekly <= ARMY.ARMY_WEEKHONOUR_LIMIT) { + job = GUILD_JOB.SHIBING; + } else { + otherMemberCnt++; + for (let [id, { rankProportion }] of gameData.guildPosition) { + let rankCnt = Math.ceil(memberCnt * rankProportion / 100); + job = id; + if (otherMemberCnt <= rankCnt) break; + } + } + await UserGuildModel.updateInfo(roleId, { job, activeWeekly: 0 }, {}); + + if (activeWeekly > ARMY.ARMY_WEEKHONOUR_LIMIT) { // 低于一定不发奖励 + members.set(roleId, job); + } + } + + // 转换周活跃奖励 + let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId }); + let rank = await r.getMyRank({ guildCode: code }); + let allWeeklyReward = getGuildActiveWeekReward(rank); + for (let [roleId, job] of members) { + let jobActiveRatio = gameData.guildPosition.get(job).activeRatio; + let reward = allWeeklyReward.map(cur => { + return { + id: cur.id, + count: Math.ceil(cur.count * jobActiveRatio) + } + }); + await sendMailByContent(MAIL_TYPE.GUILD_ACTIVE_REWARD, roleId, { goods: reward }); + // 任务 + await checkTask(serverId, roleId, null, TASK_TYPE.GUILD_JOB, { guildJob: job }); + } + + await GuildModel.updateInfo(code, { activeWeekly: 0 }, {}); + // res.releaseCallback();//解锁 + } + await initSingleRank(REDIS_KEY.GUILD_ACTIVE_RANK); + await initSingleRank(REDIS_KEY.GUILD_LV_RANK); + let curSeasonNum = await CounterModel.getCounter(COUNTER.PVP_SEASON_NUM); + + // 发送肉鸽奖励 + await repaireSendScoreReward(); + + console.log('————— settleGuildWeekly结束 —————'); +} + + +export async function getWishPool(userGuild: UserGuildType) { + let { guildCode: code, wishDntCnt, wishGoods, receivedWishPool, refTimeDaily } = userGuild; + + const now = new Date(); + let isRefDaily = shouldRefresh(refTimeDaily, now); + // console.log('####### isRefDaily', isRefDaily, refTimeDaily, now) + if (isRefDaily) { + wishGoods = []; receivedWishPool = [], wishDntCnt = 0; + } + + let userGuilds = await UserGuildModel.getWishPoolGoods(code, ' wishDntCnt wishGoods roleId'); + let list = []; + userGuilds.forEach(({ wishGoods, roleId }) => { + wishGoods.forEach(({ type, goodId, count, receiveCnt, drawCnt, id }) => { + list.push({ type, goodId, count, receiveCnt, drawCnt, id, roleId }) + }); + }); + return { list, wishDntCnt: wishDntCnt || 0, wishGoods, receivedWishPool }; +} + +export function setUserGuildSession(session: FrontendOrBackendSession, myUserGuild: UserGuildType) { + if (myUserGuild) { + session.set('guildCode', myUserGuild.guildCode); + session.set('guildAuth', myUserGuild.auth); + session.push('guildCode', () => { }); + session.push('guildAuth', () => { }); + } else { + session.set('guildCode', null); + session.set('guildAuth', null); + session.push('guildCode', () => { }); + session.push('guildAuth', () => { }); + } +} + +export async function getInvitationList(roleId: string, lastApplyCode = '') { + const result = await UserGuildApplyModel.findInviteByRole(roleId, lastApplyCode); + const list = result.map(cur => { + let guild = cur.guild; + let leader = guild.leader; + delete cur.guild; + return { applyCode: cur.applyCode, ...guild, leader: leader.roleName }; + }); + return list; +} + +// 添加军团动态 +export async function addGuildRecord(roleId: string, guildCode: string, type: GUILD_REC_TYPE, params: string[]) { + const rec = await GuildRecModel.createGuildRec(roleId, guildCode, type, params); + { + let { type, params, createTime } = rec; + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_REC_ADD, { type, params, createTime }); + } +} + +export async function pushGuildInfoUpdate(guildCode: string, info: any) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.GUILD_INFO_UPDATE, info); +} + +// 更换团长推送 +export async function pushChangeGuildLeader(guildCode: string, managerCnt: number, newLeader: RoleType, oldLeaderId: string) { + let { roleId, roleName, frame, head, spine, lv, quitTime } = newLeader; + await pushGuildInfoUpdate(guildCode, { managerCnt, leader: { roleId, roleName, frame, head, spine, lv, quitTime } }); + // 给旧团长推送 + await sendMessageToUserWithSuc(oldLeaderId, PUSH_ROUTE.DEMOTION, { code: guildCode }); + // 给新团长推送 + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PROMOTION, { code: guildCode }); +} + +/** + * 推送踢出某个成员 + * @param guildCode 军团code + * @param roleId 踢出玩家roleId + * @param guild 军团信息 + * @param sid 玩家sid + */ +export async function pushGuildMemberQuit(roleId: string, guildCode: string, guild: GuildType, sid: string) { + // 被踢出公会 + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.MEMBER_QUIT, { code: guildCode, roleId }, sid); + // 更新人数减少 + await pushGuildInfoUpdate(guildCode, { memberCnt: guild.memberCnt, guildCe: guild.guildCe }); + leaveGuildChannel(roleId, sid, guildCode); +} + +/** + * 推送解散军团 + * @param guildCode 军团code + */ +export async function pushGuildDismiss(guildCode: string) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.DISMISS, { code: guildCode }); + delGuildChannel(guildCode); +} + +export async function getGuildQuitCdTime(serverId: number) { + let serverTime = await getServerCreateTime(serverId); + let todayIndex = deltaDays(moment(serverTime * 1000).toDate(), new Date) + 1; + let result = 0; + for (let { day, minute } of gameData.guildQuitCd) { + if (todayIndex > day) result = minute; + } + console.log('####', serverId, serverTime, todayIndex, result) + return result +} diff --git a/game-server/app/services/guildTrainService.ts b/game-server/app/services/guildTrainService.ts index 989f117f8..bce079156 100644 --- a/game-server/app/services/guildTrainService.ts +++ b/game-server/app/services/guildTrainService.ts @@ -1,325 +1,325 @@ -import { UserGuildModel, UserGuildType } from '../db/UserGuild'; -import { getArmyTrainJuDian, getGuildTrainGkInfo, getTrainBaseByLv } from '../pubUtils/data'; -import { nowSeconds, getZeroPoint, isToday, getSeconds, getZeroPointD } from '../pubUtils/timeUtil'; -import { GUILD_STRUCTURE, PUSH_ROUTE, SHOP_REFRESH_TYPE, WAR_TYPE } from '../consts'; -import { GuildTrainType, GuildTrainModel, TrainInstance } from '../db/GuildTrain'; -import { GuildModel, GuildType } from '../db/Guild'; -import { findWhere } from 'underscore'; -import { ARMY } from '../pubUtils/dicParam'; -import { lockData } from './redLockService'; -import { pinus } from 'pinus'; -import { MailModel, MailType } from '../db/Mail'; -import { resResult, getRandSingleEelm, shouldRefresh } from '../pubUtils/util'; -import { STATUS } from '../consts/statusCode'; -import { GuildTrainReportModel } from '../db/GuildTrainReport'; -import { DATA_NAME } from '../consts/dataName'; -import { sendMailByContent } from './mailService'; -import { MAIL_TYPE } from '../consts'; -import { getGuildChannelSid } from './chatChannelService'; -import { sendMessageToGuildWithSuc } from './pushService'; -import { gameData } from '../pubUtils/data'; -import { BattleRecordModel } from '../db/BattleRecord'; -/** - * 获得userGuild,并检查,是否需要每日重置购买挑战次数和今日挑战次数,已经检查是否需要每周重置练兵场 - * @param roleId - * @param serverId - */ -export async function refreshTrain(userGuild: UserGuildType, roleId: string, serverId: number) { - let { trainCount, trainTime, buyTrainCount, guildCode} = userGuild; - await resetTrain(guildCode, serverId);//检查重置练兵场 - if (trainTime < getZeroPoint()) {//重置挑战次数和购买次数 - trainCount = ARMY.ARMY_TRAIN_BUYTIMES; - - buyTrainCount = 0; - userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds(), buyTrainCount}, {}); - } - - return userGuild; -} - -export async function getTrainBoxRewardsResult(guildCode: string) { - - let guildTrains = await GuildTrainModel.findGuildTrain(guildCode);//获得未失效的宝箱奖励 - let resTrainBoxs = []; - guildTrains.forEach(({ trainInstances, trainId }) => { - let { trainInstances: instances } = getArmyTrainJuDian(trainId); - let flag = false; - let boxRewards = []; - trainInstances.map(({ hid, progress, endTime, trainBoxs }) => { - let isComplete = false; - let instance = findWhere(instances, { hid }); - if (progress >= instance.progress) { - isComplete = true; - if (endTime > nowSeconds()) - flag = true; - } - boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); - }); - if (flag) { - resTrainBoxs.push({ trainId, boxRewards }); - } - }) - return resTrainBoxs -} - -/** - * 领过的试炼宝箱不允许再领 - * - * @export - * @param {string} guildCode - * @param {number[]} receivedTrainBox: {[英雄id]:[军团id]} 表示已经领取过该英雄奖励的军团 - * @return {*} - */ -export async function getTrainBoxRewardsResultWithoutAlreadyGeted(guildCode: string, receivedTrainBox: { [hid: number]: string[] }) { - - let guildTrains = await GuildTrainModel.findGuildTrain(guildCode);//获得未失效的宝箱奖励 - let resTrainBoxs = []; - guildTrains.forEach(({ trainInstances, trainId }) => { - let { trainInstances: instances } = getArmyTrainJuDian(trainId); - let flag = false; - let boxRewards = []; - trainInstances.map(({ hid, progress, endTime, trainBoxs }) => { - let isComplete = false; - let instance = findWhere(instances, { hid }); - if (progress >= instance.progress) { - isComplete = true; - if (endTime > nowSeconds()) - flag = true; - } - // 在任何军团都未领取过 || 在本军团领取过 ==> 全部正常展示 - if (!receivedTrainBox[hid] || (receivedTrainBox[hid] && receivedTrainBox[hid].length > 0 && receivedTrainBox[hid].indexOf(guildCode) != -1)) { - boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); - } else { - // 领取过,且不是在本军团领取的 ==> 置灰、奖励不可领取 - isComplete = false; - endTime = 0; - boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); - } - - }); - if (flag) { - resTrainBoxs.push({ trainId, boxRewards }); - } - }) - return resTrainBoxs -} - -/** - * 获得未失效的试炼宝箱奖励 - * @param guildTrain - */ -export function getGuildTrainRewards (guildTrain) { - let { trainInstances: instances } = getArmyTrainJuDian(guildTrain.trainId); - let trainBoxs = guildTrain.trainInstances.map(({hid, trainBoxs, endTime})=>{ - let instance = findWhere(instances, { hid }); - let isComplete = false; - if ( guildTrain.progress >= instance.progress) - isComplete = true; - return {hid, recordBoxs: trainBoxs, trainId: guildTrain.trainId, endTime, isComplete}; - }) - return { trainBoxs }; -} -/** - * 获得练兵场封装信息 练兵场关卡进度,排行榜,挑战次数,和练兵场升级奖励 - * @param guildTrain - * @param roleId - * @param trainCount - * @param trainRewards - */ -export async function getGuildTrainInfo (guildTrain: GuildTrainType, roleId: string, trainCount:number, trainRewards: Array) { - let { trainId, isComplete, trainInstances, ranks } = guildTrain; - let { trainInstances: dicInstances, trainLv } = getArmyTrainJuDian(trainId); - - let battleIds: number[] = []; - for(let { hid } of dicInstances) { - let trainInfo = getGuildTrainGkInfo(trainId, hid); - if(trainInfo) battleIds.push(...trainInfo.difficulty); - } - - let battleRecords = await BattleRecordModel.findByBattleIds(roleId, battleIds, 1); - - let resTrainInstances = trainInstances.map(({hid, progress, endTime})=>{ - let dicInstance = dicInstances.find(cur => cur.hid == hid); - if(!dicInstance) return { hid, progress, endTime, isComplete: false, passedDifficult: [] } - - let trainInfo = getGuildTrainGkInfo(trainId, hid); - let passedDifficult = trainInfo.difficulty.filter(warId => { - let battleRecord = battleRecords.find(record => record.battleId == warId); - return !!battleRecord; - }) - let isComplete = progress >= dicInstance.progress; - return {hid, progress, endTime, isComplete, passedDifficult }; - }); - let resGuildTrain = {trainId, isComplete, trainInstances: resTrainInstances, myRank: 0, ranks: [] }; - - return { guildTrain: resGuildTrain, trainCount, trainRewards: transTrainReward(trainRewards, trainLv)}; -} -/** - * 解锁试炼trainId - * @param code - * @param trainId - */ -export async function unlockTrain(code: string, trainId: number) { - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); - if (!!guildTrain) { - return guildTrain; - } - let { trainInstances } = getArmyTrainJuDian(trainId); - // 初始化 - - let instances:Array = trainInstances.map(trainInstance => { - let t = new TrainInstance(); - t.hid = trainInstance.hid; - t.progress = 0; - t.endTime = 0; - t.trainBoxs = []; - return t; - }); - guildTrain = await GuildTrainModel.openGuildTrain(code, trainId, instances); - await GuildTrainReportModel.resetGuildTrainReport(code, trainId); - await GuildModel.updateInfo(code, { trainId }, {}); - - return guildTrain; -} -/** - * 重置练兵场 - * @param code - * @param serverId - */ -export async function resetTrain(code: string, serverId: number) { - let res:any = await lockData(serverId, DATA_NAME.GUILD, code);//加锁 - if (!!res.err) - return; - let { structure, trainId, resetTrainTimeDaily } = await GuildModel.findGuild(code, serverId, 'structure trainId resetTrainTimeDaily'); - // 上周试炼到的trainId - const currentTrainId = trainId; - // if(trainId && shouldRefresh(resetTrainTimeDaily, new Date())) { - // let { trainInstances } = getArmyTrainJuDian(trainId); - // // 初始化 - // let instances = trainInstances.map(trainInstance => { - // let t = new TrainInstance(); - // t.hid = trainInstance.hid; - // t.progress = 0; - // t.endTime = 0; - // t.trainBoxs = []; - // return t; - // }); - // await GuildTrainModel.updateGuildTrain(code, trainId, { trainInstances: instances }); - // await GuildModel.updateInfo(code, { resetTrainTimeDaily: new Date() }); - // } - - - let { lv } = findWhere(structure, {id: GUILD_STRUCTURE.TRAIN}); - let guild = await GuildModel.resetGuildTrain(code, serverId, lv); - res.releaseCallback();//解锁 - if (!guild) {//不满足重置条件,结束并解锁 - return trainId; - } - const userGuildList = await UserGuildModel.getListByGuild(code, 'trainRewards roleId createdAt', {}); - const guildTrains = await GuildTrainModel.getGuildTrainBoxs(code); - - const minTrainIdOfCurrentLv = gameData.firstGuildTrainIdOfLv.get(lv); - //结算未领取的宝箱奖励发送到邮件中 - userGuildList.forEach(async function ({roleId, trainRewards, createdAt}) { - if (getZeroPoint(SHOP_REFRESH_TYPE.WEEKLY) < getSeconds(createdAt)) { - // 此处发放的奖励是上周该军团的奖励; 如果本周一5AM之后,不发放 - return; - } - let goods: { id: number, count: number }[] = []; - guildTrains.forEach(guildTrain=>{ - guildTrain.trainInstances.forEach(({ trainBoxs, hid })=>{ - if (!findWhere(trainBoxs, {roleId})) { - let { heroRewards } = getGuildTrainGkInfo(guildTrain.trainId, hid); - let good = getRandSingleEelm(heroRewards); - goods.push(good); - } - }) - }); - - for (let trainId = minTrainIdOfCurrentLv; trainId < currentTrainId; trainId++) { - let { jinjieReward } = getArmyTrainJuDian(trainId); - if (trainRewards.indexOf(trainId) === -1) { - goods.push(...jinjieReward); - } - } - if (!!goods.length) { - await sendMailByContent(MAIL_TYPE.GUILD_TRAIN_REWARD, roleId, { - params: [], goods - }); - } - }); - - await sendMessageToGuildWithSuc(code, PUSH_ROUTE.GUILD_TRAIN_RESET, {}); - - await GuildTrainModel.resetGuildTrain(code);//将开启的练兵场锁定 - await unlockTrain(code, guild.trainId);//开启练兵场1级 - // 只重置上周加入军团的玩家,本周加入的不重置 - await UserGuildModel.resetTrainUserGuildLastWeekJoinedIn(code);//重置玩家的挑战次数和购买挑战次数 - return trainId -} -/** - * 检查并重置试炼 - * @param roleId - * @param serverId - */ -export async function checkResetTrain(roleId: string, serverId: number) { - let userGuild = await UserGuildModel.getMyGuild(roleId,'guildCode'); - if (!userGuild) - return; - await resetTrain(userGuild.guildCode, serverId); -} - -/** - * 成员退出删除排行奖励 - * @param guildCode - * @param roleId - * @param trainId - */ -export async function removeTrainRank(guildCode: string, roleId: string, trainId: number) { - await GuildTrainModel.removeTrainRank(guildCode, roleId, trainId); -} - -/** - * 获取军团练兵场 - * @param roleId - * @param guild - * @param userGuild - */ -export async function getGuildTrainInstance(roleId: string, guild: GuildType, userGuild: UserGuildType) { - let { trainId, trainLv, code } = guild; - let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); - if (!guildTrain) return null - let { trainCount, trainRewards, buyTrainCount } = userGuild; - let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards); - result.buyTrainCount = buyTrainCount || 0; - result.trainLv = trainLv; - return result; -} - -/** - * 检查某trainId是否可以领取 - * @param trainRewards 玩家记录中已经领取过了的试炼奖励id - * @param trainId 玩家将要领取的试炼奖励id - */ -export function checkGuildTrainReward(trainRewards: number[], trainId: number) { - let dicJudian = getArmyTrainJuDian(trainId); - if(!dicJudian) return false; - let sameIndexOfcurTrain = gameData.trainIdByIndex.get(dicJudian.index)||new Map(); - for(let [_lv, trainId] of sameIndexOfcurTrain) { - if(trainRewards.indexOf(trainId) != -1) return false; // 领取过 - } - return true -} - -/** - * 将玩家已经领取过的记录按照当前军团等级转换 - * @param lv 等级 - * @param trainRewards 玩家领取记录 - */ -export function transTrainReward(trainRewards: number[], lv: number) { - return trainRewards.map(trainId => { - let dicJudian = getArmyTrainJuDian(trainId); - let dicNewTrain = gameData.trainIdByIndex.get(dicJudian?.index)||new Map(); - return dicNewTrain?.get(lv)||0 - }) -} \ No newline at end of file +import { UserGuildModel, UserGuildType } from '@db/UserGuild'; +import { getArmyTrainJuDian, getGuildTrainGkInfo, getTrainBaseByLv } from '@pubUtils/data'; +import { nowSeconds, getZeroPoint, isToday, getSeconds, getZeroPointD } from '@pubUtils/timeUtil'; +import { GUILD_STRUCTURE, PUSH_ROUTE, SHOP_REFRESH_TYPE, WAR_TYPE } from '@consts'; +import { GuildTrainType, GuildTrainModel, TrainInstance } from '@db/GuildTrain'; +import { GuildModel, GuildType } from '@db/Guild'; +import { findWhere } from 'underscore'; +import { ARMY } from '@pubUtils/dicParam'; +import { lockData } from './redLockService'; +import { pinus } from 'pinus'; +import { MailModel, MailType } from '@db/Mail'; +import { resResult, getRandSingleEelm, shouldRefresh } from '@pubUtils/util'; +import { STATUS } from '@consts/statusCode'; +import { GuildTrainReportModel } from '@db/GuildTrainReport'; +import { DATA_NAME } from '@consts/dataName'; +import { sendMailByContent } from './mailService'; +import { MAIL_TYPE } from '@consts'; +import { getGuildChannelSid } from './chatChannelService'; +import { sendMessageToGuildWithSuc } from './pushService'; +import { gameData } from '@pubUtils/data'; +import { BattleRecordModel } from '@db/BattleRecord'; +/** + * 获得userGuild,并检查,是否需要每日重置购买挑战次数和今日挑战次数,已经检查是否需要每周重置练兵场 + * @param roleId + * @param serverId + */ +export async function refreshTrain(userGuild: UserGuildType, roleId: string, serverId: number) { + let { trainCount, trainTime, buyTrainCount, guildCode} = userGuild; + await resetTrain(guildCode, serverId);//检查重置练兵场 + if (trainTime < getZeroPoint()) {//重置挑战次数和购买次数 + trainCount = ARMY.ARMY_TRAIN_BUYTIMES; + + buyTrainCount = 0; + userGuild = await UserGuildModel.updateInfo(roleId, {trainCount, trainTime: nowSeconds(), buyTrainCount}, {}); + } + + return userGuild; +} + +export async function getTrainBoxRewardsResult(guildCode: string) { + + let guildTrains = await GuildTrainModel.findGuildTrain(guildCode);//获得未失效的宝箱奖励 + let resTrainBoxs = []; + guildTrains.forEach(({ trainInstances, trainId }) => { + let { trainInstances: instances } = getArmyTrainJuDian(trainId); + let flag = false; + let boxRewards = []; + trainInstances.map(({ hid, progress, endTime, trainBoxs }) => { + let isComplete = false; + let instance = findWhere(instances, { hid }); + if (progress >= instance.progress) { + isComplete = true; + if (endTime > nowSeconds()) + flag = true; + } + boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); + }); + if (flag) { + resTrainBoxs.push({ trainId, boxRewards }); + } + }) + return resTrainBoxs +} + +/** + * 领过的试炼宝箱不允许再领 + * + * @export + * @param {string} guildCode + * @param {number[]} receivedTrainBox: {[英雄id]:[军团id]} 表示已经领取过该英雄奖励的军团 + * @return {*} + */ +export async function getTrainBoxRewardsResultWithoutAlreadyGeted(guildCode: string, receivedTrainBox: { [hid: number]: string[] }) { + + let guildTrains = await GuildTrainModel.findGuildTrain(guildCode);//获得未失效的宝箱奖励 + let resTrainBoxs = []; + guildTrains.forEach(({ trainInstances, trainId }) => { + let { trainInstances: instances } = getArmyTrainJuDian(trainId); + let flag = false; + let boxRewards = []; + trainInstances.map(({ hid, progress, endTime, trainBoxs }) => { + let isComplete = false; + let instance = findWhere(instances, { hid }); + if (progress >= instance.progress) { + isComplete = true; + if (endTime > nowSeconds()) + flag = true; + } + // 在任何军团都未领取过 || 在本军团领取过 ==> 全部正常展示 + if (!receivedTrainBox[hid] || (receivedTrainBox[hid] && receivedTrainBox[hid].length > 0 && receivedTrainBox[hid].indexOf(guildCode) != -1)) { + boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); + } else { + // 领取过,且不是在本军团领取的 ==> 置灰、奖励不可领取 + isComplete = false; + endTime = 0; + boxRewards.push({ hid, recordBoxs: trainBoxs, trainId, endTime, isComplete }); + } + + }); + if (flag) { + resTrainBoxs.push({ trainId, boxRewards }); + } + }) + return resTrainBoxs +} + +/** + * 获得未失效的试炼宝箱奖励 + * @param guildTrain + */ +export function getGuildTrainRewards (guildTrain) { + let { trainInstances: instances } = getArmyTrainJuDian(guildTrain.trainId); + let trainBoxs = guildTrain.trainInstances.map(({hid, trainBoxs, endTime})=>{ + let instance = findWhere(instances, { hid }); + let isComplete = false; + if ( guildTrain.progress >= instance.progress) + isComplete = true; + return {hid, recordBoxs: trainBoxs, trainId: guildTrain.trainId, endTime, isComplete}; + }) + return { trainBoxs }; +} +/** + * 获得练兵场封装信息 练兵场关卡进度,排行榜,挑战次数,和练兵场升级奖励 + * @param guildTrain + * @param roleId + * @param trainCount + * @param trainRewards + */ +export async function getGuildTrainInfo (guildTrain: GuildTrainType, roleId: string, trainCount:number, trainRewards: Array) { + let { trainId, isComplete, trainInstances, ranks } = guildTrain; + let { trainInstances: dicInstances, trainLv } = getArmyTrainJuDian(trainId); + + let battleIds: number[] = []; + for(let { hid } of dicInstances) { + let trainInfo = getGuildTrainGkInfo(trainId, hid); + if(trainInfo) battleIds.push(...trainInfo.difficulty); + } + + let battleRecords = await BattleRecordModel.findByBattleIds(roleId, battleIds, 1); + + let resTrainInstances = trainInstances.map(({hid, progress, endTime})=>{ + let dicInstance = dicInstances.find(cur => cur.hid == hid); + if(!dicInstance) return { hid, progress, endTime, isComplete: false, passedDifficult: [] } + + let trainInfo = getGuildTrainGkInfo(trainId, hid); + let passedDifficult = trainInfo.difficulty.filter(warId => { + let battleRecord = battleRecords.find(record => record.battleId == warId); + return !!battleRecord; + }) + let isComplete = progress >= dicInstance.progress; + return {hid, progress, endTime, isComplete, passedDifficult }; + }); + let resGuildTrain = {trainId, isComplete, trainInstances: resTrainInstances, myRank: 0, ranks: [] }; + + return { guildTrain: resGuildTrain, trainCount, trainRewards: transTrainReward(trainRewards, trainLv)}; +} +/** + * 解锁试炼trainId + * @param code + * @param trainId + */ +export async function unlockTrain(code: string, trainId: number) { + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); + if (!!guildTrain) { + return guildTrain; + } + let { trainInstances } = getArmyTrainJuDian(trainId); + // 初始化 + + let instances:Array = trainInstances.map(trainInstance => { + let t = new TrainInstance(); + t.hid = trainInstance.hid; + t.progress = 0; + t.endTime = 0; + t.trainBoxs = []; + return t; + }); + guildTrain = await GuildTrainModel.openGuildTrain(code, trainId, instances); + await GuildTrainReportModel.resetGuildTrainReport(code, trainId); + await GuildModel.updateInfo(code, { trainId }, {}); + + return guildTrain; +} +/** + * 重置练兵场 + * @param code + * @param serverId + */ +export async function resetTrain(code: string, serverId: number) { + let res:any = await lockData(serverId, DATA_NAME.GUILD, code);//加锁 + if (!!res.err) + return; + let { structure, trainId, resetTrainTimeDaily } = await GuildModel.findGuild(code, serverId, 'structure trainId resetTrainTimeDaily'); + // 上周试炼到的trainId + const currentTrainId = trainId; + // if(trainId && shouldRefresh(resetTrainTimeDaily, new Date())) { + // let { trainInstances } = getArmyTrainJuDian(trainId); + // // 初始化 + // let instances = trainInstances.map(trainInstance => { + // let t = new TrainInstance(); + // t.hid = trainInstance.hid; + // t.progress = 0; + // t.endTime = 0; + // t.trainBoxs = []; + // return t; + // }); + // await GuildTrainModel.updateGuildTrain(code, trainId, { trainInstances: instances }); + // await GuildModel.updateInfo(code, { resetTrainTimeDaily: new Date() }); + // } + + + let { lv } = findWhere(structure, {id: GUILD_STRUCTURE.TRAIN}); + let guild = await GuildModel.resetGuildTrain(code, serverId, lv); + res.releaseCallback();//解锁 + if (!guild) {//不满足重置条件,结束并解锁 + return trainId; + } + const userGuildList = await UserGuildModel.getListByGuild(code, 'trainRewards roleId createdAt', {}); + const guildTrains = await GuildTrainModel.getGuildTrainBoxs(code); + + const minTrainIdOfCurrentLv = gameData.firstGuildTrainIdOfLv.get(lv); + //结算未领取的宝箱奖励发送到邮件中 + userGuildList.forEach(async function ({roleId, trainRewards, createdAt}) { + if (getZeroPoint(SHOP_REFRESH_TYPE.WEEKLY) < getSeconds(createdAt)) { + // 此处发放的奖励是上周该军团的奖励; 如果本周一5AM之后,不发放 + return; + } + let goods: { id: number, count: number }[] = []; + guildTrains.forEach(guildTrain=>{ + guildTrain.trainInstances.forEach(({ trainBoxs, hid })=>{ + if (!findWhere(trainBoxs, {roleId})) { + let { heroRewards } = getGuildTrainGkInfo(guildTrain.trainId, hid); + let good = getRandSingleEelm(heroRewards); + goods.push(good); + } + }) + }); + + for (let trainId = minTrainIdOfCurrentLv; trainId < currentTrainId; trainId++) { + let { jinjieReward } = getArmyTrainJuDian(trainId); + if (trainRewards.indexOf(trainId) === -1) { + goods.push(...jinjieReward); + } + } + if (!!goods.length) { + await sendMailByContent(MAIL_TYPE.GUILD_TRAIN_REWARD, roleId, { + params: [], goods + }); + } + }); + + await sendMessageToGuildWithSuc(code, PUSH_ROUTE.GUILD_TRAIN_RESET, {}); + + await GuildTrainModel.resetGuildTrain(code);//将开启的练兵场锁定 + await unlockTrain(code, guild.trainId);//开启练兵场1级 + // 只重置上周加入军团的玩家,本周加入的不重置 + await UserGuildModel.resetTrainUserGuildLastWeekJoinedIn(code);//重置玩家的挑战次数和购买挑战次数 + return trainId +} +/** + * 检查并重置试炼 + * @param roleId + * @param serverId + */ +export async function checkResetTrain(roleId: string, serverId: number) { + let userGuild = await UserGuildModel.getMyGuild(roleId,'guildCode'); + if (!userGuild) + return; + await resetTrain(userGuild.guildCode, serverId); +} + +/** + * 成员退出删除排行奖励 + * @param guildCode + * @param roleId + * @param trainId + */ +export async function removeTrainRank(guildCode: string, roleId: string, trainId: number) { + await GuildTrainModel.removeTrainRank(guildCode, roleId, trainId); +} + +/** + * 获取军团练兵场 + * @param roleId + * @param guild + * @param userGuild + */ +export async function getGuildTrainInstance(roleId: string, guild: GuildType, userGuild: UserGuildType) { + let { trainId, trainLv, code } = guild; + let guildTrain = await GuildTrainModel.findTrainByTrainIdNotLock(code, trainId); + if (!guildTrain) return null + let { trainCount, trainRewards, buyTrainCount } = userGuild; + let result: any = await getGuildTrainInfo(guildTrain, roleId, trainCount, trainRewards); + result.buyTrainCount = buyTrainCount || 0; + result.trainLv = trainLv; + return result; +} + +/** + * 检查某trainId是否可以领取 + * @param trainRewards 玩家记录中已经领取过了的试炼奖励id + * @param trainId 玩家将要领取的试炼奖励id + */ +export function checkGuildTrainReward(trainRewards: number[], trainId: number) { + let dicJudian = getArmyTrainJuDian(trainId); + if(!dicJudian) return false; + let sameIndexOfcurTrain = gameData.trainIdByIndex.get(dicJudian.index)||new Map(); + for(let [_lv, trainId] of sameIndexOfcurTrain) { + if(trainRewards.indexOf(trainId) != -1) return false; // 领取过 + } + return true +} + +/** + * 将玩家已经领取过的记录按照当前军团等级转换 + * @param lv 等级 + * @param trainRewards 玩家领取记录 + */ +export function transTrainReward(trainRewards: number[], lv: number) { + return trainRewards.map(trainId => { + let dicJudian = getArmyTrainJuDian(trainId); + let dicNewTrain = gameData.trainIdByIndex.get(dicJudian?.index)||new Map(); + return dicNewTrain?.get(lv)||0 + }) +} diff --git a/game-server/app/services/gvg/gvgBattleMemory.ts b/game-server/app/services/gvg/gvgBattleMemory.ts index fba59c034..ab8988c91 100644 --- a/game-server/app/services/gvg/gvgBattleMemory.ts +++ b/game-server/app/services/gvg/gvgBattleMemory.ts @@ -1,220 +1,220 @@ -// 存在激战期的内存数据 - -import { GVG_CATAPULT } from "../../consts"; -import { GVGTeamType } from "../../db/GVGTeam"; -import { GVGTeamMem } from "../../domain/battleField/gvgBattle"; - -export class GVGBattleData { - public groupKey: string; // 战区 - - private teams: Map = new Map(); // 队伍, teamCode => team - public rolePoints: Map> = new Map(); // roleId => pointId[],用于更新玩家的积分 - private roleToTeam: Map = new Map(); // roleId => teamCode - private leagueToTeam: Map> = new Map(); // leagueCode => teamCode - public areaToTeams: Map> = new Map(); // areaId => teamCode set,用于定时下发地图玩家数据 - private leagueActiveTech: Map = new Map(); // 千机阁状态 leagueCode => activeTech - - constructor(groupKey: string) { - this.groupKey = groupKey; - } - - public findTeamsByArea(areaId: number, count: number) { - let teamCodes = this.areaToTeams.get(areaId)||new Set(); - let otherTeams: GVGTeamMem[] = [], robots: GVGTeamMem[] = [], points: GVGTeamMem[] = []; - for(let teamCode of teamCodes) { - let team = this.teams.get(teamCode); - if(team && !team.isBroken) { - if(team.pointId > 0) { points.push(team); continue; } - if(team.isRobot) { robots.push(team); continue; } - otherTeams.push(team); - } - } - let teams = [...points, ...robots, ...otherTeams]; - return teams.slice(0, count); - } - - public findCatapultAttackTeam(areaId: number, leagueCode: string) { - let teams: GVGTeamMem[] = []; - let teamCodes = this.areaToTeams.get(areaId)||new Set(); - for(let teamCode of teamCodes) { - let team = this.teams.get(teamCode); - if(team && team.leagueCode != leagueCode && !team.isRobot) teams.push(team); - } - return teams; - } - - public leaveCity(roleId: string) { - let teamCodes = this.roleToTeam.get(roleId)||[]; - for(let teamCode of teamCodes) { - let team = this.teams.get(teamCode); - if(team) team.setCity(0); - for(let [_areaId, teamSet] of this.areaToTeams) { - if(teamSet.has(teamCode)) teamSet.delete(teamCode); - } - if(team.leagueCode && this.leagueToTeam.has(team.leagueCode)) - this.leagueToTeam.get(team.leagueCode).delete(teamCode); - } - this.rolePoints.delete(roleId); - } - - public enterCity(...teams: GVGTeamType[]) { - for(let team of teams) { - let fromAreaId = this.teams.get(team.teamCode)?.areaId||0; - - if(!this.teams.has(team.teamCode)) { - this.teams.set(team.teamCode, new GVGTeamMem(team)) - } else { - this.teams.get(team.teamCode).updateTeam(team); - } - this.teams.get(team.teamCode).setCity(team.cityId, team.areaId, team.pointId); - if(team.pointId > 0 && !team.isRobot) { - if(!this.rolePoints.has(team.roleId)) this.rolePoints.set(team.roleId, new Map()); - for(let [pointId, teamCode] of this.rolePoints.get(team.roleId)) { - if(teamCode == team.teamCode) this.rolePoints.get(team.roleId).delete(pointId); - } - this.rolePoints.get(team.roleId).set(team.pointId, team.teamCode); - } - let teamCodesOfRole = this.roleToTeam.get(team.roleId)||[]; - if(teamCodesOfRole.indexOf(team.teamCode) == -1) teamCodesOfRole.push(team.teamCode); - this.roleToTeam.set(team.roleId, teamCodesOfRole); - if(team.leagueCode) { - if(!this.leagueToTeam.has(team.leagueCode)) { - this.leagueToTeam.set(team.leagueCode, new Set()); - } - if(!this.leagueToTeam.get(team.leagueCode).has(team.teamCode)) - this.leagueToTeam.get(team.leagueCode).add(team.teamCode); - } - - this.setAreaMap(team.teamCode, fromAreaId, team.areaId, 'enterCity'); - } - } - - private setAreaMap(teamCode: string, fromAreaId: number, toAreaId: number, fromFun) { - if(fromAreaId == toAreaId) return; - // console.log('#### gvgBattleMemory setAreaMap', 'teamCode:', teamCode, 'fromAreaId: ', fromAreaId, 'toAreaId:', toAreaId, 'appid', pinus.app.getServerId(), 'from', fromFun) - let fromAreaSet = this.areaToTeams.get(fromAreaId); - if(fromAreaSet && fromAreaSet.has(teamCode)) fromAreaSet.delete(teamCode); - - if(!this.areaToTeams.has(toAreaId)) { - this.areaToTeams.set(toAreaId, new Set()); - } - if(!this.areaToTeams.get(toAreaId).has(teamCode)) { - this.areaToTeams.get(toAreaId).add(teamCode); - } - } - - private setRolePoints(roleId: string, fromPointId: number, pointId: number, teamCode: string) { - if(fromPointId > 0) { // 被打得撤离积分点 - if(this.rolePoints.has(roleId) && this.rolePoints.get(roleId).has(fromPointId)) { - this.rolePoints.get(roleId).delete(fromPointId); - } - } - if (pointId > 0) { - if(!this.rolePoints.has(roleId)) this.rolePoints.set(roleId, new Map()); - this.rolePoints.get(roleId).set(pointId, teamCode); - } - } - - public move(teamCode: string, areaId: number, fromAreaId: number, startMoveTime: number, stopMoveTime: number) { - let team = this.teams.get(teamCode); - if(!team) return; - team.moveToArea(areaId, fromAreaId, startMoveTime, stopMoveTime); - this.setAreaMap(teamCode, fromAreaId, areaId, 'move'); - } - - public setTime(teamCode: string, teamUpdate: GVGTeamType) { - let team = this.teams.get(teamCode); - if(!team) return; - team.attackTime = teamUpdate.attackTime; - team.defenseTime = teamUpdate.defenseTime; - } - - // 队伍入驻积分点 - public teamSettle(roleId: string, teamCode: string, pointId: number) { - let teamMem = this.teams.get(teamCode); - if(!teamMem) return; - let { pointId: fromPointId } = teamMem; - this.setRolePoints(roleId, fromPointId, pointId, teamCode); - teamMem.pointId = pointId; -} - - // 关卡结算 - public battleEnd(teams: GVGTeamType[]) { - for(let team of teams) { - let teamMem = this.teams.get(team.teamCode); - if(!teamMem) { // 基本不会有没有这个内存的情况,有的话就让他重新计算一次吧 - this.enterCity(team); continue; - } - let { curTeamBreak, pointId } = team; - let { areaId: fromAreaId, pointId: originPointId } = teamMem; - teamMem.updateTeam(team); - this.setRolePoints(team.roleId, originPointId, curTeamBreak? 0: pointId, team.teamCode); - this.setAreaMap(team.teamCode, fromAreaId, team.areaId, 'battleEnd'); - } - } - - // 投石车 - public findCatapult() { - return this.findTeamsByRole(GVG_CATAPULT); - } - - public findTeamsByRole(roleId: string) { - let teamCodes = this.roleToTeam.get(roleId)||[]; - return teamCodes.map(teamCode => this.teams.get(teamCode)); - } - - // 积分点情况 - public findSettledPoint() { - let teams: GVGTeamMem[] = []; - for(let [_roleId, pointIds] of this.rolePoints) { - for(let [pointId, teamCode] of pointIds) { - let team = this.teams.get(teamCode); - if(pointId > 0 && team) teams.push(team); - } - } - return teams; - } - - public findSettledPointMapByLeague(cityId: number) { - let pointByLeague = new Map(); - for(let [_roleId, pointIds] of this.rolePoints) { - for(let [pointId, teamCode] of pointIds) { - let team = this.teams.get(teamCode); - if(pointId > 0 && team && team.leagueCode && team.cityId == cityId) { - if(!pointByLeague.has(team.leagueCode)) pointByLeague.set(team.leagueCode, []); - pointByLeague.get(team.leagueCode).push(team.pointId); - }; - } - } - return pointByLeague; - } - - public findAreas() { - return this.areaToTeams.keys(); - } - - public updateLeagueInfo(leagueCode: string, leagueName: string) { - let teamCodes = this.leagueToTeam.get(leagueCode)||new Set(); - for(let teamCode of teamCodes) { - let team = this.teams.get(teamCode); - team.leagueName = leagueName; - } - } - - public updateRoleInfo(roleId: string, info: { roleName?: string, lv?: number }) { - let teamCodes = this.leagueToTeam.get(roleId)||new Set(); - for(let teamCode of teamCodes) { - let team = this.teams.get(teamCode); - if(info.roleName) team.roleName = info.roleName; - if(info.lv) team.lv = info.lv; - } - } - - public getLeagueTech(leagueCode: string) { - return this.leagueActiveTech.get(leagueCode); - } - - public setLeagueTech(leagueCode: string, activeTech: number[]) { - this.leagueActiveTech.set(leagueCode, activeTech); - } -} \ No newline at end of file +// 存在激战期的内存数据 + +import { GVG_CATAPULT } from "@consts"; +import { GVGTeamType } from "@db/GVGTeam"; +import { GVGTeamMem } from "@domain/battleField/gvgBattle"; + +export class GVGBattleData { + public groupKey: string; // 战区 + + private teams: Map = new Map(); // 队伍, teamCode => team + public rolePoints: Map> = new Map(); // roleId => pointId[],用于更新玩家的积分 + private roleToTeam: Map = new Map(); // roleId => teamCode + private leagueToTeam: Map> = new Map(); // leagueCode => teamCode + public areaToTeams: Map> = new Map(); // areaId => teamCode set,用于定时下发地图玩家数据 + private leagueActiveTech: Map = new Map(); // 千机阁状态 leagueCode => activeTech + + constructor(groupKey: string) { + this.groupKey = groupKey; + } + + public findTeamsByArea(areaId: number, count: number) { + let teamCodes = this.areaToTeams.get(areaId)||new Set(); + let otherTeams: GVGTeamMem[] = [], robots: GVGTeamMem[] = [], points: GVGTeamMem[] = []; + for(let teamCode of teamCodes) { + let team = this.teams.get(teamCode); + if(team && !team.isBroken) { + if(team.pointId > 0) { points.push(team); continue; } + if(team.isRobot) { robots.push(team); continue; } + otherTeams.push(team); + } + } + let teams = [...points, ...robots, ...otherTeams]; + return teams.slice(0, count); + } + + public findCatapultAttackTeam(areaId: number, leagueCode: string) { + let teams: GVGTeamMem[] = []; + let teamCodes = this.areaToTeams.get(areaId)||new Set(); + for(let teamCode of teamCodes) { + let team = this.teams.get(teamCode); + if(team && team.leagueCode != leagueCode && !team.isRobot) teams.push(team); + } + return teams; + } + + public leaveCity(roleId: string) { + let teamCodes = this.roleToTeam.get(roleId)||[]; + for(let teamCode of teamCodes) { + let team = this.teams.get(teamCode); + if(team) team.setCity(0); + for(let [_areaId, teamSet] of this.areaToTeams) { + if(teamSet.has(teamCode)) teamSet.delete(teamCode); + } + if(team.leagueCode && this.leagueToTeam.has(team.leagueCode)) + this.leagueToTeam.get(team.leagueCode).delete(teamCode); + } + this.rolePoints.delete(roleId); + } + + public enterCity(...teams: GVGTeamType[]) { + for(let team of teams) { + let fromAreaId = this.teams.get(team.teamCode)?.areaId||0; + + if(!this.teams.has(team.teamCode)) { + this.teams.set(team.teamCode, new GVGTeamMem(team)) + } else { + this.teams.get(team.teamCode).updateTeam(team); + } + this.teams.get(team.teamCode).setCity(team.cityId, team.areaId, team.pointId); + if(team.pointId > 0 && !team.isRobot) { + if(!this.rolePoints.has(team.roleId)) this.rolePoints.set(team.roleId, new Map()); + for(let [pointId, teamCode] of this.rolePoints.get(team.roleId)) { + if(teamCode == team.teamCode) this.rolePoints.get(team.roleId).delete(pointId); + } + this.rolePoints.get(team.roleId).set(team.pointId, team.teamCode); + } + let teamCodesOfRole = this.roleToTeam.get(team.roleId)||[]; + if(teamCodesOfRole.indexOf(team.teamCode) == -1) teamCodesOfRole.push(team.teamCode); + this.roleToTeam.set(team.roleId, teamCodesOfRole); + if(team.leagueCode) { + if(!this.leagueToTeam.has(team.leagueCode)) { + this.leagueToTeam.set(team.leagueCode, new Set()); + } + if(!this.leagueToTeam.get(team.leagueCode).has(team.teamCode)) + this.leagueToTeam.get(team.leagueCode).add(team.teamCode); + } + + this.setAreaMap(team.teamCode, fromAreaId, team.areaId, 'enterCity'); + } + } + + private setAreaMap(teamCode: string, fromAreaId: number, toAreaId: number, fromFun) { + if(fromAreaId == toAreaId) return; + // console.log('#### gvgBattleMemory setAreaMap', 'teamCode:', teamCode, 'fromAreaId: ', fromAreaId, 'toAreaId:', toAreaId, 'appid', pinus.app.getServerId(), 'from', fromFun) + let fromAreaSet = this.areaToTeams.get(fromAreaId); + if(fromAreaSet && fromAreaSet.has(teamCode)) fromAreaSet.delete(teamCode); + + if(!this.areaToTeams.has(toAreaId)) { + this.areaToTeams.set(toAreaId, new Set()); + } + if(!this.areaToTeams.get(toAreaId).has(teamCode)) { + this.areaToTeams.get(toAreaId).add(teamCode); + } + } + + private setRolePoints(roleId: string, fromPointId: number, pointId: number, teamCode: string) { + if(fromPointId > 0) { // 被打得撤离积分点 + if(this.rolePoints.has(roleId) && this.rolePoints.get(roleId).has(fromPointId)) { + this.rolePoints.get(roleId).delete(fromPointId); + } + } + if (pointId > 0) { + if(!this.rolePoints.has(roleId)) this.rolePoints.set(roleId, new Map()); + this.rolePoints.get(roleId).set(pointId, teamCode); + } + } + + public move(teamCode: string, areaId: number, fromAreaId: number, startMoveTime: number, stopMoveTime: number) { + let team = this.teams.get(teamCode); + if(!team) return; + team.moveToArea(areaId, fromAreaId, startMoveTime, stopMoveTime); + this.setAreaMap(teamCode, fromAreaId, areaId, 'move'); + } + + public setTime(teamCode: string, teamUpdate: GVGTeamType) { + let team = this.teams.get(teamCode); + if(!team) return; + team.attackTime = teamUpdate.attackTime; + team.defenseTime = teamUpdate.defenseTime; + } + + // 队伍入驻积分点 + public teamSettle(roleId: string, teamCode: string, pointId: number) { + let teamMem = this.teams.get(teamCode); + if(!teamMem) return; + let { pointId: fromPointId } = teamMem; + this.setRolePoints(roleId, fromPointId, pointId, teamCode); + teamMem.pointId = pointId; +} + + // 关卡结算 + public battleEnd(teams: GVGTeamType[]) { + for(let team of teams) { + let teamMem = this.teams.get(team.teamCode); + if(!teamMem) { // 基本不会有没有这个内存的情况,有的话就让他重新计算一次吧 + this.enterCity(team); continue; + } + let { curTeamBreak, pointId } = team; + let { areaId: fromAreaId, pointId: originPointId } = teamMem; + teamMem.updateTeam(team); + this.setRolePoints(team.roleId, originPointId, curTeamBreak? 0: pointId, team.teamCode); + this.setAreaMap(team.teamCode, fromAreaId, team.areaId, 'battleEnd'); + } + } + + // 投石车 + public findCatapult() { + return this.findTeamsByRole(GVG_CATAPULT); + } + + public findTeamsByRole(roleId: string) { + let teamCodes = this.roleToTeam.get(roleId)||[]; + return teamCodes.map(teamCode => this.teams.get(teamCode)); + } + + // 积分点情况 + public findSettledPoint() { + let teams: GVGTeamMem[] = []; + for(let [_roleId, pointIds] of this.rolePoints) { + for(let [pointId, teamCode] of pointIds) { + let team = this.teams.get(teamCode); + if(pointId > 0 && team) teams.push(team); + } + } + return teams; + } + + public findSettledPointMapByLeague(cityId: number) { + let pointByLeague = new Map(); + for(let [_roleId, pointIds] of this.rolePoints) { + for(let [pointId, teamCode] of pointIds) { + let team = this.teams.get(teamCode); + if(pointId > 0 && team && team.leagueCode && team.cityId == cityId) { + if(!pointByLeague.has(team.leagueCode)) pointByLeague.set(team.leagueCode, []); + pointByLeague.get(team.leagueCode).push(team.pointId); + }; + } + } + return pointByLeague; + } + + public findAreas() { + return this.areaToTeams.keys(); + } + + public updateLeagueInfo(leagueCode: string, leagueName: string) { + let teamCodes = this.leagueToTeam.get(leagueCode)||new Set(); + for(let teamCode of teamCodes) { + let team = this.teams.get(teamCode); + team.leagueName = leagueName; + } + } + + public updateRoleInfo(roleId: string, info: { roleName?: string, lv?: number }) { + let teamCodes = this.leagueToTeam.get(roleId)||new Set(); + for(let teamCode of teamCodes) { + let team = this.teams.get(teamCode); + if(info.roleName) team.roleName = info.roleName; + if(info.lv) team.lv = info.lv; + } + } + + public getLeagueTech(leagueCode: string) { + return this.leagueActiveTech.get(leagueCode); + } + + public setLeagueTech(leagueCode: string, activeTech: number[]) { + this.leagueActiveTech.set(leagueCode, activeTech); + } +} diff --git a/game-server/app/services/gvg/gvgBattleService.ts b/game-server/app/services/gvg/gvgBattleService.ts index b06f50b8c..2e124a065 100644 --- a/game-server/app/services/gvg/gvgBattleService.ts +++ b/game-server/app/services/gvg/gvgBattleService.ts @@ -1,973 +1,973 @@ -import { GVGTeamMem } from "../../domain/battleField/gvgBattle"; -import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague"; -import GVGTeam, { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from "../../db/GVGTeam"; -import { GVGCityModel, GVGCityType } from "../../db/GVGCity"; -import { gameData, getGVGBattleRankReward } from "../../pubUtils/data"; -import { COUNTER, GVG_AREA_TYPE, GVG_ATTACK_TYPE, GVG_BATTLE_RANK_TYPE, GVG_PERIOD, GVG_POINT_TYPE, GVG_SERVER_TYPE, GVG_TECH_TYPE, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, SERVER_GROUP_FUN_TYPE, STATUS } from "../../consts"; -import { getTimeFun, nowSeconds } from "../../pubUtils/timeUtil"; -import { DicGVGAreaPoint } from "../../pubUtils/dictionary/DicGVGAreaPoint"; -import { getGVGBattleData, getGVGBattleMap } from "../memoryCache/gvgBattleData"; -import { GVGAttackSpine, GVGCityMapInfo, GVGEnemies, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, GVGTeamSpineInfo, GVGWinStreakInfo } from "../../domain/gvgField/returnData"; -import { GVG } from "../../pubUtils/dicParam"; -import { GVGHeroInfo, PvpEnemies, PvpHeroInfo } from "../../domain/dbGeneral"; -import { getGroupKey, getGVGConfig, getGVGConfigFromRemote, getGVGPeriodData, getGVGServerType } from "./gvgService"; -import { GVGLeaguePrepareModel } from "../../db/GVGLeaguePrepare"; -import { pinus } from "pinus"; -import { dispatch } from "../../pubUtils/dispatcher"; -import { Rank } from "../rankService"; -import { KeyNameParam, LeagueRankInfo, myIdInter, RoleRankInfo } from "../../domain/rank"; -import { findKeys, getAllServerName, getServerName, redisClient } from "../redisService"; -import { sendMessageToGVGAreaByTeamWithSuc, sendMessageToGVGAreaWithSuc, sendMessageToGVGCityWithSuc, sendMessageToUserWithSuc } from "../pushService"; -import { sendMailByContent, sendMailToLeagueByContent } from "../mailService"; -import { GVGCityAreaPointModel } from "../../db/GVGCityAreaPoint"; -import { addCityGuardMessage } from "./gvgRecService"; -import { GVGUserDataModel } from "../../db/GVGUserData"; -import { RoleModel } from "../../db/Role"; -import { getFightTimeByPeriod } from "./gvgFightService"; -import { getRandSingleEelm, parseNumberList } from "../../pubUtils/util"; -import { HeroModel, HeroType } from "../../db/Hero"; -import { ArtifactModel } from "../../db/Artifact"; -import { getHeroesAttributes } from "../playerCeService"; -import { CounterModel } from "../../db/Counter"; -import { getGroupIdOfServer } from "../serverService"; -import { LineupHero } from "../../domain/roleField/hero"; -import { gvgEndParamInter } from "../../pubUtils/interface"; - -/** - * 获取本联军上周占领的城池 - * @param league - * @returns number[] 城池id - */ -export async function getGVGCities(league: GVGLeagueType) { - let { configId } = getGVGConfig(); - let cities = await GVGCityModel.findGuardCityByLeague(configId, league.leagueCode, 'cityId'); - return cities.map(city => city.cityId); -} - -/** - * 获取当前城池状态 - * @returns [{cityId: number, guardLeagueCode: string, guardLeagueName: string, teamCnt: number }] - */ -export async function getGVGCitiesInfo(configId: number, groupKey: string, league?: GVGLeagueType) { - let cities = await GVGCityModel.findGuardCity(configId, groupKey); - let result: GVGCityMapInfo[] = []; - for(let city of cities) { - let obj = new GVGCityMapInfo(city.cityId); - obj.setCity(city); - if(league) { - let players = (city.players||[]).filter(cur => cur.leagueCode == league.leagueCode); - obj.setTeamCnt(players.length); - let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId: city.cityId }); - let score = await r.getMyScore({ leagueCode: league.leagueCode }); - obj.setScore(score||0); - } - result.push(obj); - } - return result; -} - -export async function getAllGVGCitiesInfo(configId: number, groupKey: string, serverType: number) { - let cities = await GVGCityModel.findGuardCity(configId, groupKey); - let result: GVGCityMapInfo[] = []; - for(let [cityId, { mapType }] of gameData.gvgCity) { - if(mapType != serverType) continue; - let obj = new GVGCityMapInfo(cityId); - let city = cities.find(cur => cur.cityId == cityId); - obj.setCity(city); - result.push(obj); - } - return result -} - -/** - * 获取内存中队伍的数据结构 - */ -export function getGVGTeamMemInfo(team: GVGTeamType): GVGTeamMem { - const teamMem = new GVGTeamMem(team); - teamMem.isMoving = false; - teamMem.startMoveTime = 0; - teamMem.stopMoveTime = 0; - return teamMem; -} - -/** - * 获取 重新进入城池/复活 所在的区域 - * @param city GVGCity - * @param leagueCode 联军id - * @returns - */ -export function getBirthAreaOfCity(city: GVGCityType, leagueCode: string) { - let isGuard = city.guardLeague == leagueCode; - let dicGVGCity = gameData.gvgCity.get(city.cityId); - return isGuard? dicGVGCity.defenseBirth: dicGVGCity.attackBirth; -} - -/** - * 玩家是否可以进入城池 - * @param city - * @param leagueCode - * @returns - */ -export function checkEnterCityTime(city: GVGCityType, leagueCode: string) { - let isGuard = city?.guardLeague == leagueCode; - let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.BATTLE); - if(isGuard && startFightTime - GVG.GVG_GUARD_START_TIME > nowSeconds()) return false; - if(!isGuard && startFightTime > nowSeconds()) return false; - if(endFightTime < nowSeconds()) return false; - return true -} - -// guild.gvgBattleHandler.startMove 检测 -export function checkMoveStatus(team: GVGTeamType, cityId: number, areaId: number) { - if(!team) return STATUS.GVG_BATTLE_TEAM_NOT_FOUND; - if(team.cityId != cityId) return STATUS.GVG_BATTLE_IS_NOT_IN_CITY; - if(team.pointId > 0) return STATUS.GVG_BATTLE_TEAM_IS_SELLTED; - if(team.stopMoveTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING; - if(team.moveCdTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING_CD; - if(team.lockTime > nowSeconds()) return STATUS.GVG_TEAM_DEFENSEING; - if(team.restartTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_REVIVE; - let dicArea = gameData.gvgArea.get(areaId); - if(!dicArea) return STATUS.DIC_DATA_NOT_FOUND; - if(dicArea.relateArea.indexOf(team.areaId) == -1) return STATUS.GVG_BATTLE_AREA_NOT_RELATE; - return STATUS.SUCCESS; -} - -export function checkSettleStatus(team: GVGTeamType) { - if(!team) return STATUS.GVG_BATTLE_TEAM_NOT_FOUND; - if(team.stopMoveTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING; - // if(team.moveCdTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING_CD; - if(team.lockTime > nowSeconds()) return STATUS.GVG_TEAM_DEFENSEING; - if(team.restartTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_REVIVE; - return STATUS.SUCCESS; -} - -export async function initRobots(configId: number, groupKey: string, city: GVGCityType | { cityId: number, guardLeague: string }) { - let { cityId, guardLeague = '' } = city; - if(guardLeague) return []; - let robotTeams = await GVGTeamModel.findRobotTeams(configId, groupKey, cityId); - let updateDicPoints: DicGVGAreaPoint[] = []; - let { battleAreaIds = []} = gameData.gvgCity.get(cityId); - for(let areaId of battleAreaIds) { - let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; - for(let pointId of pointIds) { - let dicPoint = gameData.gvgAreaPoint.get(pointId); - if(!dicPoint || dicPoint.type != GVG_POINT_TYPE.ROBOT) continue; - let robotTeam = robotTeams.find(team => team.pointId == dicPoint.pointId); - if(!robotTeam || (!robotTeam.isBroken && robotTeam.configId != configId) ) { - updateDicPoints.push(dicPoint); - } - } - } - if(updateDicPoints.length > 0) { - let lv = gameData.war.get(GVG.GVG_ROBOT_WARJSON)?.level||50; - robotTeams = await GVGTeamModel.initRobots(configId, groupKey, cityId, updateDicPoints, lv); - // 存入内存 - let teamObj = getGVGBattleData(groupKey); - teamObj.enterCity(...robotTeams); - } - return robotTeams; -} - -export function checkAreaIsInCity(cityId: number, areaIds: number[]) { - let dicCity = gameData.gvgCity.get(cityId); - if(!dicCity) return false; - for(let areaId of areaIds) { - if(dicCity.areaIds.indexOf(areaId) == -1) return false; - } - return true; -} - -export function calBattleScoreByCe(isSuccess: boolean, lineupCe: number) { - let winScore = Math.floor(lineupCe/GVG.GVG_BATTLE_SCORE); - if(winScore <= 0) winScore = 1; - return isSuccess? winScore: 0; -} - -export async function refreshTeams(configId: number, groupKey: string, roleId: string, myLeague: GVGLeagueType, hasConfirm: boolean) { - let oldTeams = await GVGTeamModel.findByRole(roleId, '-_id'); - let teams: GVGTeamType[] = []; - for(let team of oldTeams) { - if(team.configId != configId || (hasConfirm && team.confirmConfigId != configId)) { - let { teamCode, maxDurability, lineup } = team; - let { lv, title, roleName, guildCode } = await RoleModel.findByRoleId(roleId, 'lv title roleName guildCode'); - let heroes = await HeroModel.findByHidRange(lineup.map(hero => hero.actorId), roleId); - let { newLineup, newLineupCe } = await generNewLineup(roleId, heroes, lineup.map(({ actorId, dataId, outIndex }) => ({ actorId, dataId, order: outIndex }))); - let addUpdate = hasConfirm? { confirmConfigId: configId }: {}; - let newTeam = await GVGTeamModel.refreshByConfig(teamCode, { configId, lv, title, durability: maxDurability, cityId: 0, areaId: 0, pointId: 0, roleName, guildCode, leagueCode: myLeague.leagueCode, leagueName: myLeague.name, groupKey, lineup: newLineup, lineupCe: newLineupCe, ...addUpdate }); - teams.push(newTeam); - } else { - teams.push(team); - } - } - return teams -} - -export async function generNewLineup(roleId: string, heroes: HeroType[], lineup: { actorId: number, dataId: number, order: number, subHid?: number }[]) { - let attrByHid = await getHeroesAttributes(roleId); - let newLineup: GVGHeroInfo[] = [], newLineupCe = 0; - for(let { actorId, dataId, order, subHid } of lineup) { - let hero = heroes.find(cur => cur.hid == actorId); - if(hero) { - let artifact = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; - let heroInfo = new GVGHeroInfo(); - heroInfo.setHeroInfo(hero, artifact, []); - heroInfo.setDataId(dataId, order); - let subHero = heroes.find(cur => cur.hid == subHid); - if(subHero) heroInfo.setSubHero(subHero); - - let attr = attrByHid.get(actorId); - if(!attr) continue; - let attribute = attr.getAttributesToString(); - heroInfo.setAttribute(attribute); - - newLineup.push(heroInfo); - newLineupCe += hero.ce; - } - } - return { newLineup, newLineupCe }; -} - -/** - * 离开城池 - * 当玩家占领据点的时候,可以保留据点;不占领的时候,不保留;退出游戏的时候,全不保留 - * @param isForce 是否是玩家关闭游戏的那种离开 - * @param roleId - * @param serverId - * @param guildCode - * @param myLeague - * @returns - */ -export async function leaveCity(isForce: boolean, roleId: string, serverId: number, guildCode: string, myLeague?: GVGLeagueType) { - if(!myLeague) myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); - let groupKey = await getGroupKey(serverId); - let { configId } = await getGVGConfigFromRemote(); - let teams = await GVGTeamModel.findByRole(roleId); - let hasPoint = !!teams.find(team => team.pointId > 0); - - // console.log('######### leaveCity', configId, groupKey) - if(isForce || !hasPoint) { - await GVGTeamModel.leaveCity(roleId); - await GVGCityModel.decreasePlayer(configId, groupKey, roleId); - if(myLeague) await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, 0); - await GVGCityAreaPointModel.playerLeave(configId, groupKey, roleId); - // 处理内存数据 - await pinus.app.rpc.guild.guildRemote.leaveCityMem.broadcast(groupKey, roleId); - for(let team of teams) { - if(team.cityId > 0 && team.areaId > 0) { - await sendAreaLeaveMsg(groupKey, team.areaId, team.cityId, team.teamCode); - } - } - } -} - -export async function leaveCityMem(groupKey: string, roleId: string) { - let teamObj = getGVGBattleData(groupKey); - teamObj.leaveCity(roleId); -} - -// 复活cd -export async function getTechReviveMinus(groupKey: string, configId: number, leagueCode: string) { - let teamObj = getGVGBattleData(groupKey); - let activeTech = teamObj.getLeagueTech(leagueCode); - if(!activeTech) { - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); - activeTech = leaguePrepare?.activeTech||[]; - teamObj.setLeagueTech(leagueCode, activeTech); - } - let minusCd = 0; - for(let techId of activeTech) { - let dicTech = gameData.gvgTech.get(techId); - if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_REVIVE_GAP) { - minusCd += dicTech.param[0]; - } - } - let cd = GVG.GVG_DEFAULT_REVIVE_CD - minusCd; - if(cd < 0) cd = 0; - - return cd; -} - -// 诸葛连弩的伤害 -export async function getTechKnifeHurt(configId: number, leagueCode: string) { - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); - let hurt = 0; - let activeTech = leaguePrepare?.activeTech||[]; - for(let techId of activeTech) { - let dicTech = gameData.gvgTech.get(techId); - if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) { - if(dicTech.param[2] > hurt) hurt = dicTech.param[2]; - } - } - return hurt -} - -export function getGVGWarId(defenseTeam: GVGTeamType) { - if(!defenseTeam.isRobot) return GVG.GVG_CITY_BGMAP_GKID; // 玩家防守地图 - if(!defenseTeam.isCatapult) return GVG.GVG_CATAPULT_WARJSON; // 投石车使用 - return GVG.GVG_ROBOT_WARJSON; // 据点守卫使用 -} - -// guild.gvgBattleHandler.battleStart 里的heroes返回 -export function getOppHeroes(warId: number, isRobot: boolean, lineup: GVGHeroInfo[]) { - let heroes: GVGEnemies[] = []; - const dicWar = gameData.war.get(warId); - if(!dicWar) { console.error(`warId ${warId} not found`); return [] } - const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId)||[]; - for(let warJson of dicWarJson) { - if(!isRobot) { - let heroInfo = lineup.find(cur => cur.dataId == warJson.dataId); - if(!heroInfo) continue; - let hero = new GVGEnemies(warJson, heroInfo); - heroes.push(hero); - } else { - if(warJson.relation == 2) { - let dicHero = gameData.hero.get(warJson.actorId); - if(!dicHero) continue; - let heroInfo = new GVGHeroInfo(); - heroInfo.setRobotInfo(dicHero, warJson.lv); - let hero = new GVGEnemies(warJson, heroInfo); - heroes.push(hero); - } - } - } - return heroes -} - -// guild.gvgBattleHandler.battleStart 检测 -export function checkGVGBattleStart(roleId: string, attackTeam: GVGTeamType, defenseTeam: GVGTeamType) { - - if(!attackTeam || !defenseTeam) return STATUS.GVG_BATTLE_TEAM_INVALID; - if(attackTeam.roleId != roleId) return STATUS.GVG_TEAM_IS_NOT_MINE; - if(attackTeam.leagueCode == defenseTeam.leagueCode) return STATUS.GVG_SAME_LEAGUE_CANNOT_ATTACK; - if(attackTeam.areaId != defenseTeam.areaId) return STATUS.GVG_TEAM_NOT_SAME_AREA; - - if(attackTeam.attackTime > nowSeconds()) return STATUS.GVG_TEAM_ATTACKING; - if(defenseTeam.defenseTime > nowSeconds() || defenseTeam.lockTime > nowSeconds()) { - return defenseTeam.isRobot? STATUS.GVG_ROBOT_DEFENSEING: STATUS.GVG_TEAM_DEFENSEING; - } - - if(attackTeam.lockTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_LOCK; - if(attackTeam.durability <= 0) return STATUS.GVG_ATTACK_TEAM_BROKEN; - if(defenseTeam.durability <= 0) return STATUS.GVG_DEFENSE_TEAM_BROKEN; - - return STATUS.SUCCESS; -} - -export function getNewLineup(team: GVGTeamType, newInfo: gvgEndParamInter[]) { - if (team.isRobot) return { isAllDead: false, newLineup: team.lineup}; - let isAllDead = team.curTeamBreak || checkAllDead(team.lineup, newInfo); - let newLineup: GVGHeroInfo[] = []; - for(let hero of team.lineup) { - if (isAllDead) { - hero.hp = "max"; - hero.maxHp = "max"; - hero.others = ''; - } else { - let info = newInfo.find(cur => cur.actorId == hero.actorId); - if (info) { - hero.hp = info.hp; - hero.maxHp = info.maxHp; - hero.others = info.others; - } - } - - newLineup.push(hero); - } - return { isAllDead, newLineup }; -} - -// 检查本场战斗武将是否死光了 -export function checkAllDead(oldLineup: GVGHeroInfo[], newInfo: gvgEndParamInter[]) { - for(let hero of oldLineup) { - let curInfo = newInfo.find(cur => cur.actorId == hero.actorId); - if (!curInfo || curInfo.hp > 0) return false; - } - return true; -} - -// —————————— 定时器相关 —————————— // -// gvg激战期开始定时器 -export async function gvgBattleStart() { - - let { configId } = getGVGConfig(); - let guardCities = await GVGCityModel.findAllGuardCities(configId); - for(let { cityId, groupKey, guardLeague, guardLeagueName } of guardCities) { - let sid = await dispatchTeam(groupKey, cityId); - await pinus.app.rpc.guild.guildRemote.initCatapult.toServer(sid, cityId, groupKey, guardLeague, guardLeagueName); - } -} - -// 每次活动开始初始化投石车 -export async function initCatapult(cityId: number, groupKey: string, leagueCode: string, leagueName: string) { - let { configId } = getGVGConfig(); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); - let activeTech = leaguePrepare?.activeTech||[]; - let hasCatapult = false, atk = 0, durability = 0; - for(let techId of activeTech) { - let dicTech = gameData.gvgTech.get(techId); - if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_CATAPULT) { - hasCatapult = true, atk = dicTech.param[0]; durability = dicTech.param[1]; - } - } - if(hasCatapult) { - let updateDicPoints: DicGVGAreaPoint[] = []; - let { catapultAreaIds = []} = gameData.gvgCity.get(cityId); - for(let areaId of catapultAreaIds) { - let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; - for(let pointId of pointIds) { - let dicPoint = gameData.gvgAreaPoint.get(pointId); - if(!dicPoint || dicPoint.type != GVG_POINT_TYPE.CATAPULT) continue; - updateDicPoints.push(dicPoint); - } - } - - let lv = gameData.war.get(GVG.GVG_CATAPULT_WARJSON)?.level||50; - let teams = await GVGTeamModel.initCatapult(configId, groupKey, cityId, updateDicPoints, leagueCode, leagueName, atk, durability, lv); - // 处理内存 - let teamObj = getGVGBattleData(groupKey); - teamObj.enterCity(...teams); - } -} - -// 投石车投伤害 -export async function catapultHurt() { - let { configId, period } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - if(nowSeconds() < startFightTime || nowSeconds() > endFightTime) return; - for(let [_key, teamObj] of getGVGBattleMap()) { - let teams = teamObj.findCatapult(); - for(let catapult of teams) { - let dicGVGCity = gameData.gvgCity.get(catapult?.cityId); - let battleAreaIds = dicGVGCity?.battleAreaIds||[] - if(!catapult || catapult.isBroken || !dicGVGCity || battleAreaIds.length <= 0) continue; - let areaId = getRandSingleEelm(battleAreaIds); - // let areaId = catapult.cityId * 100 + 2; - let teamMems = teamObj.findCatapultAttackTeam(areaId, catapult.leagueCode); - let teams: GVGTeamType[] = []; - for(let { teamCode, leagueCode } of teamMems) { - let team = await GVGTeamModel.attackByCatapult(teamCode, catapult.captapultAtk, dicGVGCity.attackBirth, await getTechReviveMinus(teamObj.groupKey, configId, leagueCode)); - teams.push(team); - } - teamObj.battleEnd(teams); - if(teams.length > 0) { - let roleToTeams = new Map(); - let areaTeams: GVGTeamInList[] = []; - for(let team of teams) { - await pushTeamBeHurtMessage(team); - if(team.curTeamBreak && team.originPointId > 0) { - await GVGCityAreaPointModel.leavePoint(configId, teamObj.groupKey, team.teamCode); - } - if(!roleToTeams.has(team.roleId)) roleToTeams.set(team.roleId, []); - roleToTeams.get(team.roleId).push(new GVGTeamInList(team)); - areaTeams.push(new GVGTeamInList(team)); - } - await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { - cityId: catapult.cityId, areaId, attackType: GVG_ATTACK_TYPE.CATAPULT, teams: areaTeams - }); - for(let [roleId, myTeams] of roleToTeams) { - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { - cityId: catapult.cityId, areaId, attackType: GVG_ATTACK_TYPE.CATAPULT, teams: myTeams - }); - } - } - await sendMessageToGVGCityWithSuc(teamObj.groupKey, catapult.cityId, PUSH_ROUTE.GVG_SPINE_ATTACKED, { - cityId: catapult.cityId, areaId, teamCode: catapult.teamCode, attackType: GVG_ATTACK_TYPE.CATAPULT, spines: teams.map(team => new GVGAttackSpine(team, catapult.captapultAtk)) - }); - } - } -} - -// 战斗积分更新 -export async function redisAddBattleScore(gvgTeam: GVGTeamType, incScore: number) { - let { configId, groupKey, cityId, roleId, isRobot } = gvgTeam; - if(isRobot) return; - let nextWeek = getTimeFun().getAfterDayWithHour(7); - - let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }); - await r.setExpire(nextWeek); - await r.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true); - - // let r2 = new Rank(REDIS_KEY.GVG_BATTLE_USER_RANK_BY_CITY, { configId, groupKey, cityId }); - // await r2.setExpire(nextWeek); - // await r2.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true); -} - -export async function redisAddSettleScore(gvgTeam: GVGTeamType, incScore: number) { - let { configId, groupKey, cityId, leagueCode, isRobot, roleId } = gvgTeam; - if(isRobot) return; - let nextWeek = getTimeFun().getAfterDayWithHour(7); - - let r1 = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }); - await r1.setExpire(nextWeek); - await r1.setRankWithLeagueInfo(leagueCode, incScore, Date.now(), null, true); - - let r2 = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); - await r2.setExpire(nextWeek); - await r2.setRankWithLeagueInfo(leagueCode, incScore, Date.now(), null, true); - - let r3 = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }); - await r3.setExpire(nextWeek); - await r3.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true) - - // let r4 = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK_BY_CITY, { configId, groupKey, cityId }); - // await r4.setExpire(nextWeek); - // await r4.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true) -} - -export async function getSpineCnt() { - let cnt = await redisClient().getAsync(REDIS_KEY.GVG_SPINE_CNT); - return cnt? parseInt(cnt): 20; -} - -// 获取联军分城池排行榜 -export async function getBattleRanksByCity(configId: number, groupKey: string, cityId: number, myLeague?: GVGLeagueType) { - let teamObj = getGVGBattleData(groupKey); - let pointByLeague = teamObj.findSettledPointMapByLeague(cityId); - let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); - r.setGenerFieldsFun((obj => { - if(obj instanceof LeagueRankInfo) { - let pointIds = pointByLeague.get(obj.code)||[]; - let incScore = 0; - for(let pointId of pointIds) incScore += gameData.gvgAreaPoint.get(pointId)?.score||0; - return { rank: obj.rank, leagueCode: obj.code, leagueName: obj.name, score: obj.num, incScore } - } - return obj - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ leagueCode: myLeague?.leagueCode }); - if (myLeague && !myRank) { - myRank = await r.generMyRankWithLeague(myLeague.leagueCode, 0, 0, myLeague); - } - return { ranks, myRank } -} - -// 玩家进驻的积分排行榜 -export async function getPlayerSettleRanksByCity(configId: number, groupKey: string, cityId: number, roleId?: string) { - let teamObj = getGVGBattleData(groupKey); - let r = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey, cityId }); - r.setGenerFieldsFun((obj => { - if(obj instanceof RoleRankInfo) { - let pointIds = teamObj.rolePoints.get(obj.roleId)||[]; - let incScore = 0; - for(let [pointId] of pointIds) incScore += gameData.gvgAreaPoint.get(pointId)?.score||0; - return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, score: obj.num, incScore } - } - return obj - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); - if (roleId && !myRank) { - myRank = await r.generMyRankWithRole(roleId, 0, 0); - } - return { ranks, myRank } -} - -// 玩家挑战的积分排行榜,按城池 -export async function getPlayerRanksByCity(configId: number, groupKey: string, cityId: number, roleId?: string) { - let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey, cityId }); - r.setGenerFieldsFun((obj => { - if(obj instanceof RoleRankInfo) { - return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, score: obj.num } - } - return obj - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); - if (roleId && !myRank) { - myRank = await r.generMyRankWithRole(roleId, 0, 0); - } - return { ranks, myRank } -} - -// 每5秒一次结算 -export async function gvgBattleSeconds() { - const { configId, period } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - // const serverNames = await getAllServerName(); - - // let spineCnt = await getSpineCnt(); - let keys: { groupKey: string, cityId: number }[] = [] - for(let [_key, teamObj] of getGVGBattleMap()) { - // console.log('#### gvgBattleSeconds groupKey: ', _key, 'areas', teamObj.findAreas(), 'appid', pinus.app.getServerId()); - if(startFightTime <= nowSeconds() && endFightTime >= nowSeconds()) { - // 每5秒给据点上的人加积分 - let teams = teamObj.findSettledPoint(); - for(let teamMem of teams) { - if(teamMem.isBroken || teamMem.durability <= 0) continue; - let addScore = gameData.gvgAreaPoint.get(teamMem.pointId)?.score||0; - let team = await GVGTeamModel.addScore(teamMem.teamCode, 0, addScore); - await redisAddSettleScore(team, addScore); - } - } - - // 向下推送区域数据 - // let spinesByCity = new Map(); - for(let areaId of teamObj.findAreas()) { - let dicArea = gameData.gvgArea.get(areaId); - // let teams = teamObj.findTeamsByArea(areaId, spineCnt); - // let spines = teams.map(team => new GVGTeamSpineInMap(team, serverNames)); - // if(!spinesByCity.has(dicArea.cityId)) spinesByCity.set(dicArea.cityId, []); - // spinesByCity.get(dicArea.cityId).push(...spines); - let index = keys.findIndex(cur => cur.cityId == dicArea.cityId && cur.groupKey == teamObj.groupKey); - if(index == -1) keys.push({ groupKey: teamObj.groupKey, cityId: dicArea.cityId }); - } - // for(let [cityId, spines] of spinesByCity) { - // if(spines.length > 0) await sendMessageToGVGCityWithSuc(teamObj.groupKey, cityId, PUSH_ROUTE.GVG_AREA_SPINE_CHANGE, { cityId, spines }); - // } - - } - - if(startFightTime <= nowSeconds() && endFightTime >= nowSeconds()) { - // console.log('#### cityRank keys', JSON.stringify(keys), 'appid', pinus.app.getServerId()) - for(let { groupKey, cityId } of keys) { - let { ranks } = await getBattleRanksByCity(configId, groupKey, cityId); - let { ranks: memberRanks } = await getPlayerRanksByCity(configId, groupKey, cityId); - let { ranks: memberSettleRanks } = await getPlayerSettleRanksByCity(configId, groupKey, cityId); - await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_CITY_RANK_UPDATE, { cityId, ranks, memberRanks, memberSettleRanks }); - } - } - -} - -export async function gvgBattleEnd() { - console.log('######### gvgBattleEnd #######') - let { configId } = getGVGConfig(); - let dontSendReward = await redisClient().getAsync(REDIS_KEY.GVG_SEND_REWARD) == 'true'; - // 城池占领情况 - await calCityGuard(configId, dontSendReward); - - // 联军排行榜发放奖励 - let leagueKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_LEAGUE_RANK}:${configId}:`); - for(let key of leagueKeys) { - let [,, groupKey] = key.split(':'); - let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }); - let ranks = await r.getRankByRange(); - // 联军排行榜发放奖励 - for(let _obj of ranks) { - let obj = _obj; - let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.LEAGUE, obj.rank); - await sendMailToLeagueByContent(MAIL_TYPE.GVG_BATTLE_LEAGUE_RANK_REWARD, obj.code, { params: [`${obj.rank}`], goods: dicRank.reward }, null, dontSendReward); - } - } - - // 个人排行榜发放奖励 - let playerKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_RANK}:${configId}:`); - for(let key of playerKeys) { - let [,, groupKey] = key.split(':'); - let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }); - let ranks = await r.getRankByRange(); - - for(let _obj of ranks) { - let obj = _obj; - let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.PLAYER, obj.rank); - await sendMailByContent(MAIL_TYPE.GVG_BATTLE_PLAYER_RANK_REWARD, obj.roleId, { params: [`${obj.rank}`], goods: dicRank.reward }, dontSendReward); - } - } - - // 个人积分排行榜发放奖励 - let playerSettleKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK}:${configId}:`); - for(let key of playerSettleKeys) { - let [,, groupKey] = key.split(':'); - let r = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }); - let ranks = await r.getRankByRange(); - - for(let _obj of ranks) { - let obj = _obj; - let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.PLAYER_SETTLE, obj.rank); - await sendMailByContent(MAIL_TYPE.GVG_BATTLE_PLAYER_SETTLE_RANK_REWARD, obj.roleId, { params: [`${obj.rank}`], goods: dicRank.reward }, dontSendReward); - } - } -} - -interface SortCities { cityType: number, cityId: number, index: number, league: string, score: number }; -interface RankAndLastLeague { ranks: LeagueRankInfo[], lastLeague: string }; - -// 赛期末结算守城 -export async function calCityGuard(configId: number, canSendReward: boolean) { - - let sortCities = new Map(); // groupKey => cities - let rankByCity = new Map>(); // groupKey => city => {ranks, lastLeague} - await generateData(configId, sortCities, rankByCity); - for(let [groupKey, cities] of sortCities) { - let cityResult: number[] = []; - let index = 0; // 防死循环,万一出什么事cityResult.length一直不等于cities.length - let guardLeagueCnt = new Map(); - while(cityResult.length != cities.length && (++index < 1000)) { - let sorted = cities - .filter(city => cityResult.indexOf(city.cityId) == -1) - .sort((a, b) => { - if(a.cityType != b.cityType) return a.cityType - b.cityType; - if(a.score != b.score) return b.score - a.score; - return b.cityId - a.cityId; - }); - - for(let { league: leagueCode, cityId } of sorted) { - if(!leagueCode) continue; - let cnt = guardLeagueCnt.get(leagueCode)||0; - if(cnt < GVG.GVG_CITY_OCCUPIED_NUMBER) { - await addGuardCity(configId, groupKey, cityId, leagueCode, canSendReward); - guardLeagueCnt.set(leagueCode, cnt + 1); - cityResult.push(cityId); - break; - } else { - let city = cities.find(cur => cur.cityId == cityId); - if(!city) continue; - if(city.index == -1) { - cityResult.push(city.cityId); continue; - } - let nextIndex = city.index + 1; - let { ranks, lastLeague } = rankByCity.get(groupKey)?.get(city.cityId)||{ ranks: [], lastLeague: '' }; - if(ranks[nextIndex]) { - city.index = nextIndex; - city.league = ranks[nextIndex].code; - city.score = ranks[nextIndex].num; - } else { - if(lastLeague) { - city.index = -1; - city.league = lastLeague; - city.score = 0; - } else { - cityResult.push(city.cityId); continue; - } - } - } - } - } - - } -} - -// 结算守城处理数据 -async function generateData(configId: number, sortCities: Map, rankByCity: Map>) { - let keys = await findKeys(`${REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY}:${configId}:`); - let lastCities = await GVGCityModel.findByConfig(configId); - for(let key of keys) { - let [,, groupKey, _cityId] = key.split(':'); - let cityId = parseInt(_cityId); - let dicCity = gameData.gvgCity.get(cityId); - if(!dicCity) continue; - - let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); - let ranks = await r.getRankByRange(); - if(ranks.length <= 0) continue; - if(!sortCities.has(groupKey)) sortCities.set(groupKey, []); - sortCities.get(groupKey).push({ cityType: dicCity.cityType, cityId, index: 0, league: ranks[0].code, score: ranks[0].num }); - - if(!rankByCity.has(groupKey)) rankByCity.set(groupKey, new Map()); - let guardCity = lastCities.find(city => city.cityId == cityId && city.groupKey == groupKey); - if(!rankByCity.get(groupKey).has(cityId)) rankByCity.get(groupKey).set(cityId, { ranks, lastLeague: guardCity?.guardLeague??'' }) - } - for(let { groupKey, cityId, guardLeague } of lastCities) { - if(rankByCity.has(groupKey) && rankByCity.get(groupKey).has(cityId)) continue; - - let dicCity = gameData.gvgCity.get(cityId); - if(!dicCity) continue; - - if(!sortCities.has(groupKey)) sortCities.set(groupKey, []); - sortCities.get(groupKey).push({ cityType: dicCity.cityType, cityId, index: -1, league: guardLeague, score: 0 }); - - if(!rankByCity.has(groupKey)) rankByCity.set(groupKey, new Map()); - if(!rankByCity.get(groupKey).has(cityId)) rankByCity.get(groupKey).set(cityId, { ranks: [], lastLeague: guardLeague||'' }) - } -} - -async function addGuardCity(configId: number, groupKey: string, cityId: number, leagueCode: string, canSendReward: boolean) { - let dicCity = gameData.gvgCity.get(cityId); - let dicCityAdd = gameData.gvgCityAdd.get(dicCity.cityType); - let league = await GVGLeagueModel.findByCodeWithoutPopulate(leagueCode); - if(!league) return; - let leagueGroupKey = await getGroupKey(league.serverId); - if(groupKey != leagueGroupKey) { - console.log('addGuardCity groupKey err', cityId, groupKey, leagueCode, league.serverId); - return; - } - await GVGCityModel.guardCity(configId, groupKey, cityId, league); - await sendMailToLeagueByContent(MAIL_TYPE.GVG_GUARD_CITY_REWARD, leagueCode, { params: [dicCity.cityName], goods: dicCityAdd.occupyReward }, league, canSendReward); - await addCityGuardMessage(league, cityId); -} - -// —————————— 定时器相关 end —————————— // - -// —————————— 推送相关 —————————— // -// 推送 -export async function battleEndSendMessage(groupKey: string, cityId: number, defenseTeam: GVGTeamType, attackTeam: GVGTeamType, attackType: GVG_ATTACK_TYPE) { - let areaId = defenseTeam.curTeamBreak? defenseTeam.fromAreaId: defenseTeam.areaId; - // 推送伤害 - await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { - cityId, areaId, attackType, teams: [new GVGTeamInList(defenseTeam), new GVGTeamInList(attackTeam)] - }); - if(!defenseTeam.isRobot) { - await sendMessageToUserWithSuc(defenseTeam.roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { - cityId, areaId, attackType, teams: [new GVGTeamInList(defenseTeam, true)] - }); - } - await pushTeamBeHurtMessage(defenseTeam, attackTeam); - await pushTeamBeHurtMessage(attackTeam); -} - -export async function sendWinStreakMessage(groupKey: string, cityId: number, attackTeam: GVGTeamType, defenseTeam: GVGTeamType, isSuccess: boolean) { - if (attackTeam && !attackTeam.isRobot) { - let result = await GVGUserDataModel.setWinStreak(attackTeam.configId, attackTeam.leagueCode, attackTeam.roleId, isSuccess); - if (needSendMsg(result.winStreak)) { - await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_WIN_STREAK, new GVGWinStreakInfo(attackTeam, result.winStreak)); - } - } - if (defenseTeam && !defenseTeam.isRobot) { - let result = await GVGUserDataModel.setWinStreak(defenseTeam.configId, defenseTeam.leagueCode, defenseTeam.roleId, !isSuccess); - if (needSendMsg(result.winStreak)) { - await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_WIN_STREAK, new GVGWinStreakInfo(defenseTeam, result.winStreak)); - } - } -} - -function needSendMsg(winStreak: number) { - let arr = parseNumberList(GVG.WIN_STREAK_REPORT_LIMIT); - return arr.includes(winStreak); -} - -// 队伍移动 -export async function pushTeamBeHurtMessage(team: GVGTeamType, replaceTeam?: GVGTeamType) { - if(team.curTeamBreak && team.originPointId > 0) { - await sendAreaPointChange(team.groupKey, team.fromAreaId, team.cityId, team.originPointId, replaceTeam?.originPointId??0, replaceTeam||team); - if(replaceTeam && !replaceTeam.curTeamBreak && replaceTeam.originPointId > 0) { - await sendAreaPointChange(replaceTeam.groupKey, replaceTeam.fromAreaId, replaceTeam.cityId, replaceTeam.originPointId, 0, replaceTeam); - } - } - - if(team.curTeamBreak) { - await pushTeamMoveMessage(team); - } - if(team.isRobot && team.isBroken) { - await sendAreaLeaveMsg(team.groupKey, team.fromAreaId, team.cityId, team.teamCode); - } -} - -export async function pushTeamMoveMessage(team: GVGTeamType) { - if(team.fromAreaId != team.areaId) { - if(team.fromAreaId > 0) await sendAreaLeaveMsg(team.groupKey, team.fromAreaId, team.cityId, team.teamCode); - if(team.areaId > 0) await sendAreaAddMsg(team.groupKey, team.areaId, team.fromAreaId, team.cityId, team); - } -} -// —————————— 推送相关 end —————————— // - -export async function sendAreaLeaveMsg(groupKey: string, areaId: number, cityId: number, teamCode: string) { - await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, { - cityId, areaId, teamCode - }); - await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_AREA_LEAVE, { - cityId, areaId, teamCode - }); -} - -export async function sendAreaAddMsg(groupKey: string, areaId: number, fromAreaId: number, cityId: number, team: GVGTeamType) { - await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_PLAYER_AREA_ADD, { - cityId, areaId, fromAreaId, player: new GVGTeamInList(team) - }); - await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_AREA_ADD, { - cityId, areaId, fromAreaId, spine: new GVGTeamSpineInfo(team, await getServerName(team.serverId)) - }); -} - -export async function sendAreaPointChange(groupKey: string, areaId: number, cityId: number, targetPointId: number, originPointId: number, team: GVGTeamType) { - await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, { - cityId, areaId, targetPointId, originPointId, point: new GVGTeamInListOnPoint(team.pointId, true, team) - }); - await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_POINT_CHANGE, { - cityId, areaId, targetPointId, originPointId, spine: new GVGTeamSpineInfo(team, await getServerName(team.serverId)) - }) -} - -// 外面页面上的排行榜 -export async function getBattleRank(redisKey: REDIS_KEY, keyParam: KeyNameParam, myId: myIdInter) { - let r = new Rank(redisKey, keyParam); - r.setGenerFieldsFun((obj => { - if(obj instanceof LeagueRankInfo) return { rank: obj.rank, name: obj.name, score: obj.num } - if(obj instanceof RoleRankInfo) return { rank: obj.rank, name: obj.roleName, score: obj.num } - })); - - let { ranks, myRank } = await r.getRankListWithMyRank(myId); - if (!myRank) { - if(redisKey == REDIS_KEY.GVG_BATTLE_RANK) { - myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); - } else if (redisKey == REDIS_KEY.GVG_BATTLE_LEAGUE_RANK) { - myRank = await r.generMyRankWithLeague(myId.leagueCode, 0, 0); - } else if (redisKey == REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK) { - myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); - } - } - return { ranks, myRank } -} - -export async function initTeamToMem() { - let sid = pinus.app.getServerId(); - let servers = pinus.app.getServersByType('guild'); - let { configId, period } = getGVGPeriodData(); - if(period != GVG_PERIOD.BATTLE) return; - let teams = await GVGTeamModel.findByConfigId(configId); - for(let team of teams) { - if(team.isBroken) continue; - let dispacthSid = await dispatchTeam(team.groupKey, team.cityId); - if(dispacthSid == sid) { - let teamObj = getGVGBattleData(team.groupKey); - teamObj.enterCity(team); - } - } -} - -async function dispatchTeam(groupKey: string, cityId: number) { - let groupId = ''; - if(groupKey.startsWith('s')) { - let serverId = parseInt(groupKey.slice(1)); - groupId = (await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG)).toString(); - } else { - groupId = groupKey.slice(1); - } - - let servers = pinus.app.getServersByType('guild'); - let sid = (await dispatch(redisClient(), `${groupId}_${cityId}`, servers, 'guild'))?.id; - return sid; -} - -/** - * 查询队伍中的武将是否可以使用 - * @param roleId - * @param index - * @param lineup - * @returns - */ -export async function checkGVGLineupWhenSave(roleId: string, index: number, lineup: LineupHero[]) { - const teams = await GVGTeamModel.findByRole(roleId, '-_id index lineup'); - for(let { actorId, subHid } of lineup) { - let dicHero = gameData.hero.get(actorId); - if(subHid && (!dicHero || dicHero.urType != 1)) return STATUS.HERO_CAN_NOT_SET_SUB; - - for(let team of teams) { - // 查actorId没有在其他队伍中使用 - if(team.index != index) { - let hasActor = team.lineup.find(hero => hero.actorId == actorId); - if(hasActor) return STATUS.GVG_TEAM_HERO_DUPLICATE; - - // 查actorId没有在其他队伍作为副将 - let hasActorIsSubHero = team.lineup.find(hero => hero.subHid == actorId); - if(hasActorIsSubHero) return STATUS.GVG_TEAM_HERO_USED_AS_SUB_HERO; - // 查副将 - if(subHid) { - let hasSubHero = team.lineup.find(hero => hero.actorId == subHid); - if(hasSubHero) return STATUS.GVG_TEAM_SUB_HERO_DUPLICATE; - } - } else { - // 查actorId没有在其他队伍作为副将 - let hasActorIsSubHero = lineup.find(hero => hero.subHid == actorId); - if(hasActorIsSubHero) return STATUS.GVG_TEAM_HERO_USED_AS_SUB_HERO; - - // 查副将 - if(subHid) { - let hasSubHero = lineup.find(hero => hero.actorId == subHid); - if(hasSubHero) return STATUS.GVG_TEAM_SUB_HERO_DUPLICATE; - } - } - } - } - return STATUS.SUCCESS -} \ No newline at end of file +import { GVGTeamMem } from "@domain/battleField/gvgBattle"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import GVGTeam, { GVGTeamModel, GVGTeamType, GVGTeamUpdate } from "@db/GVGTeam"; +import { GVGCityModel, GVGCityType } from "@db/GVGCity"; +import { gameData, getGVGBattleRankReward } from "@pubUtils/data"; +import { COUNTER, GVG_AREA_TYPE, GVG_ATTACK_TYPE, GVG_BATTLE_RANK_TYPE, GVG_PERIOD, GVG_POINT_TYPE, GVG_SERVER_TYPE, GVG_TECH_TYPE, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, SERVER_GROUP_FUN_TYPE, STATUS } from "@consts"; +import { getTimeFun, nowSeconds } from "@pubUtils/timeUtil"; +import { DicGVGAreaPoint } from "@pubUtils/dictionary/DicGVGAreaPoint"; +import { getGVGBattleData, getGVGBattleMap } from "../memoryCache/gvgBattleData"; +import { GVGAttackSpine, GVGCityMapInfo, GVGEnemies, GVGTeamInList, GVGTeamInListOnPoint, GVGTeamSpineInMap, GVGTeamSpineInfo, GVGWinStreakInfo } from "@domain/gvgField/returnData"; +import { GVG } from "@pubUtils/dicParam"; +import { GVGHeroInfo, PvpEnemies, PvpHeroInfo } from "@domain/dbGeneral"; +import { getGroupKey, getGVGConfig, getGVGConfigFromRemote, getGVGPeriodData, getGVGServerType } from "./gvgService"; +import { GVGLeaguePrepareModel } from "@db/GVGLeaguePrepare"; +import { pinus } from "pinus"; +import { dispatch } from "@pubUtils/dispatcher"; +import { Rank } from "../rankService"; +import { KeyNameParam, LeagueRankInfo, myIdInter, RoleRankInfo } from "@domain/rank"; +import { findKeys, getAllServerName, getServerName, redisClient } from "../redisService"; +import { sendMessageToGVGAreaByTeamWithSuc, sendMessageToGVGAreaWithSuc, sendMessageToGVGCityWithSuc, sendMessageToUserWithSuc } from "../pushService"; +import { sendMailByContent, sendMailToLeagueByContent } from "../mailService"; +import { GVGCityAreaPointModel } from "@db/GVGCityAreaPoint"; +import { addCityGuardMessage } from "./gvgRecService"; +import { GVGUserDataModel } from "@db/GVGUserData"; +import { RoleModel } from "@db/Role"; +import { getFightTimeByPeriod } from "./gvgFightService"; +import { getRandSingleEelm, parseNumberList } from "@pubUtils/util"; +import { HeroModel, HeroType } from "@db/Hero"; +import { ArtifactModel } from "@db/Artifact"; +import { getHeroesAttributes } from "../playerCeService"; +import { CounterModel } from "@db/Counter"; +import { getGroupIdOfServer } from "../serverService"; +import { LineupHero } from "@domain/roleField/hero"; +import { gvgEndParamInter } from "@pubUtils/interface"; + +/** + * 获取本联军上周占领的城池 + * @param league + * @returns number[] 城池id + */ +export async function getGVGCities(league: GVGLeagueType) { + let { configId } = getGVGConfig(); + let cities = await GVGCityModel.findGuardCityByLeague(configId, league.leagueCode, 'cityId'); + return cities.map(city => city.cityId); +} + +/** + * 获取当前城池状态 + * @returns [{cityId: number, guardLeagueCode: string, guardLeagueName: string, teamCnt: number }] + */ +export async function getGVGCitiesInfo(configId: number, groupKey: string, league?: GVGLeagueType) { + let cities = await GVGCityModel.findGuardCity(configId, groupKey); + let result: GVGCityMapInfo[] = []; + for(let city of cities) { + let obj = new GVGCityMapInfo(city.cityId); + obj.setCity(city); + if(league) { + let players = (city.players||[]).filter(cur => cur.leagueCode == league.leagueCode); + obj.setTeamCnt(players.length); + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId: city.cityId }); + let score = await r.getMyScore({ leagueCode: league.leagueCode }); + obj.setScore(score||0); + } + result.push(obj); + } + return result; +} + +export async function getAllGVGCitiesInfo(configId: number, groupKey: string, serverType: number) { + let cities = await GVGCityModel.findGuardCity(configId, groupKey); + let result: GVGCityMapInfo[] = []; + for(let [cityId, { mapType }] of gameData.gvgCity) { + if(mapType != serverType) continue; + let obj = new GVGCityMapInfo(cityId); + let city = cities.find(cur => cur.cityId == cityId); + obj.setCity(city); + result.push(obj); + } + return result +} + +/** + * 获取内存中队伍的数据结构 + */ +export function getGVGTeamMemInfo(team: GVGTeamType): GVGTeamMem { + const teamMem = new GVGTeamMem(team); + teamMem.isMoving = false; + teamMem.startMoveTime = 0; + teamMem.stopMoveTime = 0; + return teamMem; +} + +/** + * 获取 重新进入城池/复活 所在的区域 + * @param city GVGCity + * @param leagueCode 联军id + * @returns + */ +export function getBirthAreaOfCity(city: GVGCityType, leagueCode: string) { + let isGuard = city.guardLeague == leagueCode; + let dicGVGCity = gameData.gvgCity.get(city.cityId); + return isGuard? dicGVGCity.defenseBirth: dicGVGCity.attackBirth; +} + +/** + * 玩家是否可以进入城池 + * @param city + * @param leagueCode + * @returns + */ +export function checkEnterCityTime(city: GVGCityType, leagueCode: string) { + let isGuard = city?.guardLeague == leagueCode; + let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.BATTLE); + if(isGuard && startFightTime - GVG.GVG_GUARD_START_TIME > nowSeconds()) return false; + if(!isGuard && startFightTime > nowSeconds()) return false; + if(endFightTime < nowSeconds()) return false; + return true +} + +// guild.gvgBattleHandler.startMove 检测 +export function checkMoveStatus(team: GVGTeamType, cityId: number, areaId: number) { + if(!team) return STATUS.GVG_BATTLE_TEAM_NOT_FOUND; + if(team.cityId != cityId) return STATUS.GVG_BATTLE_IS_NOT_IN_CITY; + if(team.pointId > 0) return STATUS.GVG_BATTLE_TEAM_IS_SELLTED; + if(team.stopMoveTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING; + if(team.moveCdTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING_CD; + if(team.lockTime > nowSeconds()) return STATUS.GVG_TEAM_DEFENSEING; + if(team.restartTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_REVIVE; + let dicArea = gameData.gvgArea.get(areaId); + if(!dicArea) return STATUS.DIC_DATA_NOT_FOUND; + if(dicArea.relateArea.indexOf(team.areaId) == -1) return STATUS.GVG_BATTLE_AREA_NOT_RELATE; + return STATUS.SUCCESS; +} + +export function checkSettleStatus(team: GVGTeamType) { + if(!team) return STATUS.GVG_BATTLE_TEAM_NOT_FOUND; + if(team.stopMoveTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING; + // if(team.moveCdTime > nowSeconds()) return STATUS.GVG_BATTLE_IS_MOVING_CD; + if(team.lockTime > nowSeconds()) return STATUS.GVG_TEAM_DEFENSEING; + if(team.restartTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_REVIVE; + return STATUS.SUCCESS; +} + +export async function initRobots(configId: number, groupKey: string, city: GVGCityType | { cityId: number, guardLeague: string }) { + let { cityId, guardLeague = '' } = city; + if(guardLeague) return []; + let robotTeams = await GVGTeamModel.findRobotTeams(configId, groupKey, cityId); + let updateDicPoints: DicGVGAreaPoint[] = []; + let { battleAreaIds = []} = gameData.gvgCity.get(cityId); + for(let areaId of battleAreaIds) { + let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; + for(let pointId of pointIds) { + let dicPoint = gameData.gvgAreaPoint.get(pointId); + if(!dicPoint || dicPoint.type != GVG_POINT_TYPE.ROBOT) continue; + let robotTeam = robotTeams.find(team => team.pointId == dicPoint.pointId); + if(!robotTeam || (!robotTeam.isBroken && robotTeam.configId != configId) ) { + updateDicPoints.push(dicPoint); + } + } + } + if(updateDicPoints.length > 0) { + let lv = gameData.war.get(GVG.GVG_ROBOT_WARJSON)?.level||50; + robotTeams = await GVGTeamModel.initRobots(configId, groupKey, cityId, updateDicPoints, lv); + // 存入内存 + let teamObj = getGVGBattleData(groupKey); + teamObj.enterCity(...robotTeams); + } + return robotTeams; +} + +export function checkAreaIsInCity(cityId: number, areaIds: number[]) { + let dicCity = gameData.gvgCity.get(cityId); + if(!dicCity) return false; + for(let areaId of areaIds) { + if(dicCity.areaIds.indexOf(areaId) == -1) return false; + } + return true; +} + +export function calBattleScoreByCe(isSuccess: boolean, lineupCe: number) { + let winScore = Math.floor(lineupCe/GVG.GVG_BATTLE_SCORE); + if(winScore <= 0) winScore = 1; + return isSuccess? winScore: 0; +} + +export async function refreshTeams(configId: number, groupKey: string, roleId: string, myLeague: GVGLeagueType, hasConfirm: boolean) { + let oldTeams = await GVGTeamModel.findByRole(roleId, '-_id'); + let teams: GVGTeamType[] = []; + for(let team of oldTeams) { + if(team.configId != configId || (hasConfirm && team.confirmConfigId != configId)) { + let { teamCode, maxDurability, lineup } = team; + let { lv, title, roleName, guildCode } = await RoleModel.findByRoleId(roleId, 'lv title roleName guildCode'); + let heroes = await HeroModel.findByHidRange(lineup.map(hero => hero.actorId), roleId); + let { newLineup, newLineupCe } = await generNewLineup(roleId, heroes, lineup.map(({ actorId, dataId, outIndex }) => ({ actorId, dataId, order: outIndex }))); + let addUpdate = hasConfirm? { confirmConfigId: configId }: {}; + let newTeam = await GVGTeamModel.refreshByConfig(teamCode, { configId, lv, title, durability: maxDurability, cityId: 0, areaId: 0, pointId: 0, roleName, guildCode, leagueCode: myLeague.leagueCode, leagueName: myLeague.name, groupKey, lineup: newLineup, lineupCe: newLineupCe, ...addUpdate }); + teams.push(newTeam); + } else { + teams.push(team); + } + } + return teams +} + +export async function generNewLineup(roleId: string, heroes: HeroType[], lineup: { actorId: number, dataId: number, order: number, subHid?: number }[]) { + let attrByHid = await getHeroesAttributes(roleId); + let newLineup: GVGHeroInfo[] = [], newLineupCe = 0; + for(let { actorId, dataId, order, subHid } of lineup) { + let hero = heroes.find(cur => cur.hid == actorId); + if(hero) { + let artifact = hero.artifact? await ArtifactModel.findbySeqId(roleId, hero.artifact): null; + let heroInfo = new GVGHeroInfo(); + heroInfo.setHeroInfo(hero, artifact, []); + heroInfo.setDataId(dataId, order); + let subHero = heroes.find(cur => cur.hid == subHid); + if(subHero) heroInfo.setSubHero(subHero); + + let attr = attrByHid.get(actorId); + if(!attr) continue; + let attribute = attr.getAttributesToString(); + heroInfo.setAttribute(attribute); + + newLineup.push(heroInfo); + newLineupCe += hero.ce; + } + } + return { newLineup, newLineupCe }; +} + +/** + * 离开城池 + * 当玩家占领据点的时候,可以保留据点;不占领的时候,不保留;退出游戏的时候,全不保留 + * @param isForce 是否是玩家关闭游戏的那种离开 + * @param roleId + * @param serverId + * @param guildCode + * @param myLeague + * @returns + */ +export async function leaveCity(isForce: boolean, roleId: string, serverId: number, guildCode: string, myLeague?: GVGLeagueType) { + if(!myLeague) myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode); + let groupKey = await getGroupKey(serverId); + let { configId } = await getGVGConfigFromRemote(); + let teams = await GVGTeamModel.findByRole(roleId); + let hasPoint = !!teams.find(team => team.pointId > 0); + + // console.log('######### leaveCity', configId, groupKey) + if(isForce || !hasPoint) { + await GVGTeamModel.leaveCity(roleId); + await GVGCityModel.decreasePlayer(configId, groupKey, roleId); + if(myLeague) await GVGUserDataModel.changeCity(configId, myLeague.leagueCode, roleId, 0); + await GVGCityAreaPointModel.playerLeave(configId, groupKey, roleId); + // 处理内存数据 + await pinus.app.rpc.guild.guildRemote.leaveCityMem.broadcast(groupKey, roleId); + for(let team of teams) { + if(team.cityId > 0 && team.areaId > 0) { + await sendAreaLeaveMsg(groupKey, team.areaId, team.cityId, team.teamCode); + } + } + } +} + +export async function leaveCityMem(groupKey: string, roleId: string) { + let teamObj = getGVGBattleData(groupKey); + teamObj.leaveCity(roleId); +} + +// 复活cd +export async function getTechReviveMinus(groupKey: string, configId: number, leagueCode: string) { + let teamObj = getGVGBattleData(groupKey); + let activeTech = teamObj.getLeagueTech(leagueCode); + if(!activeTech) { + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + activeTech = leaguePrepare?.activeTech||[]; + teamObj.setLeagueTech(leagueCode, activeTech); + } + let minusCd = 0; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_REVIVE_GAP) { + minusCd += dicTech.param[0]; + } + } + let cd = GVG.GVG_DEFAULT_REVIVE_CD - minusCd; + if(cd < 0) cd = 0; + + return cd; +} + +// 诸葛连弩的伤害 +export async function getTechKnifeHurt(configId: number, leagueCode: string) { + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + let hurt = 0; + let activeTech = leaguePrepare?.activeTech||[]; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_KNIFE) { + if(dicTech.param[2] > hurt) hurt = dicTech.param[2]; + } + } + return hurt +} + +export function getGVGWarId(defenseTeam: GVGTeamType) { + if(!defenseTeam.isRobot) return GVG.GVG_CITY_BGMAP_GKID; // 玩家防守地图 + if(!defenseTeam.isCatapult) return GVG.GVG_CATAPULT_WARJSON; // 投石车使用 + return GVG.GVG_ROBOT_WARJSON; // 据点守卫使用 +} + +// guild.gvgBattleHandler.battleStart 里的heroes返回 +export function getOppHeroes(warId: number, isRobot: boolean, lineup: GVGHeroInfo[]) { + let heroes: GVGEnemies[] = []; + const dicWar = gameData.war.get(warId); + if(!dicWar) { console.error(`warId ${warId} not found`); return [] } + const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId)||[]; + for(let warJson of dicWarJson) { + if(!isRobot) { + let heroInfo = lineup.find(cur => cur.dataId == warJson.dataId); + if(!heroInfo) continue; + let hero = new GVGEnemies(warJson, heroInfo); + heroes.push(hero); + } else { + if(warJson.relation == 2) { + let dicHero = gameData.hero.get(warJson.actorId); + if(!dicHero) continue; + let heroInfo = new GVGHeroInfo(); + heroInfo.setRobotInfo(dicHero, warJson.lv); + let hero = new GVGEnemies(warJson, heroInfo); + heroes.push(hero); + } + } + } + return heroes +} + +// guild.gvgBattleHandler.battleStart 检测 +export function checkGVGBattleStart(roleId: string, attackTeam: GVGTeamType, defenseTeam: GVGTeamType) { + + if(!attackTeam || !defenseTeam) return STATUS.GVG_BATTLE_TEAM_INVALID; + if(attackTeam.roleId != roleId) return STATUS.GVG_TEAM_IS_NOT_MINE; + if(attackTeam.leagueCode == defenseTeam.leagueCode) return STATUS.GVG_SAME_LEAGUE_CANNOT_ATTACK; + if(attackTeam.areaId != defenseTeam.areaId) return STATUS.GVG_TEAM_NOT_SAME_AREA; + + if(attackTeam.attackTime > nowSeconds()) return STATUS.GVG_TEAM_ATTACKING; + if(defenseTeam.defenseTime > nowSeconds() || defenseTeam.lockTime > nowSeconds()) { + return defenseTeam.isRobot? STATUS.GVG_ROBOT_DEFENSEING: STATUS.GVG_TEAM_DEFENSEING; + } + + if(attackTeam.lockTime > nowSeconds()) return STATUS.GVG_BATTLE_TEAM_LOCK; + if(attackTeam.durability <= 0) return STATUS.GVG_ATTACK_TEAM_BROKEN; + if(defenseTeam.durability <= 0) return STATUS.GVG_DEFENSE_TEAM_BROKEN; + + return STATUS.SUCCESS; +} + +export function getNewLineup(team: GVGTeamType, newInfo: gvgEndParamInter[]) { + if (team.isRobot) return { isAllDead: false, newLineup: team.lineup}; + let isAllDead = team.curTeamBreak || checkAllDead(team.lineup, newInfo); + let newLineup: GVGHeroInfo[] = []; + for(let hero of team.lineup) { + if (isAllDead) { + hero.hp = "max"; + hero.maxHp = "max"; + hero.others = ''; + } else { + let info = newInfo.find(cur => cur.actorId == hero.actorId); + if (info) { + hero.hp = info.hp; + hero.maxHp = info.maxHp; + hero.others = info.others; + } + } + + newLineup.push(hero); + } + return { isAllDead, newLineup }; +} + +// 检查本场战斗武将是否死光了 +export function checkAllDead(oldLineup: GVGHeroInfo[], newInfo: gvgEndParamInter[]) { + for(let hero of oldLineup) { + let curInfo = newInfo.find(cur => cur.actorId == hero.actorId); + if (!curInfo || curInfo.hp > 0) return false; + } + return true; +} + +// —————————— 定时器相关 —————————— // +// gvg激战期开始定时器 +export async function gvgBattleStart() { + + let { configId } = getGVGConfig(); + let guardCities = await GVGCityModel.findAllGuardCities(configId); + for(let { cityId, groupKey, guardLeague, guardLeagueName } of guardCities) { + let sid = await dispatchTeam(groupKey, cityId); + await pinus.app.rpc.guild.guildRemote.initCatapult.toServer(sid, cityId, groupKey, guardLeague, guardLeagueName); + } +} + +// 每次活动开始初始化投石车 +export async function initCatapult(cityId: number, groupKey: string, leagueCode: string, leagueName: string) { + let { configId } = getGVGConfig(); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, leagueCode); + let activeTech = leaguePrepare?.activeTech||[]; + let hasCatapult = false, atk = 0, durability = 0; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech && dicTech.type == GVG_TECH_TYPE.BATTLE_ITEM_CATAPULT) { + hasCatapult = true, atk = dicTech.param[0]; durability = dicTech.param[1]; + } + } + if(hasCatapult) { + let updateDicPoints: DicGVGAreaPoint[] = []; + let { catapultAreaIds = []} = gameData.gvgCity.get(cityId); + for(let areaId of catapultAreaIds) { + let pointIds = gameData.gvgPointByAreaId.get(areaId)||[]; + for(let pointId of pointIds) { + let dicPoint = gameData.gvgAreaPoint.get(pointId); + if(!dicPoint || dicPoint.type != GVG_POINT_TYPE.CATAPULT) continue; + updateDicPoints.push(dicPoint); + } + } + + let lv = gameData.war.get(GVG.GVG_CATAPULT_WARJSON)?.level||50; + let teams = await GVGTeamModel.initCatapult(configId, groupKey, cityId, updateDicPoints, leagueCode, leagueName, atk, durability, lv); + // 处理内存 + let teamObj = getGVGBattleData(groupKey); + teamObj.enterCity(...teams); + } +} + +// 投石车投伤害 +export async function catapultHurt() { + let { configId, period } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + if(nowSeconds() < startFightTime || nowSeconds() > endFightTime) return; + for(let [_key, teamObj] of getGVGBattleMap()) { + let teams = teamObj.findCatapult(); + for(let catapult of teams) { + let dicGVGCity = gameData.gvgCity.get(catapult?.cityId); + let battleAreaIds = dicGVGCity?.battleAreaIds||[] + if(!catapult || catapult.isBroken || !dicGVGCity || battleAreaIds.length <= 0) continue; + let areaId = getRandSingleEelm(battleAreaIds); + // let areaId = catapult.cityId * 100 + 2; + let teamMems = teamObj.findCatapultAttackTeam(areaId, catapult.leagueCode); + let teams: GVGTeamType[] = []; + for(let { teamCode, leagueCode } of teamMems) { + let team = await GVGTeamModel.attackByCatapult(teamCode, catapult.captapultAtk, dicGVGCity.attackBirth, await getTechReviveMinus(teamObj.groupKey, configId, leagueCode)); + teams.push(team); + } + teamObj.battleEnd(teams); + if(teams.length > 0) { + let roleToTeams = new Map(); + let areaTeams: GVGTeamInList[] = []; + for(let team of teams) { + await pushTeamBeHurtMessage(team); + if(team.curTeamBreak && team.originPointId > 0) { + await GVGCityAreaPointModel.leavePoint(configId, teamObj.groupKey, team.teamCode); + } + if(!roleToTeams.has(team.roleId)) roleToTeams.set(team.roleId, []); + roleToTeams.get(team.roleId).push(new GVGTeamInList(team)); + areaTeams.push(new GVGTeamInList(team)); + } + await sendMessageToGVGAreaByTeamWithSuc(teamObj.groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { + cityId: catapult.cityId, areaId, attackType: GVG_ATTACK_TYPE.CATAPULT, teams: areaTeams + }); + for(let [roleId, myTeams] of roleToTeams) { + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { + cityId: catapult.cityId, areaId, attackType: GVG_ATTACK_TYPE.CATAPULT, teams: myTeams + }); + } + } + await sendMessageToGVGCityWithSuc(teamObj.groupKey, catapult.cityId, PUSH_ROUTE.GVG_SPINE_ATTACKED, { + cityId: catapult.cityId, areaId, teamCode: catapult.teamCode, attackType: GVG_ATTACK_TYPE.CATAPULT, spines: teams.map(team => new GVGAttackSpine(team, catapult.captapultAtk)) + }); + } + } +} + +// 战斗积分更新 +export async function redisAddBattleScore(gvgTeam: GVGTeamType, incScore: number) { + let { configId, groupKey, cityId, roleId, isRobot } = gvgTeam; + if(isRobot) return; + let nextWeek = getTimeFun().getAfterDayWithHour(7); + + let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }); + await r.setExpire(nextWeek); + await r.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true); + + // let r2 = new Rank(REDIS_KEY.GVG_BATTLE_USER_RANK_BY_CITY, { configId, groupKey, cityId }); + // await r2.setExpire(nextWeek); + // await r2.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true); +} + +export async function redisAddSettleScore(gvgTeam: GVGTeamType, incScore: number) { + let { configId, groupKey, cityId, leagueCode, isRobot, roleId } = gvgTeam; + if(isRobot) return; + let nextWeek = getTimeFun().getAfterDayWithHour(7); + + let r1 = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }); + await r1.setExpire(nextWeek); + await r1.setRankWithLeagueInfo(leagueCode, incScore, Date.now(), null, true); + + let r2 = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); + await r2.setExpire(nextWeek); + await r2.setRankWithLeagueInfo(leagueCode, incScore, Date.now(), null, true); + + let r3 = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }); + await r3.setExpire(nextWeek); + await r3.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true) + + // let r4 = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK_BY_CITY, { configId, groupKey, cityId }); + // await r4.setExpire(nextWeek); + // await r4.setRankWithRoleInfo(roleId, incScore, Date.now(), null, true) +} + +export async function getSpineCnt() { + let cnt = await redisClient().getAsync(REDIS_KEY.GVG_SPINE_CNT); + return cnt? parseInt(cnt): 20; +} + +// 获取联军分城池排行榜 +export async function getBattleRanksByCity(configId: number, groupKey: string, cityId: number, myLeague?: GVGLeagueType) { + let teamObj = getGVGBattleData(groupKey); + let pointByLeague = teamObj.findSettledPointMapByLeague(cityId); + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); + r.setGenerFieldsFun((obj => { + if(obj instanceof LeagueRankInfo) { + let pointIds = pointByLeague.get(obj.code)||[]; + let incScore = 0; + for(let pointId of pointIds) incScore += gameData.gvgAreaPoint.get(pointId)?.score||0; + return { rank: obj.rank, leagueCode: obj.code, leagueName: obj.name, score: obj.num, incScore } + } + return obj + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ leagueCode: myLeague?.leagueCode }); + if (myLeague && !myRank) { + myRank = await r.generMyRankWithLeague(myLeague.leagueCode, 0, 0, myLeague); + } + return { ranks, myRank } +} + +// 玩家进驻的积分排行榜 +export async function getPlayerSettleRanksByCity(configId: number, groupKey: string, cityId: number, roleId?: string) { + let teamObj = getGVGBattleData(groupKey); + let r = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey, cityId }); + r.setGenerFieldsFun((obj => { + if(obj instanceof RoleRankInfo) { + let pointIds = teamObj.rolePoints.get(obj.roleId)||[]; + let incScore = 0; + for(let [pointId] of pointIds) incScore += gameData.gvgAreaPoint.get(pointId)?.score||0; + return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, score: obj.num, incScore } + } + return obj + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); + if (roleId && !myRank) { + myRank = await r.generMyRankWithRole(roleId, 0, 0); + } + return { ranks, myRank } +} + +// 玩家挑战的积分排行榜,按城池 +export async function getPlayerRanksByCity(configId: number, groupKey: string, cityId: number, roleId?: string) { + let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey, cityId }); + r.setGenerFieldsFun((obj => { + if(obj instanceof RoleRankInfo) { + return { rank: obj.rank, roleId: obj.roleId, name: obj.roleName, score: obj.num } + } + return obj + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId }); + if (roleId && !myRank) { + myRank = await r.generMyRankWithRole(roleId, 0, 0); + } + return { ranks, myRank } +} + +// 每5秒一次结算 +export async function gvgBattleSeconds() { + const { configId, period } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + // const serverNames = await getAllServerName(); + + // let spineCnt = await getSpineCnt(); + let keys: { groupKey: string, cityId: number }[] = [] + for(let [_key, teamObj] of getGVGBattleMap()) { + // console.log('#### gvgBattleSeconds groupKey: ', _key, 'areas', teamObj.findAreas(), 'appid', pinus.app.getServerId()); + if(startFightTime <= nowSeconds() && endFightTime >= nowSeconds()) { + // 每5秒给据点上的人加积分 + let teams = teamObj.findSettledPoint(); + for(let teamMem of teams) { + if(teamMem.isBroken || teamMem.durability <= 0) continue; + let addScore = gameData.gvgAreaPoint.get(teamMem.pointId)?.score||0; + let team = await GVGTeamModel.addScore(teamMem.teamCode, 0, addScore); + await redisAddSettleScore(team, addScore); + } + } + + // 向下推送区域数据 + // let spinesByCity = new Map(); + for(let areaId of teamObj.findAreas()) { + let dicArea = gameData.gvgArea.get(areaId); + // let teams = teamObj.findTeamsByArea(areaId, spineCnt); + // let spines = teams.map(team => new GVGTeamSpineInMap(team, serverNames)); + // if(!spinesByCity.has(dicArea.cityId)) spinesByCity.set(dicArea.cityId, []); + // spinesByCity.get(dicArea.cityId).push(...spines); + let index = keys.findIndex(cur => cur.cityId == dicArea.cityId && cur.groupKey == teamObj.groupKey); + if(index == -1) keys.push({ groupKey: teamObj.groupKey, cityId: dicArea.cityId }); + } + // for(let [cityId, spines] of spinesByCity) { + // if(spines.length > 0) await sendMessageToGVGCityWithSuc(teamObj.groupKey, cityId, PUSH_ROUTE.GVG_AREA_SPINE_CHANGE, { cityId, spines }); + // } + + } + + if(startFightTime <= nowSeconds() && endFightTime >= nowSeconds()) { + // console.log('#### cityRank keys', JSON.stringify(keys), 'appid', pinus.app.getServerId()) + for(let { groupKey, cityId } of keys) { + let { ranks } = await getBattleRanksByCity(configId, groupKey, cityId); + let { ranks: memberRanks } = await getPlayerRanksByCity(configId, groupKey, cityId); + let { ranks: memberSettleRanks } = await getPlayerSettleRanksByCity(configId, groupKey, cityId); + await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_CITY_RANK_UPDATE, { cityId, ranks, memberRanks, memberSettleRanks }); + } + } + +} + +export async function gvgBattleEnd() { + console.log('######### gvgBattleEnd #######') + let { configId } = getGVGConfig(); + let dontSendReward = await redisClient().getAsync(REDIS_KEY.GVG_SEND_REWARD) == 'true'; + // 城池占领情况 + await calCityGuard(configId, dontSendReward); + + // 联军排行榜发放奖励 + let leagueKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_LEAGUE_RANK}:${configId}:`); + for(let key of leagueKeys) { + let [,, groupKey] = key.split(':'); + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK, { configId, groupKey }); + let ranks = await r.getRankByRange(); + // 联军排行榜发放奖励 + for(let _obj of ranks) { + let obj = _obj; + let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.LEAGUE, obj.rank); + await sendMailToLeagueByContent(MAIL_TYPE.GVG_BATTLE_LEAGUE_RANK_REWARD, obj.code, { params: [`${obj.rank}`], goods: dicRank.reward }, null, dontSendReward); + } + } + + // 个人排行榜发放奖励 + let playerKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_RANK}:${configId}:`); + for(let key of playerKeys) { + let [,, groupKey] = key.split(':'); + let r = new Rank(REDIS_KEY.GVG_BATTLE_RANK, { configId, groupKey }); + let ranks = await r.getRankByRange(); + + for(let _obj of ranks) { + let obj = _obj; + let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.PLAYER, obj.rank); + await sendMailByContent(MAIL_TYPE.GVG_BATTLE_PLAYER_RANK_REWARD, obj.roleId, { params: [`${obj.rank}`], goods: dicRank.reward }, dontSendReward); + } + } + + // 个人积分排行榜发放奖励 + let playerSettleKeys = await findKeys(`${REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK}:${configId}:`); + for(let key of playerSettleKeys) { + let [,, groupKey] = key.split(':'); + let r = new Rank(REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK, { configId, groupKey }); + let ranks = await r.getRankByRange(); + + for(let _obj of ranks) { + let obj = _obj; + let dicRank = getGVGBattleRankReward(GVG_BATTLE_RANK_TYPE.PLAYER_SETTLE, obj.rank); + await sendMailByContent(MAIL_TYPE.GVG_BATTLE_PLAYER_SETTLE_RANK_REWARD, obj.roleId, { params: [`${obj.rank}`], goods: dicRank.reward }, dontSendReward); + } + } +} + +interface SortCities { cityType: number, cityId: number, index: number, league: string, score: number }; +interface RankAndLastLeague { ranks: LeagueRankInfo[], lastLeague: string }; + +// 赛期末结算守城 +export async function calCityGuard(configId: number, canSendReward: boolean) { + + let sortCities = new Map(); // groupKey => cities + let rankByCity = new Map>(); // groupKey => city => {ranks, lastLeague} + await generateData(configId, sortCities, rankByCity); + for(let [groupKey, cities] of sortCities) { + let cityResult: number[] = []; + let index = 0; // 防死循环,万一出什么事cityResult.length一直不等于cities.length + let guardLeagueCnt = new Map(); + while(cityResult.length != cities.length && (++index < 1000)) { + let sorted = cities + .filter(city => cityResult.indexOf(city.cityId) == -1) + .sort((a, b) => { + if(a.cityType != b.cityType) return a.cityType - b.cityType; + if(a.score != b.score) return b.score - a.score; + return b.cityId - a.cityId; + }); + + for(let { league: leagueCode, cityId } of sorted) { + if(!leagueCode) continue; + let cnt = guardLeagueCnt.get(leagueCode)||0; + if(cnt < GVG.GVG_CITY_OCCUPIED_NUMBER) { + await addGuardCity(configId, groupKey, cityId, leagueCode, canSendReward); + guardLeagueCnt.set(leagueCode, cnt + 1); + cityResult.push(cityId); + break; + } else { + let city = cities.find(cur => cur.cityId == cityId); + if(!city) continue; + if(city.index == -1) { + cityResult.push(city.cityId); continue; + } + let nextIndex = city.index + 1; + let { ranks, lastLeague } = rankByCity.get(groupKey)?.get(city.cityId)||{ ranks: [], lastLeague: '' }; + if(ranks[nextIndex]) { + city.index = nextIndex; + city.league = ranks[nextIndex].code; + city.score = ranks[nextIndex].num; + } else { + if(lastLeague) { + city.index = -1; + city.league = lastLeague; + city.score = 0; + } else { + cityResult.push(city.cityId); continue; + } + } + } + } + } + + } +} + +// 结算守城处理数据 +async function generateData(configId: number, sortCities: Map, rankByCity: Map>) { + let keys = await findKeys(`${REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY}:${configId}:`); + let lastCities = await GVGCityModel.findByConfig(configId); + for(let key of keys) { + let [,, groupKey, _cityId] = key.split(':'); + let cityId = parseInt(_cityId); + let dicCity = gameData.gvgCity.get(cityId); + if(!dicCity) continue; + + let r = new Rank(REDIS_KEY.GVG_BATTLE_LEAGUE_RANK_BY_CITY, { configId, groupKey, cityId }); + let ranks = await r.getRankByRange(); + if(ranks.length <= 0) continue; + if(!sortCities.has(groupKey)) sortCities.set(groupKey, []); + sortCities.get(groupKey).push({ cityType: dicCity.cityType, cityId, index: 0, league: ranks[0].code, score: ranks[0].num }); + + if(!rankByCity.has(groupKey)) rankByCity.set(groupKey, new Map()); + let guardCity = lastCities.find(city => city.cityId == cityId && city.groupKey == groupKey); + if(!rankByCity.get(groupKey).has(cityId)) rankByCity.get(groupKey).set(cityId, { ranks, lastLeague: guardCity?.guardLeague??'' }) + } + for(let { groupKey, cityId, guardLeague } of lastCities) { + if(rankByCity.has(groupKey) && rankByCity.get(groupKey).has(cityId)) continue; + + let dicCity = gameData.gvgCity.get(cityId); + if(!dicCity) continue; + + if(!sortCities.has(groupKey)) sortCities.set(groupKey, []); + sortCities.get(groupKey).push({ cityType: dicCity.cityType, cityId, index: -1, league: guardLeague, score: 0 }); + + if(!rankByCity.has(groupKey)) rankByCity.set(groupKey, new Map()); + if(!rankByCity.get(groupKey).has(cityId)) rankByCity.get(groupKey).set(cityId, { ranks: [], lastLeague: guardLeague||'' }) + } +} + +async function addGuardCity(configId: number, groupKey: string, cityId: number, leagueCode: string, canSendReward: boolean) { + let dicCity = gameData.gvgCity.get(cityId); + let dicCityAdd = gameData.gvgCityAdd.get(dicCity.cityType); + let league = await GVGLeagueModel.findByCodeWithoutPopulate(leagueCode); + if(!league) return; + let leagueGroupKey = await getGroupKey(league.serverId); + if(groupKey != leagueGroupKey) { + console.log('addGuardCity groupKey err', cityId, groupKey, leagueCode, league.serverId); + return; + } + await GVGCityModel.guardCity(configId, groupKey, cityId, league); + await sendMailToLeagueByContent(MAIL_TYPE.GVG_GUARD_CITY_REWARD, leagueCode, { params: [dicCity.cityName], goods: dicCityAdd.occupyReward }, league, canSendReward); + await addCityGuardMessage(league, cityId); +} + +// —————————— 定时器相关 end —————————— // + +// —————————— 推送相关 —————————— // +// 推送 +export async function battleEndSendMessage(groupKey: string, cityId: number, defenseTeam: GVGTeamType, attackTeam: GVGTeamType, attackType: GVG_ATTACK_TYPE) { + let areaId = defenseTeam.curTeamBreak? defenseTeam.fromAreaId: defenseTeam.areaId; + // 推送伤害 + await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_TEAM_ATTACKED, { + cityId, areaId, attackType, teams: [new GVGTeamInList(defenseTeam), new GVGTeamInList(attackTeam)] + }); + if(!defenseTeam.isRobot) { + await sendMessageToUserWithSuc(defenseTeam.roleId, PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, { + cityId, areaId, attackType, teams: [new GVGTeamInList(defenseTeam, true)] + }); + } + await pushTeamBeHurtMessage(defenseTeam, attackTeam); + await pushTeamBeHurtMessage(attackTeam); +} + +export async function sendWinStreakMessage(groupKey: string, cityId: number, attackTeam: GVGTeamType, defenseTeam: GVGTeamType, isSuccess: boolean) { + if (attackTeam && !attackTeam.isRobot) { + let result = await GVGUserDataModel.setWinStreak(attackTeam.configId, attackTeam.leagueCode, attackTeam.roleId, isSuccess); + if (needSendMsg(result.winStreak)) { + await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_WIN_STREAK, new GVGWinStreakInfo(attackTeam, result.winStreak)); + } + } + if (defenseTeam && !defenseTeam.isRobot) { + let result = await GVGUserDataModel.setWinStreak(defenseTeam.configId, defenseTeam.leagueCode, defenseTeam.roleId, !isSuccess); + if (needSendMsg(result.winStreak)) { + await sendMessageToGVGCityWithSuc(groupKey, cityId, PUSH_ROUTE.GVG_WIN_STREAK, new GVGWinStreakInfo(defenseTeam, result.winStreak)); + } + } +} + +function needSendMsg(winStreak: number) { + let arr = parseNumberList(GVG.WIN_STREAK_REPORT_LIMIT); + return arr.includes(winStreak); +} + +// 队伍移动 +export async function pushTeamBeHurtMessage(team: GVGTeamType, replaceTeam?: GVGTeamType) { + if(team.curTeamBreak && team.originPointId > 0) { + await sendAreaPointChange(team.groupKey, team.fromAreaId, team.cityId, team.originPointId, replaceTeam?.originPointId??0, replaceTeam||team); + if(replaceTeam && !replaceTeam.curTeamBreak && replaceTeam.originPointId > 0) { + await sendAreaPointChange(replaceTeam.groupKey, replaceTeam.fromAreaId, replaceTeam.cityId, replaceTeam.originPointId, 0, replaceTeam); + } + } + + if(team.curTeamBreak) { + await pushTeamMoveMessage(team); + } + if(team.isRobot && team.isBroken) { + await sendAreaLeaveMsg(team.groupKey, team.fromAreaId, team.cityId, team.teamCode); + } +} + +export async function pushTeamMoveMessage(team: GVGTeamType) { + if(team.fromAreaId != team.areaId) { + if(team.fromAreaId > 0) await sendAreaLeaveMsg(team.groupKey, team.fromAreaId, team.cityId, team.teamCode); + if(team.areaId > 0) await sendAreaAddMsg(team.groupKey, team.areaId, team.fromAreaId, team.cityId, team); + } +} +// —————————— 推送相关 end —————————— // + +export async function sendAreaLeaveMsg(groupKey: string, areaId: number, cityId: number, teamCode: string) { + await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, { + cityId, areaId, teamCode + }); + await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_AREA_LEAVE, { + cityId, areaId, teamCode + }); +} + +export async function sendAreaAddMsg(groupKey: string, areaId: number, fromAreaId: number, cityId: number, team: GVGTeamType) { + await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_PLAYER_AREA_ADD, { + cityId, areaId, fromAreaId, player: new GVGTeamInList(team) + }); + await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_AREA_ADD, { + cityId, areaId, fromAreaId, spine: new GVGTeamSpineInfo(team, await getServerName(team.serverId)) + }); +} + +export async function sendAreaPointChange(groupKey: string, areaId: number, cityId: number, targetPointId: number, originPointId: number, team: GVGTeamType) { + await sendMessageToGVGAreaByTeamWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_AREA_POINT_CHANGE, { + cityId, areaId, targetPointId, originPointId, point: new GVGTeamInListOnPoint(team.pointId, true, team) + }); + await sendMessageToGVGAreaWithSuc(groupKey, areaId, PUSH_ROUTE.GVG_SPINE_POINT_CHANGE, { + cityId, areaId, targetPointId, originPointId, spine: new GVGTeamSpineInfo(team, await getServerName(team.serverId)) + }) +} + +// 外面页面上的排行榜 +export async function getBattleRank(redisKey: REDIS_KEY, keyParam: KeyNameParam, myId: myIdInter) { + let r = new Rank(redisKey, keyParam); + r.setGenerFieldsFun((obj => { + if(obj instanceof LeagueRankInfo) return { rank: obj.rank, name: obj.name, score: obj.num } + if(obj instanceof RoleRankInfo) return { rank: obj.rank, name: obj.roleName, score: obj.num } + })); + + let { ranks, myRank } = await r.getRankListWithMyRank(myId); + if (!myRank) { + if(redisKey == REDIS_KEY.GVG_BATTLE_RANK) { + myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); + } else if (redisKey == REDIS_KEY.GVG_BATTLE_LEAGUE_RANK) { + myRank = await r.generMyRankWithLeague(myId.leagueCode, 0, 0); + } else if (redisKey == REDIS_KEY.GVG_BATTLE_USR_SETTLE_RANK) { + myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); + } + } + return { ranks, myRank } +} + +export async function initTeamToMem() { + let sid = pinus.app.getServerId(); + let servers = pinus.app.getServersByType('guild'); + let { configId, period } = getGVGPeriodData(); + if(period != GVG_PERIOD.BATTLE) return; + let teams = await GVGTeamModel.findByConfigId(configId); + for(let team of teams) { + if(team.isBroken) continue; + let dispacthSid = await dispatchTeam(team.groupKey, team.cityId); + if(dispacthSid == sid) { + let teamObj = getGVGBattleData(team.groupKey); + teamObj.enterCity(team); + } + } +} + +async function dispatchTeam(groupKey: string, cityId: number) { + let groupId = ''; + if(groupKey.startsWith('s')) { + let serverId = parseInt(groupKey.slice(1)); + groupId = (await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG)).toString(); + } else { + groupId = groupKey.slice(1); + } + + let servers = pinus.app.getServersByType('guild'); + let sid = (await dispatch(redisClient(), `${groupId}_${cityId}`, servers, 'guild'))?.id; + return sid; +} + +/** + * 查询队伍中的武将是否可以使用 + * @param roleId + * @param index + * @param lineup + * @returns + */ +export async function checkGVGLineupWhenSave(roleId: string, index: number, lineup: LineupHero[]) { + const teams = await GVGTeamModel.findByRole(roleId, '-_id index lineup'); + for(let { actorId, subHid } of lineup) { + let dicHero = gameData.hero.get(actorId); + if(subHid && (!dicHero || dicHero.urType != 1)) return STATUS.HERO_CAN_NOT_SET_SUB; + + for(let team of teams) { + // 查actorId没有在其他队伍中使用 + if(team.index != index) { + let hasActor = team.lineup.find(hero => hero.actorId == actorId); + if(hasActor) return STATUS.GVG_TEAM_HERO_DUPLICATE; + + // 查actorId没有在其他队伍作为副将 + let hasActorIsSubHero = team.lineup.find(hero => hero.subHid == actorId); + if(hasActorIsSubHero) return STATUS.GVG_TEAM_HERO_USED_AS_SUB_HERO; + // 查副将 + if(subHid) { + let hasSubHero = team.lineup.find(hero => hero.actorId == subHid); + if(hasSubHero) return STATUS.GVG_TEAM_SUB_HERO_DUPLICATE; + } + } else { + // 查actorId没有在其他队伍作为副将 + let hasActorIsSubHero = lineup.find(hero => hero.subHid == actorId); + if(hasActorIsSubHero) return STATUS.GVG_TEAM_HERO_USED_AS_SUB_HERO; + + // 查副将 + if(subHid) { + let hasSubHero = lineup.find(hero => hero.actorId == subHid); + if(hasSubHero) return STATUS.GVG_TEAM_SUB_HERO_DUPLICATE; + } + } + } + } + return STATUS.SUCCESS +} diff --git a/game-server/app/services/gvg/gvgFightService.ts b/game-server/app/services/gvg/gvgFightService.ts index 8d0dc9f65..4d4cd7831 100644 --- a/game-server/app/services/gvg/gvgFightService.ts +++ b/game-server/app/services/gvg/gvgFightService.ts @@ -1,551 +1,551 @@ -// 征战中原相关 - -import moment = require("moment"); -import { GVG_PERIOD, GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, VESTIGE_OPP_STATUS, VESTIGE_STATUS } from "../../consts"; -import { ArtifactModel } from "../../db/Artifact"; -import { GVGConfigModel } from "../../db/GVGConfig"; -import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague"; -import { GVGUserDataModel } from "../../db/GVGUserData"; -import { GVGVestigeModel } from "../../db/GVGVestige"; -import { GVGVestigeLeagueRankModel, GVGVestigeLeagueRankType } from "../../db/GVGVestigeLeagueRank"; -import { GVGVestigeLockModel } from "../../db/GVGVestigeLock"; -import { GVGVestigeRankModel, GVGVestigeRankType, GVGVestigeRankUpdate } from "../../db/GVGVestigeRank"; -import { GVGVestigeRecModel, GVGVestigeRecType, GVGVestigeRecUpdate } from "../../db/GVGVestigeRec"; -import { GVGVestigeSumRankModel, GVGVestigeSumRankType } from "../../db/GVGVestigeSumRank"; -import { HeroModel, HeroType } from "../../db/Hero"; -import { RoleModel } from "../../db/Role"; -import { OppDetailData, OppPlayerHeroInfo, OppPlayerInfo } from "../../domain/gvgField/gvgDb"; -import { GVGVestigeOppPlayer } from "../../domain/gvgField/returnData"; -import { KeyNameParam, LeagueRankInfo, myIdInter, RoleRankInfo } from "../../domain/rank"; -import { gameData, getGVGVestigeLeagueRank, getGVGVestigePlayerRank, getGVGVestigeRange } from "../../pubUtils/data"; -import { GVG } from "../../pubUtils/dicParam"; -import { RewardInter } from "../../pubUtils/interface"; -import { getCurDay, getTimeFun, nowSeconds } from "../../pubUtils/timeUtil"; -import { getRandEelm } from "../../pubUtils/util"; -import { getNumberArr, uniqueArr } from "../ladderService"; -import { sendMailByContent } from "../mailService"; -import { getHeroesAttributes } from "../playerCeService"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { Rank } from "../rankService"; -import { findKeys, getAllServerName, redisClient } from "../redisService"; -import { isDevelopEnv } from "../utilService"; -import { addGVGReward, combinePushItem } from "./gvgItemService"; -import { calFighterContribute } from "./gvgPrepareService"; -import { addVestigeLeagueRankRec, addVestigeRankMessage } from "./gvgRecService"; -import { getGroupKey, getGVGServerType, getPeriodByTime } from "./gvgService"; -import { Combo } from "../../domain/battleField/pvp"; -import { getRemoteRplPrefix } from "../../pubUtils/battleUtils"; -import { pinus } from "pinus"; -import { pushIconShow } from "../connectorService"; - -let gvgFightTime = undefined; - -// !!注意,这个函数会改动内存,线上不应该使用 -export function setPeriodTime(startFightTime: number, endFightTime: number) { - gvgFightTime = { startFightTime, endFightTime } -} - -export function resetPeriodTime() { - gvgFightTime = undefined; -} - -// 备战期的遗迹和激战期的开始结束战斗时间 -export function getFightTimeByPeriod(period: GVG_PERIOD, time?: number) { - let dicPeriod = gameData.gvgPeriod.get(period); - if(!dicPeriod) return { startFightTime: 0, endFightTime: 0 }; - - if(isDevelopEnv() && gvgFightTime) { - return gvgFightTime; - } - - return { - startFightTime: getTimeFun(time).getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond), - endFightTime: getTimeFun(time).getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond), - } -} - -export function checkFightTime() { - let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.PREPARE); - let now = nowSeconds(); - return startFightTime <= now && endFightTime >= now; -} - -// 征战中原每天随机的遗迹点 -export async function getVestiges(serverId: number) { - let groupKey = await getGroupKey(serverId); - let serverType = await getGVGServerType(serverId); - let vestige = await GVGVestigeModel.getVestige(groupKey); - if(!vestige) { - let dicGVGVestige = gameData.gvgVestigeByServerType.get(serverType)||[]; - let day = getCurDay(true); - let pool = dicGVGVestige.filter(cur => cur.openday.includes(day)); - - let cnt = gameData.gvgVestigeCntByServerType.get(serverType)||0; - let randResult = getRandEelm(pool, cnt); - vestige = await GVGVestigeModel.initTodayVestige(groupKey, randResult); - } - return vestige.vestiges||[]; -} - -export async function getMyVestiges(serverId: number, roleId: string) { - let vestiges = await getVestiges(serverId); - let myRanks = await GVGVestigeRankModel.findAllByRole(roleId); - let result: { vestigeId: number, position: string, myRank: number }[] = []; - for(let vestige of vestiges) { - let myRank = myRanks.find(cur => cur.vestigeId == vestige.vestigeId); - result.push({ ...vestige, myRank: myRank?.rank||0 }); - } - return result; -} - -export async function checkVestige(serverId: number, vestigeId: number) { - let vestiges = await getVestiges(serverId); - return !!vestiges.find(cur => cur.vestigeId == vestigeId); -} - -// 根据自己排名随机出对手排名 -export function refreshVestigeOppRanks(rank: number) { - let dicRange = getGVGVestigeRange(rank); - if(!dicRange) return []; - - let { rangeBeforeFrom, rangeBeforeTo, rangeBeforeNum, rangeAfterFrom, rangeAfterTo, rangeAfterNum } = dicRange; - let beforeRanks = randomRank(rangeBeforeFrom == -1? rank: rangeBeforeFrom, rangeBeforeTo == -1? rank: rangeBeforeTo, rangeBeforeNum); - let afterRanks = randomRank(rangeAfterFrom == -1? rank: rangeAfterFrom, rangeAfterTo == -1? rank: rangeAfterTo, rangeAfterNum); - - let topRanks = getNumberArr(dicRange.topChallengeFrom, dicRange.topChallengeTo); - let ranks = [...topRanks, ...beforeRanks, ...afterRanks]; - return uniqueArr(ranks.sort((a, b) => a - b)); -} - -function randomRank(min: number, max: number, len: number) { - if(min == max || len == 0) return []; - let arr = getNumberArr(min + 1, max); - return getRandEelm(arr, len); -} - -// 根据ranks获取oppPlayer显示数据 -export async function getOppPlayerByRanks(serverId: number, groupKey: string, vestigeId: number, ranks: number[]) { - let serverNames = await getAllServerName(); - let opps = await GVGVestigeRankModel.findByRanks(groupKey, vestigeId, ranks); - let roleIds = opps.map(cur => cur.roleId); - let roles = await RoleModel.findByRoleIds(roleIds, 'roleId roleName head frame spine heads frames spines title lv guildName serverId updatedAt') - let dicRankMap = gameData.gvgVestige.get(vestigeId); - if(!dicRankMap) return []; - let result: GVGVestigeOppPlayer[] = []; - for(let rank of ranks) { - let obj = new GVGVestigeOppPlayer(rank); - let opp = opps.find(cur => cur.rank == rank); - let dicCurRank = dicRankMap.get(rank); - if(opp) { - let role = roles.find(cur => cur.roleId == opp.roleId); - if(!role) continue; - let lineupce = opp.lineup.reduce((pre, cur) => pre + cur.ce, 0); - const { leagueCode, name } = opp; - obj.setByRole(role, serverNames, lineupce, dicCurRank?.score||0, leagueCode, name); - } else { - obj.setByDic(dicCurRank, serverNames[serverId]); - } - result.push(obj); - } - - return result; -} - -// 获取其他遗迹里使用过的武将 -export async function getVestigeUsedHeroes(roleId: string, curVestigeId: number) { - let myDatas = await GVGVestigeRankModel.findAllByRole(roleId); - let result: number[] = []; - for(let { vestigeId, lineup = [] } of myDatas) { - if(vestigeId == curVestigeId) continue; - for(let { actorId, subHid } of lineup) { - result.push(actorId); - if(subHid) result.push(subHid); - } - } - return result; -} - -// 是否在其他遗迹中使用过这个武将 -export async function checkHeroIsUsedInOtherVestige(roleId: string, curVestigeId: number, heroes: { actorId: number, subHid: number }[]) { - let usedHeroes = await getVestigeUsedHeroes(roleId, curVestigeId); - for(let { actorId, subHid } of heroes) { - if(usedHeroes.indexOf(actorId) != -1) return true; - // 查副将 - if(subHid) { - if(usedHeroes.indexOf(subHid) != -1) return true; - - let hasSubHero = heroes.find(hero => hero.actorId == subHid); - if(hasSubHero) return true; - } - } - return false; -} - -// 检查我的排名是否可以挑战对方的排名 -export function checkVestigeRank(myRank: number, targetRank: number) { - let dicRange = getGVGVestigeRange(myRank); - if(!dicRange) return false; - if(myRank == targetRank || targetRank == 0) return false; - - // 是否可以挑战最前的几个排名 - if(dicRange.topChallengeFrom <= targetRank && dicRange.topChallengeTo >= targetRank) return true; - if(dicRange.rangeBeforeTo == -1) { - if(dicRange.rangeBeforeFrom < targetRank && myRank > targetRank) return true; - } else { - if(dicRange.rangeBeforeFrom < targetRank && dicRange.rangeBeforeTo >= targetRank) return true; - } - if(dicRange.rangeAfterTo == -1) { - if(dicRange.rangeAfterFrom < targetRank && myRank > targetRank) return true; - } else { - if(dicRange.rangeAfterFrom < targetRank && dicRange.rangeAfterTo >= targetRank) return true; - } - - return false; -} - -export function isRobot(roleId: string) { - if(!roleId) roleId = ''; - return roleId.startsWith('robot'); -} - -export async function checkVestigeOppStatus(configId: number, groupKey: string, vestigeId: number, roleId: string, myRank: number, targetRoleId: string, rank: number) { - - let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); - if(!myData || myData.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE; - - if(isRobot(targetRoleId)) { - let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank); - if(targetData) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE; - } else { - let targetData = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId); - if(targetData?.rank != rank) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE; - } - let lockResult = await GVGVestigeLockModel.chooseOppLock(groupKey, vestigeId, rank, configId, roleId, targetRoleId); - if(!lockResult) return VESTIGE_OPP_STATUS.OPP_IS_LOCKED; - - return VESTIGE_OPP_STATUS.BATTLE; -} - -// 生成防守数据 -export async function generateDefenseInfo(roleId: string, vestigeId: number, rank: number) { - if(isRobot(roleId)) { - let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); // 调用之前已经验证过了 - let dicWar = gameData.war.get(dicRank?.warId); - let dicWarJson = gameData.warJson.get(dicWar?.dispatchJsonId); - if(!dicWarJson) return new OppPlayerInfo(); - - let heroes: OppPlayerHeroInfo[] = []; - for(let json of dicWarJson) { - if(json.relation == 2) { - let hero = new OppPlayerHeroInfo(); - hero.setByWarJson(json); - heroes.push(hero); - } - } - let info = new OppPlayerInfo(); - info.initByRobot(dicRank, heroes, true); - return info; - } else { - let playerVestigeData = await GVGVestigeRankModel.findByRole(vestigeId, roleId); - if(!playerVestigeData) return null; - let lineup = playerVestigeData.lineup||[]; - let hids = lineup.map(cur => cur.actorId); - let role = await RoleModel.findByRoleId(playerVestigeData.roleId, 'roleId roleName heads head frames frame spines spine title lv'); - let heroes = await HeroModel.findByHidRange(hids, playerVestigeData.roleId, 'hid skinId lv star colorStar quality ce'); - let league = await GVGLeagueModel.findByCode(playerVestigeData.leagueCode); - - let info = new OppPlayerInfo(); - info.initByPlayer(playerVestigeData.rank, role, league, true); - info.setPlayerHeroes(heroes, lineup, playerVestigeData.combo||[]); - return info; - } -} - -export async function generateAttackInfo(roleId: string, league: GVGLeagueType, rank: number) { - let role = await RoleModel.findByRoleId(roleId, 'roleId roleName heads head frames frame spines spine title lv'); - let info = new OppPlayerInfo(); - info.initByPlayer(rank, role, league, false); - return info; -} - -export async function generateAttackHeroInfo(lineup: { actorId: number, dataId: number, order: number, subHid: number }[], dbHeroes: HeroType[], combo: Combo[]) { - let info = new OppPlayerInfo(); - info.setPlayerHeroes(dbHeroes, lineup, combo); - return info; -} - -export async function getOppDetailData(rec: GVGVestigeRecType) { - let isRobot = rec.defenseInfo.isRobot; - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank); - let result = new OppDetailData(rec, getVestigeRecStatus(rec)); - if(!isRobot) { - const dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); - const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); - const defenseInfo = rec.defenseInfo.heroes||[]; - const hids: number[] = []; - for(let { hid, subHid } of defenseInfo) { - hids.push(hid); - if(subHid) hids.push(subHid); - } - const heroes = await HeroModel.findByHidRange(hids, rec.defenseRoleId, 'hid lv quality star colorStar skins ce skinId'); - const artifactSeids = heroes.map(hero => hero.artifact); - const artifacts = await ArtifactModel.findbySeqIds(rec.defenseRoleId, artifactSeids); - result.setByPlayer(dicWarJson, defenseInfo, heroes, artifacts, rec.defenseInfo.combo); - let attrByHid = await getHeroesAttributes(rec.defenseRoleId); - for(let [hid, attribute] of attrByHid) { - result.setAttribute(hid, attribute.getAttributesToString()); - } - } - - return result; - -} - -// 根据记录里的时间判断当前状态 -export function getVestigeRecStatus(rec: GVGVestigeRecType) { - let { checkTime = 0, battleTime = 0, endTime = 0, cancel } = rec; - if(cancel) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) }; - if(endTime > 0 && endTime <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) }; - if(battleTime > 0 && battleTime <= Date.now() && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.BATTLE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN }; - if(checkTime > 0 && checkTime <= Date.now() && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.CHECK, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN }; - // 超时的 - if(battleTime > 0 && endTime == 0 && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN }; - if(checkTime > 0 && battleTime == 0 && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN }; - return { status: VESTIGE_STATUS.NO, time: 0 }; -} - -// 将开始战斗时候的阵容存到防守阵容 -export async function updateMyVestigeRank(isChange: boolean, atkData: GVGVestigeRankType, defData: GVGVestigeRankType, historyRank: number, rec: GVGVestigeRecType) { - let update: GVGVestigeRankUpdate = {}, needUpdate = false; - if(isChange) { - if(atkData && !atkData.hasDefense) { // 只有第一次挑战且自己没有主动保存过阵容的时候才会这么保存 - let heroes = rec.attackInfo.heroes||[]; - let lineup = heroes.map(hero => ({ actorId: hero.hid, dataId: hero.dataId, order: hero.order, ce: hero.ce, subHid: hero.subHid })); - update.lineup = lineup; - update.hasDefense = true; - needUpdate = true; - } - if(atkData && (historyRank == 0 || atkData.rank < historyRank)) { // 更新历史最高排名 - update.historyRank = atkData.rank; - needUpdate = true; - } - if(atkData) { // 排名变化时刷新对手 - let oppRanks = refreshVestigeOppRanks(atkData.rank); - update.oppRanks = oppRanks; - needUpdate = true; - } - } - if(needUpdate) { - atkData = await GVGVestigeRankModel.updateByRoleId(atkData.vestigeId, atkData.roleId, update); - } - if(isChange && defData) { - let oppRanks = refreshVestigeOppRanks(defData.rank); - defData = await GVGVestigeRankModel.updateByRoleId(defData.vestigeId, defData.roleId, { oppRanks }); - } - return atkData -} - -export function calBreakGoods(vestige: number, historyRank: number, rank: number) { - let dicRankMap = gameData.gvgVestige.get(vestige); - if(!dicRankMap) return { rewards: [], leagueRewards: [] }; - let rewards: RewardInter[] = [], leagueRewards: RewardInter[] = []; - for(let i = historyRank + 1; i <= rank; i++) { - let dicRank = dicRankMap.get(i); - if(!dicRank) continue; - combinePushItem(rewards, dicRank.onceReward); - combinePushItem(leagueRewards, dicRank.onceLeagueReward); - } - return { rewards, leagueRewards } -} - -// 玩家当天的驻扎记录,没有的话就创建一个 -export async function getMyVestigeRank(configId: number, groupKey: string, vestigeId: number, roleId: string, myLeague?: GVGLeagueType) { - - let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名 - if(!myVestigeRank) { - let role = await RoleModel.findByRoleId(roleId, 'roleId guildCode'); - let oppRanks = refreshVestigeOppRanks(-1); - if(!myLeague) { - myLeague = await GVGLeagueModel.findLeagueByGuild(role.guildCode); - if(!myLeague) return null - } - const { leagueCode, name } = myLeague; - myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupKey, role, leagueCode, name, oppRanks ); - } - return myVestigeRank; -} - -// 保存排行榜 -export async function saveScoreToRank(rec: GVGVestigeRecType) { - await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.attackInfo); - await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.defenseInfo); -} - -export function getDayKeyInfo() { - return moment().format('YYMMDD'); -} - -export async function savePlayerRank(configId: number, groupKey: string, vestigeId: number, playerInfo: Partial) { - if(playerInfo.isRobot) return - let dicRankMap = gameData.gvgVestige.get(vestigeId); - let newRank = dicRankMap?.get(playerInfo.newRank)?.score||0; - let oldRank = dicRankMap?.get(playerInfo.oldRank)?.score||0; - - let nextWeek = getTimeFun().getAfterDayWithHour(7); - let myScore = await GVGVestigeSumRankModel.incScore(playerInfo.roleId, playerInfo.leagueCode, configId, groupKey, newRank - oldRank); - let r1 = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day: getDayKeyInfo() }); - await r1.setExpire(nextWeek); - await r1.setRankWithRoleInfo(playerInfo.roleId, myScore.score, myScore.updatedAt.getTime()); - let leagueScore = await GVGVestigeLeagueRankModel.incScore(configId, playerInfo.leagueCode, groupKey, newRank - oldRank); - let r2 = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day: getDayKeyInfo() }); - await r2.setExpire(nextWeek); - await r2.setRankWithLeagueInfo(playerInfo.leagueCode, leagueScore.score, leagueScore.updatedAt.getTime()); -} - -export async function getVestigeRank(redisKey: REDIS_KEY, isSimple: boolean, keyParam: KeyNameParam, myId: myIdInter, serverNames?: any) { - let r = new Rank(redisKey, keyParam); - r.setGenerFieldsFun((obj => { - if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL && obj instanceof RoleRankInfo) { - if(isSimple) { - return { rank: obj.rank, name: obj.roleName, serverName: serverNames[obj.serverId], score: obj.num } - } else { - return { ...obj, serverName: serverNames[obj.serverId], score: obj.num } - } - } - if(redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE && obj instanceof LeagueRankInfo) { - if(isSimple) { - return { rank: obj.rank, name: obj.name, score: obj.num } - } else { - return { ...obj, score: obj.num, leader: {...obj.leader, serverName: serverNames[obj.leader.serverId]}}; - } - } - return obj - })); - - let { ranks, myRank } = await r.getRankListWithMyRank(myId); - if (!myRank) { - if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) { - myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); - } else if (redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE) { - myRank = await r.generMyRankWithLeague(myId.leagueCode, 0, 0); - } - } - return { ranks, myRank } -} - -// systimer 服 每天晚上22点 -export async function saveVestigeRankSchedule() { - let config = await GVGConfigModel.findConfig(); - let period = getPeriodByTime(config.teamTime, config.prepareTime, config.battleTime, config.scheduleTime); - if(period != GVG_PERIOD.PREPARE) return; - let day = getDayKeyInfo(); - let keys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_LEAGUE}:${day}:`); - for(let key of keys) { - let [,, groupKey] = key.split(':'); - let r = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day}); - let ranks = await r.getRankByRangeRaw(); - await GVGVestigeLeagueRankModel.saveRank(groupKey, ranks); - await addVestigeLeagueRankRec(config.configId, groupKey, ranks); - await addVestigeRankMessage(ranks); - } - - let memberKeys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_MEMBER_ALL}:${day}:`); - for(let key of memberKeys) { - let [,, groupKey] = key.split(':'); - let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day}); - let ranks = await r.getRankByRangeRaw(); - await GVGVestigeSumRankModel.saveRank(groupKey, ranks); - } - let playerSumRanks = await GVGVestigeSumRankModel.findAllScores(); - let userDatas = await GVGUserDataModel.addVestigeScores(config.configId, playerSumRanks); - for(let userData of userDatas) { - await sendMessageToUserWithSuc(userData.roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode: userData.leagueCode, job: LEAGUE_JOB.FIGHTER, sumContribute: calFighterContribute(userData.contribute) }); - } -} - -// systimer 服,每周六5点 -export async function gvgBattlePeriodSchedule() { - const config = await GVGConfigModel.findConfig(); - await sendUngotVestigeReward(config.configId); -} - -export async function sendUngotVestigeReward(configId: number) { - const playerDatas = await GVGVestigeSumRankModel.getAllCanReceiveRanks(configId); - const leagueCodes: string[] = []; - const dataByLeague = new Map>(); // leagueCode => playerdata - const receiveLeagueParam: { _id: string, roleIds: string[] }[] = [], receivePlayerParam: string[] = []; - for(let player of playerDatas) { - if(leagueCodes.indexOf(player.leagueCode) == -1) { - leagueCodes.push(player.leagueCode); - } - if(!dataByLeague.has(player.leagueCode)) dataByLeague.set(player.leagueCode, new Map()); - if(!dataByLeague.get(player.leagueCode).has(player.roleId)) dataByLeague.get(player.leagueCode).set(player.roleId, { playerRanks: [], leagueRanks: [] }); - dataByLeague.get(player.leagueCode).get(player.roleId).playerRanks.push({ _id: player._id, rank: player.rank }); - - receivePlayerParam.push(player._id); - } - - const leagueDatas = await GVGVestigeLeagueRankModel.getAllCanReceiveRanks(configId, leagueCodes); - for(let leagueData of leagueDatas) { - let players = dataByLeague.get(leagueData.leagueCode); - if(!players) continue; - for(let [roleId, data] of players) { - if(leagueData.receiveMembers.indexOf(roleId) == -1) { - data.leagueRanks.push({ _id: leagueData._id, rank: leagueData.rank }); - let index = receiveLeagueParam.findIndex(cur => cur._id == leagueData._id); - if(index == -1) { - receiveLeagueParam.push({ _id: leagueData._id, roleIds: [ roleId ] }); - } else { - receiveLeagueParam[index].roleIds.push(roleId); - } - } - } - } - - for(let [ leagueCode, players ] of dataByLeague) { - for(let [ roleId, { playerRanks, leagueRanks }] of players) { - let { leagueReward, rewards } = calVestigeLeagueBoxRewards(leagueRanks, playerRanks); - if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, null, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); - if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.VESTIGE_REWARD, roleId, { params: [`${configId}`], goods: rewards }); - } - } - - await GVGVestigeSumRankModel.receiveRanks(receivePlayerParam); - await GVGVestigeLeagueRankModel.receiveManyRanks(receiveLeagueParam); -} - -export function calVestigeLeagueBoxRewards(canReceiveRanks: { rank: number }[], canReceivePlayerRanks: { rank: number }[]) { - let rewards: RewardInter[] = [], leagueReward: RewardInter[] = []; - for(let { rank } of canReceiveRanks) { - let dicRank = getGVGVestigeLeagueRank(rank); - if(!dicRank) { console.error('dic_zyz_GVGVestigeLeagueRank error'); continue; } - // console.log('###### league', rank, dicRank) - combinePushItem(rewards, dicRank.rankReward); - combinePushItem(leagueReward, dicRank.rankLeagueReward); - } - for(let { rank } of canReceivePlayerRanks) { - let dicRank = getGVGVestigePlayerRank(rank); - if(!dicRank) { console.error('dic_zyz_GVGVestigPlayerRank error'); continue; } - // console.log('###### player', rank, dicRank) - combinePushItem(rewards, dicRank.rankPlayerReward); - combinePushItem(leagueReward, dicRank.rankPlayerLeagueReward); - } - let boxPreview: { id: number, count: number, itemType: number }[] = []; - for(let { id, count } of rewards) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM }); - for(let { id, count } of leagueReward) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM }); - return { - leagueReward, rewards, boxPreview, canReceiveBox: canReceiveRanks.length > 0 || canReceivePlayerRanks.length > 0 - } -} - -export async function pushGvgFightIconShow(roleId: string, battleCode: string) { - const rec = await GVGVestigeRecModel.findByBattleCode(battleCode); - let result: (GVGVestigeRecUpdate & { rplFileUrl: string })[] = []; - const { attackRoleId, hasRpl, remoteUrl } = rec; - const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; - const obj = getVestigeRecStatus(rec); - if (obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl }); - let gvgFightRecs = { list: result, rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) }; - - await pushIconShow(roleId, false, gvgFightRecs) -} \ No newline at end of file +// 征战中原相关 + +import moment = require("moment"); +import { GVG_PERIOD, GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, VESTIGE_OPP_STATUS, VESTIGE_STATUS } from "@consts"; +import { ArtifactModel } from "@db/Artifact"; +import { GVGConfigModel } from "@db/GVGConfig"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import { GVGUserDataModel } from "@db/GVGUserData"; +import { GVGVestigeModel } from "@db/GVGVestige"; +import { GVGVestigeLeagueRankModel, GVGVestigeLeagueRankType } from "@db/GVGVestigeLeagueRank"; +import { GVGVestigeLockModel } from "@db/GVGVestigeLock"; +import { GVGVestigeRankModel, GVGVestigeRankType, GVGVestigeRankUpdate } from "@db/GVGVestigeRank"; +import { GVGVestigeRecModel, GVGVestigeRecType, GVGVestigeRecUpdate } from "@db/GVGVestigeRec"; +import { GVGVestigeSumRankModel, GVGVestigeSumRankType } from "@db/GVGVestigeSumRank"; +import { HeroModel, HeroType } from "@db/Hero"; +import { RoleModel } from "@db/Role"; +import { OppDetailData, OppPlayerHeroInfo, OppPlayerInfo } from "@domain/gvgField/gvgDb"; +import { GVGVestigeOppPlayer } from "@domain/gvgField/returnData"; +import { KeyNameParam, LeagueRankInfo, myIdInter, RoleRankInfo } from "@domain/rank"; +import { gameData, getGVGVestigeLeagueRank, getGVGVestigePlayerRank, getGVGVestigeRange } from "@pubUtils/data"; +import { GVG } from "@pubUtils/dicParam"; +import { RewardInter } from "@pubUtils/interface"; +import { getCurDay, getTimeFun, nowSeconds } from "@pubUtils/timeUtil"; +import { getRandEelm } from "@pubUtils/util"; +import { getNumberArr, uniqueArr } from "../ladderService"; +import { sendMailByContent } from "../mailService"; +import { getHeroesAttributes } from "../playerCeService"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { Rank } from "../rankService"; +import { findKeys, getAllServerName, redisClient } from "../redisService"; +import { isDevelopEnv } from "../utilService"; +import { addGVGReward, combinePushItem } from "./gvgItemService"; +import { calFighterContribute } from "./gvgPrepareService"; +import { addVestigeLeagueRankRec, addVestigeRankMessage } from "./gvgRecService"; +import { getGroupKey, getGVGServerType, getPeriodByTime } from "./gvgService"; +import { Combo } from "@domain/battleField/pvp"; +import { getRemoteRplPrefix } from "@pubUtils/battleUtils"; +import { pinus } from "pinus"; +import { pushIconShow } from "../connectorService"; + +let gvgFightTime = undefined; + +// !!注意,这个函数会改动内存,线上不应该使用 +export function setPeriodTime(startFightTime: number, endFightTime: number) { + gvgFightTime = { startFightTime, endFightTime } +} + +export function resetPeriodTime() { + gvgFightTime = undefined; +} + +// 备战期的遗迹和激战期的开始结束战斗时间 +export function getFightTimeByPeriod(period: GVG_PERIOD, time?: number) { + let dicPeriod = gameData.gvgPeriod.get(period); + if(!dicPeriod) return { startFightTime: 0, endFightTime: 0 }; + + if(isDevelopEnv() && gvgFightTime) { + return gvgFightTime; + } + + return { + startFightTime: getTimeFun(time).getTimeWithHour(dicPeriod.startHour, dicPeriod.startMinute, dicPeriod.startSecond), + endFightTime: getTimeFun(time).getTimeWithHour(dicPeriod.endHour, dicPeriod.endMinute, dicPeriod.endSecond), + } +} + +export function checkFightTime() { + let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.PREPARE); + let now = nowSeconds(); + return startFightTime <= now && endFightTime >= now; +} + +// 征战中原每天随机的遗迹点 +export async function getVestiges(serverId: number) { + let groupKey = await getGroupKey(serverId); + let serverType = await getGVGServerType(serverId); + let vestige = await GVGVestigeModel.getVestige(groupKey); + if(!vestige) { + let dicGVGVestige = gameData.gvgVestigeByServerType.get(serverType)||[]; + let day = getCurDay(true); + let pool = dicGVGVestige.filter(cur => cur.openday.includes(day)); + + let cnt = gameData.gvgVestigeCntByServerType.get(serverType)||0; + let randResult = getRandEelm(pool, cnt); + vestige = await GVGVestigeModel.initTodayVestige(groupKey, randResult); + } + return vestige.vestiges||[]; +} + +export async function getMyVestiges(serverId: number, roleId: string) { + let vestiges = await getVestiges(serverId); + let myRanks = await GVGVestigeRankModel.findAllByRole(roleId); + let result: { vestigeId: number, position: string, myRank: number }[] = []; + for(let vestige of vestiges) { + let myRank = myRanks.find(cur => cur.vestigeId == vestige.vestigeId); + result.push({ ...vestige, myRank: myRank?.rank||0 }); + } + return result; +} + +export async function checkVestige(serverId: number, vestigeId: number) { + let vestiges = await getVestiges(serverId); + return !!vestiges.find(cur => cur.vestigeId == vestigeId); +} + +// 根据自己排名随机出对手排名 +export function refreshVestigeOppRanks(rank: number) { + let dicRange = getGVGVestigeRange(rank); + if(!dicRange) return []; + + let { rangeBeforeFrom, rangeBeforeTo, rangeBeforeNum, rangeAfterFrom, rangeAfterTo, rangeAfterNum } = dicRange; + let beforeRanks = randomRank(rangeBeforeFrom == -1? rank: rangeBeforeFrom, rangeBeforeTo == -1? rank: rangeBeforeTo, rangeBeforeNum); + let afterRanks = randomRank(rangeAfterFrom == -1? rank: rangeAfterFrom, rangeAfterTo == -1? rank: rangeAfterTo, rangeAfterNum); + + let topRanks = getNumberArr(dicRange.topChallengeFrom, dicRange.topChallengeTo); + let ranks = [...topRanks, ...beforeRanks, ...afterRanks]; + return uniqueArr(ranks.sort((a, b) => a - b)); +} + +function randomRank(min: number, max: number, len: number) { + if(min == max || len == 0) return []; + let arr = getNumberArr(min + 1, max); + return getRandEelm(arr, len); +} + +// 根据ranks获取oppPlayer显示数据 +export async function getOppPlayerByRanks(serverId: number, groupKey: string, vestigeId: number, ranks: number[]) { + let serverNames = await getAllServerName(); + let opps = await GVGVestigeRankModel.findByRanks(groupKey, vestigeId, ranks); + let roleIds = opps.map(cur => cur.roleId); + let roles = await RoleModel.findByRoleIds(roleIds, 'roleId roleName head frame spine heads frames spines title lv guildName serverId updatedAt') + let dicRankMap = gameData.gvgVestige.get(vestigeId); + if(!dicRankMap) return []; + let result: GVGVestigeOppPlayer[] = []; + for(let rank of ranks) { + let obj = new GVGVestigeOppPlayer(rank); + let opp = opps.find(cur => cur.rank == rank); + let dicCurRank = dicRankMap.get(rank); + if(opp) { + let role = roles.find(cur => cur.roleId == opp.roleId); + if(!role) continue; + let lineupce = opp.lineup.reduce((pre, cur) => pre + cur.ce, 0); + const { leagueCode, name } = opp; + obj.setByRole(role, serverNames, lineupce, dicCurRank?.score||0, leagueCode, name); + } else { + obj.setByDic(dicCurRank, serverNames[serverId]); + } + result.push(obj); + } + + return result; +} + +// 获取其他遗迹里使用过的武将 +export async function getVestigeUsedHeroes(roleId: string, curVestigeId: number) { + let myDatas = await GVGVestigeRankModel.findAllByRole(roleId); + let result: number[] = []; + for(let { vestigeId, lineup = [] } of myDatas) { + if(vestigeId == curVestigeId) continue; + for(let { actorId, subHid } of lineup) { + result.push(actorId); + if(subHid) result.push(subHid); + } + } + return result; +} + +// 是否在其他遗迹中使用过这个武将 +export async function checkHeroIsUsedInOtherVestige(roleId: string, curVestigeId: number, heroes: { actorId: number, subHid: number }[]) { + let usedHeroes = await getVestigeUsedHeroes(roleId, curVestigeId); + for(let { actorId, subHid } of heroes) { + if(usedHeroes.indexOf(actorId) != -1) return true; + // 查副将 + if(subHid) { + if(usedHeroes.indexOf(subHid) != -1) return true; + + let hasSubHero = heroes.find(hero => hero.actorId == subHid); + if(hasSubHero) return true; + } + } + return false; +} + +// 检查我的排名是否可以挑战对方的排名 +export function checkVestigeRank(myRank: number, targetRank: number) { + let dicRange = getGVGVestigeRange(myRank); + if(!dicRange) return false; + if(myRank == targetRank || targetRank == 0) return false; + + // 是否可以挑战最前的几个排名 + if(dicRange.topChallengeFrom <= targetRank && dicRange.topChallengeTo >= targetRank) return true; + if(dicRange.rangeBeforeTo == -1) { + if(dicRange.rangeBeforeFrom < targetRank && myRank > targetRank) return true; + } else { + if(dicRange.rangeBeforeFrom < targetRank && dicRange.rangeBeforeTo >= targetRank) return true; + } + if(dicRange.rangeAfterTo == -1) { + if(dicRange.rangeAfterFrom < targetRank && myRank > targetRank) return true; + } else { + if(dicRange.rangeAfterFrom < targetRank && dicRange.rangeAfterTo >= targetRank) return true; + } + + return false; +} + +export function isRobot(roleId: string) { + if(!roleId) roleId = ''; + return roleId.startsWith('robot'); +} + +export async function checkVestigeOppStatus(configId: number, groupKey: string, vestigeId: number, roleId: string, myRank: number, targetRoleId: string, rank: number) { + + let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId); + if(!myData || myData.rank != myRank) return VESTIGE_OPP_STATUS.MY_RANK_CHANGE; + + if(isRobot(targetRoleId)) { + let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank); + if(targetData) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE; + } else { + let targetData = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId); + if(targetData?.rank != rank) return VESTIGE_OPP_STATUS.OPP_RANK_CHANGE; + } + let lockResult = await GVGVestigeLockModel.chooseOppLock(groupKey, vestigeId, rank, configId, roleId, targetRoleId); + if(!lockResult) return VESTIGE_OPP_STATUS.OPP_IS_LOCKED; + + return VESTIGE_OPP_STATUS.BATTLE; +} + +// 生成防守数据 +export async function generateDefenseInfo(roleId: string, vestigeId: number, rank: number) { + if(isRobot(roleId)) { + let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank); // 调用之前已经验证过了 + let dicWar = gameData.war.get(dicRank?.warId); + let dicWarJson = gameData.warJson.get(dicWar?.dispatchJsonId); + if(!dicWarJson) return new OppPlayerInfo(); + + let heroes: OppPlayerHeroInfo[] = []; + for(let json of dicWarJson) { + if(json.relation == 2) { + let hero = new OppPlayerHeroInfo(); + hero.setByWarJson(json); + heroes.push(hero); + } + } + let info = new OppPlayerInfo(); + info.initByRobot(dicRank, heroes, true); + return info; + } else { + let playerVestigeData = await GVGVestigeRankModel.findByRole(vestigeId, roleId); + if(!playerVestigeData) return null; + let lineup = playerVestigeData.lineup||[]; + let hids = lineup.map(cur => cur.actorId); + let role = await RoleModel.findByRoleId(playerVestigeData.roleId, 'roleId roleName heads head frames frame spines spine title lv'); + let heroes = await HeroModel.findByHidRange(hids, playerVestigeData.roleId, 'hid skinId lv star colorStar quality ce'); + let league = await GVGLeagueModel.findByCode(playerVestigeData.leagueCode); + + let info = new OppPlayerInfo(); + info.initByPlayer(playerVestigeData.rank, role, league, true); + info.setPlayerHeroes(heroes, lineup, playerVestigeData.combo||[]); + return info; + } +} + +export async function generateAttackInfo(roleId: string, league: GVGLeagueType, rank: number) { + let role = await RoleModel.findByRoleId(roleId, 'roleId roleName heads head frames frame spines spine title lv'); + let info = new OppPlayerInfo(); + info.initByPlayer(rank, role, league, false); + return info; +} + +export async function generateAttackHeroInfo(lineup: { actorId: number, dataId: number, order: number, subHid: number }[], dbHeroes: HeroType[], combo: Combo[]) { + let info = new OppPlayerInfo(); + info.setPlayerHeroes(dbHeroes, lineup, combo); + return info; +} + +export async function getOppDetailData(rec: GVGVestigeRecType) { + let isRobot = rec.defenseInfo.isRobot; + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank); + let result = new OppDetailData(rec, getVestigeRecStatus(rec)); + if(!isRobot) { + const dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); + const dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); + const defenseInfo = rec.defenseInfo.heroes||[]; + const hids: number[] = []; + for(let { hid, subHid } of defenseInfo) { + hids.push(hid); + if(subHid) hids.push(subHid); + } + const heroes = await HeroModel.findByHidRange(hids, rec.defenseRoleId, 'hid lv quality star colorStar skins ce skinId'); + const artifactSeids = heroes.map(hero => hero.artifact); + const artifacts = await ArtifactModel.findbySeqIds(rec.defenseRoleId, artifactSeids); + result.setByPlayer(dicWarJson, defenseInfo, heroes, artifacts, rec.defenseInfo.combo); + let attrByHid = await getHeroesAttributes(rec.defenseRoleId); + for(let [hid, attribute] of attrByHid) { + result.setAttribute(hid, attribute.getAttributesToString()); + } + } + + return result; + +} + +// 根据记录里的时间判断当前状态 +export function getVestigeRecStatus(rec: GVGVestigeRecType) { + let { checkTime = 0, battleTime = 0, endTime = 0, cancel } = rec; + if(cancel) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) }; + if(endTime > 0 && endTime <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(endTime/1000) }; + if(battleTime > 0 && battleTime <= Date.now() && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.BATTLE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN }; + if(checkTime > 0 && checkTime <= Date.now() && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 > Date.now()) return { status: VESTIGE_STATUS.CHECK, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN }; + // 超时的 + if(battleTime > 0 && endTime == 0 && battleTime + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN }; + if(checkTime > 0 && battleTime == 0 && checkTime + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN * 1000 <= Date.now()) return { status: VESTIGE_STATUS.COMPLETE, time: Math.floor(checkTime/1000) + GVG.GVG_VESTIGE_PREPARE_COUNTDOWN }; + return { status: VESTIGE_STATUS.NO, time: 0 }; +} + +// 将开始战斗时候的阵容存到防守阵容 +export async function updateMyVestigeRank(isChange: boolean, atkData: GVGVestigeRankType, defData: GVGVestigeRankType, historyRank: number, rec: GVGVestigeRecType) { + let update: GVGVestigeRankUpdate = {}, needUpdate = false; + if(isChange) { + if(atkData && !atkData.hasDefense) { // 只有第一次挑战且自己没有主动保存过阵容的时候才会这么保存 + let heroes = rec.attackInfo.heroes||[]; + let lineup = heroes.map(hero => ({ actorId: hero.hid, dataId: hero.dataId, order: hero.order, ce: hero.ce, subHid: hero.subHid })); + update.lineup = lineup; + update.hasDefense = true; + needUpdate = true; + } + if(atkData && (historyRank == 0 || atkData.rank < historyRank)) { // 更新历史最高排名 + update.historyRank = atkData.rank; + needUpdate = true; + } + if(atkData) { // 排名变化时刷新对手 + let oppRanks = refreshVestigeOppRanks(atkData.rank); + update.oppRanks = oppRanks; + needUpdate = true; + } + } + if(needUpdate) { + atkData = await GVGVestigeRankModel.updateByRoleId(atkData.vestigeId, atkData.roleId, update); + } + if(isChange && defData) { + let oppRanks = refreshVestigeOppRanks(defData.rank); + defData = await GVGVestigeRankModel.updateByRoleId(defData.vestigeId, defData.roleId, { oppRanks }); + } + return atkData +} + +export function calBreakGoods(vestige: number, historyRank: number, rank: number) { + let dicRankMap = gameData.gvgVestige.get(vestige); + if(!dicRankMap) return { rewards: [], leagueRewards: [] }; + let rewards: RewardInter[] = [], leagueRewards: RewardInter[] = []; + for(let i = historyRank + 1; i <= rank; i++) { + let dicRank = dicRankMap.get(i); + if(!dicRank) continue; + combinePushItem(rewards, dicRank.onceReward); + combinePushItem(leagueRewards, dicRank.onceLeagueReward); + } + return { rewards, leagueRewards } +} + +// 玩家当天的驻扎记录,没有的话就创建一个 +export async function getMyVestigeRank(configId: number, groupKey: string, vestigeId: number, roleId: string, myLeague?: GVGLeagueType) { + + let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名 + if(!myVestigeRank) { + let role = await RoleModel.findByRoleId(roleId, 'roleId guildCode'); + let oppRanks = refreshVestigeOppRanks(-1); + if(!myLeague) { + myLeague = await GVGLeagueModel.findLeagueByGuild(role.guildCode); + if(!myLeague) return null + } + const { leagueCode, name } = myLeague; + myVestigeRank = await GVGVestigeRankModel.initRank(configId, vestigeId, groupKey, role, leagueCode, name, oppRanks ); + } + return myVestigeRank; +} + +// 保存排行榜 +export async function saveScoreToRank(rec: GVGVestigeRecType) { + await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.attackInfo); + await savePlayerRank(rec.configId, rec.groupKey, rec.vestigeId, rec.defenseInfo); +} + +export function getDayKeyInfo() { + return moment().format('YYMMDD'); +} + +export async function savePlayerRank(configId: number, groupKey: string, vestigeId: number, playerInfo: Partial) { + if(playerInfo.isRobot) return + let dicRankMap = gameData.gvgVestige.get(vestigeId); + let newRank = dicRankMap?.get(playerInfo.newRank)?.score||0; + let oldRank = dicRankMap?.get(playerInfo.oldRank)?.score||0; + + let nextWeek = getTimeFun().getAfterDayWithHour(7); + let myScore = await GVGVestigeSumRankModel.incScore(playerInfo.roleId, playerInfo.leagueCode, configId, groupKey, newRank - oldRank); + let r1 = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day: getDayKeyInfo() }); + await r1.setExpire(nextWeek); + await r1.setRankWithRoleInfo(playerInfo.roleId, myScore.score, myScore.updatedAt.getTime()); + let leagueScore = await GVGVestigeLeagueRankModel.incScore(configId, playerInfo.leagueCode, groupKey, newRank - oldRank); + let r2 = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day: getDayKeyInfo() }); + await r2.setExpire(nextWeek); + await r2.setRankWithLeagueInfo(playerInfo.leagueCode, leagueScore.score, leagueScore.updatedAt.getTime()); +} + +export async function getVestigeRank(redisKey: REDIS_KEY, isSimple: boolean, keyParam: KeyNameParam, myId: myIdInter, serverNames?: any) { + let r = new Rank(redisKey, keyParam); + r.setGenerFieldsFun((obj => { + if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL && obj instanceof RoleRankInfo) { + if(isSimple) { + return { rank: obj.rank, name: obj.roleName, serverName: serverNames[obj.serverId], score: obj.num } + } else { + return { ...obj, serverName: serverNames[obj.serverId], score: obj.num } + } + } + if(redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE && obj instanceof LeagueRankInfo) { + if(isSimple) { + return { rank: obj.rank, name: obj.name, score: obj.num } + } else { + return { ...obj, score: obj.num, leader: {...obj.leader, serverName: serverNames[obj.leader.serverId]}}; + } + } + return obj + })); + + let { ranks, myRank } = await r.getRankListWithMyRank(myId); + if (!myRank) { + if(redisKey == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) { + myRank = await r.generMyRankWithRole(myId.roleId, 0, 0); + } else if (redisKey == REDIS_KEY.GVG_VESTIGE_LEAGUE) { + myRank = await r.generMyRankWithLeague(myId.leagueCode, 0, 0); + } + } + return { ranks, myRank } +} + +// systimer 服 每天晚上22点 +export async function saveVestigeRankSchedule() { + let config = await GVGConfigModel.findConfig(); + let period = getPeriodByTime(config.teamTime, config.prepareTime, config.battleTime, config.scheduleTime); + if(period != GVG_PERIOD.PREPARE) return; + let day = getDayKeyInfo(); + let keys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_LEAGUE}:${day}:`); + for(let key of keys) { + let [,, groupKey] = key.split(':'); + let r = new Rank(REDIS_KEY.GVG_VESTIGE_LEAGUE, { groupKey, day}); + let ranks = await r.getRankByRangeRaw(); + await GVGVestigeLeagueRankModel.saveRank(groupKey, ranks); + await addVestigeLeagueRankRec(config.configId, groupKey, ranks); + await addVestigeRankMessage(ranks); + } + + let memberKeys = await findKeys(`${REDIS_KEY.GVG_VESTIGE_MEMBER_ALL}:${day}:`); + for(let key of memberKeys) { + let [,, groupKey] = key.split(':'); + let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, { groupKey, day}); + let ranks = await r.getRankByRangeRaw(); + await GVGVestigeSumRankModel.saveRank(groupKey, ranks); + } + let playerSumRanks = await GVGVestigeSumRankModel.findAllScores(); + let userDatas = await GVGUserDataModel.addVestigeScores(config.configId, playerSumRanks); + for(let userData of userDatas) { + await sendMessageToUserWithSuc(userData.roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode: userData.leagueCode, job: LEAGUE_JOB.FIGHTER, sumContribute: calFighterContribute(userData.contribute) }); + } +} + +// systimer 服,每周六5点 +export async function gvgBattlePeriodSchedule() { + const config = await GVGConfigModel.findConfig(); + await sendUngotVestigeReward(config.configId); +} + +export async function sendUngotVestigeReward(configId: number) { + const playerDatas = await GVGVestigeSumRankModel.getAllCanReceiveRanks(configId); + const leagueCodes: string[] = []; + const dataByLeague = new Map>(); // leagueCode => playerdata + const receiveLeagueParam: { _id: string, roleIds: string[] }[] = [], receivePlayerParam: string[] = []; + for(let player of playerDatas) { + if(leagueCodes.indexOf(player.leagueCode) == -1) { + leagueCodes.push(player.leagueCode); + } + if(!dataByLeague.has(player.leagueCode)) dataByLeague.set(player.leagueCode, new Map()); + if(!dataByLeague.get(player.leagueCode).has(player.roleId)) dataByLeague.get(player.leagueCode).set(player.roleId, { playerRanks: [], leagueRanks: [] }); + dataByLeague.get(player.leagueCode).get(player.roleId).playerRanks.push({ _id: player._id, rank: player.rank }); + + receivePlayerParam.push(player._id); + } + + const leagueDatas = await GVGVestigeLeagueRankModel.getAllCanReceiveRanks(configId, leagueCodes); + for(let leagueData of leagueDatas) { + let players = dataByLeague.get(leagueData.leagueCode); + if(!players) continue; + for(let [roleId, data] of players) { + if(leagueData.receiveMembers.indexOf(roleId) == -1) { + data.leagueRanks.push({ _id: leagueData._id, rank: leagueData.rank }); + let index = receiveLeagueParam.findIndex(cur => cur._id == leagueData._id); + if(index == -1) { + receiveLeagueParam.push({ _id: leagueData._id, roleIds: [ roleId ] }); + } else { + receiveLeagueParam[index].roleIds.push(roleId); + } + } + } + } + + for(let [ leagueCode, players ] of dataByLeague) { + for(let [ roleId, { playerRanks, leagueRanks }] of players) { + let { leagueReward, rewards } = calVestigeLeagueBoxRewards(leagueRanks, playerRanks); + if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, null, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); + if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.VESTIGE_REWARD, roleId, { params: [`${configId}`], goods: rewards }); + } + } + + await GVGVestigeSumRankModel.receiveRanks(receivePlayerParam); + await GVGVestigeLeagueRankModel.receiveManyRanks(receiveLeagueParam); +} + +export function calVestigeLeagueBoxRewards(canReceiveRanks: { rank: number }[], canReceivePlayerRanks: { rank: number }[]) { + let rewards: RewardInter[] = [], leagueReward: RewardInter[] = []; + for(let { rank } of canReceiveRanks) { + let dicRank = getGVGVestigeLeagueRank(rank); + if(!dicRank) { console.error('dic_zyz_GVGVestigeLeagueRank error'); continue; } + // console.log('###### league', rank, dicRank) + combinePushItem(rewards, dicRank.rankReward); + combinePushItem(leagueReward, dicRank.rankLeagueReward); + } + for(let { rank } of canReceivePlayerRanks) { + let dicRank = getGVGVestigePlayerRank(rank); + if(!dicRank) { console.error('dic_zyz_GVGVestigPlayerRank error'); continue; } + // console.log('###### player', rank, dicRank) + combinePushItem(rewards, dicRank.rankPlayerReward); + combinePushItem(leagueReward, dicRank.rankPlayerLeagueReward); + } + let boxPreview: { id: number, count: number, itemType: number }[] = []; + for(let { id, count } of rewards) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM }); + for(let { id, count } of leagueReward) boxPreview.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM }); + return { + leagueReward, rewards, boxPreview, canReceiveBox: canReceiveRanks.length > 0 || canReceivePlayerRanks.length > 0 + } +} + +export async function pushGvgFightIconShow(roleId: string, battleCode: string) { + const rec = await GVGVestigeRecModel.findByBattleCode(battleCode); + let result: (GVGVestigeRecUpdate & { rplFileUrl: string })[] = []; + const { attackRoleId, hasRpl, remoteUrl } = rec; + const rplFileUrl = battleCode && hasRpl ? remoteUrl : ''; + const obj = getVestigeRecStatus(rec); + if (obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl }); + let gvgFightRecs = { list: result, rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env')) }; + + await pushIconShow(roleId, false, gvgFightRecs) +} diff --git a/game-server/app/services/gvg/gvgItemService.ts b/game-server/app/services/gvg/gvgItemService.ts index 2b8d7ac07..a46d1a0b9 100644 --- a/game-server/app/services/gvg/gvgItemService.ts +++ b/game-server/app/services/gvg/gvgItemService.ts @@ -1,106 +1,106 @@ -import { GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_ITEM_REFRESH_TYPE, GVG_ITEM, PUSH_ROUTE } from "../../consts"; -import { GVGUserItemModel } from "../../db/GVGUserItem"; -import { gameData } from "../../pubUtils/data"; -import { RewardInter } from "../../pubUtils/interface"; -import { saveGVGItemChangeLog } from "../../pubUtils/logUtil"; -import { DAY_TO_SECOND, getZeroPoint, getFutureTime } from "../../pubUtils/timeUtil"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { addItems, handleCost } from "../role/rewardService"; -import { getGVGConfig } from "./gvgService"; - -/** - * 获取道具(必须在guild进程下使用) - * @param roleId - * @param roleName - * @param leagueCode - * @param sid - * @param leagueItems GVG内专用道具 - * @param items 普通道具 - * @param reason - * @returns - */ -export async function addGVGReward(roleId: string, roleName: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) { - let returnGoods: { id: number, count: number, itemType: number }[] = [], pushGoods: { id: number, count: number, expireTime: number, inc: number, reason: number }[] = []; - let { configId } = getGVGConfig(); - if(items.length > 0) { - const goods = await addItems(roleId, roleName, sid, items, reason); - for(let { id, count } of goods) { - returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM }); - } - } - for(let { id, count } of leagueItems) { - let dicItem = gameData.gvgItem.get(id); - if(!dicItem) continue; - let item = await GVGUserItemModel.increaseItem(configId, leagueCode, roleId, id, count, getExpireTime(dicItem.refreshType)); - returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM }); - pushGoods.push({ id, count: item.count, inc: count, expireTime: item.expireTime, reason }); - } - if(pushGoods.length > 0) { - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LEAGUE_ITEM_UPDATE, { items: pushGoods }, sid); - saveGVGItemChangeLog(roleId, leagueCode, pushGoods, reason); - } - return returnGoods; -} - -function getExpireTime(refreshType: number) { - if(refreshType == LEAGUE_ITEM_REFRESH_TYPE.DAILY) { - return getZeroPoint() + DAY_TO_SECOND; - } - return getFutureTime(); -} - -/** - * 消耗道具 - * @param roleId - * @param leagueCode - * @param sid - * @param leagueItems GVG内专用道具 - * @param items 普通背包道具 - * @param reason - * @returns - */ -export async function handleGVGCost(roleId: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) { - let { configId } = getGVGConfig(); - // 检查本地道具数量 - const curItems = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, leagueItems.map(cur => cur.id)); - for(let { id, count } of leagueItems) { - let curItem = curItems.find(cur => cur.id == id); - if(!curItem || curItem.count < count) { - return false; - } - } - const itemResult = await handleCost(roleId, sid, items, reason); - if(!itemResult) return false; - - const decreaseResult = await GVGUserItemModel.decreaseItem(configId, leagueCode, roleId, leagueItems); - const pushGoods = decreaseResult.map(item => { - let leagueItem = leagueItems.find(cur => cur.id == item.id); - return { id: item.id, count: item.count, expireTime: item.expireTime, inc: leagueItem?.count } - }); - if(pushGoods.length > 0) { - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LEAGUE_ITEM_UPDATE, { items: pushGoods }, sid); - saveGVGItemChangeLog(roleId, leagueCode, pushGoods, reason); - } - return true; -} - -export function getProduceCoinCnt(items: RewardInter[]) { - let produceCoinCnt = 0; - for(let { id, count } of items) { - if(id == GVG_ITEM.PRODUCE_COIN) { - produceCoinCnt = count; break; - } - } - return produceCoinCnt; -} - -export function combinePushItem(targetItems: RewardInter[], dicItems: RewardInter[]) { - for(let { id, count } of dicItems) { - let obj = targetItems.find(obj => obj.id == id); - if(!obj) { - targetItems.push({ id, count }); - } else { - obj.count += count; - } - } -} \ No newline at end of file +import { GVG_RETURN_ITEM_TYPE, ITEM_CHANGE_REASON, LEAGUE_ITEM_REFRESH_TYPE, GVG_ITEM, PUSH_ROUTE } from "@consts"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { gameData } from "@pubUtils/data"; +import { RewardInter } from "@pubUtils/interface"; +import { saveGVGItemChangeLog } from "@pubUtils/logUtil"; +import { DAY_TO_SECOND, getZeroPoint, getFutureTime } from "@pubUtils/timeUtil"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { addItems, handleCost } from "../role/rewardService"; +import { getGVGConfig } from "./gvgService"; + +/** + * 获取道具(必须在guild进程下使用) + * @param roleId + * @param roleName + * @param leagueCode + * @param sid + * @param leagueItems GVG内专用道具 + * @param items 普通道具 + * @param reason + * @returns + */ +export async function addGVGReward(roleId: string, roleName: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) { + let returnGoods: { id: number, count: number, itemType: number }[] = [], pushGoods: { id: number, count: number, expireTime: number, inc: number, reason: number }[] = []; + let { configId } = getGVGConfig(); + if(items.length > 0) { + const goods = await addItems(roleId, roleName, sid, items, reason); + for(let { id, count } of goods) { + returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.NORMAL_ITEM }); + } + } + for(let { id, count } of leagueItems) { + let dicItem = gameData.gvgItem.get(id); + if(!dicItem) continue; + let item = await GVGUserItemModel.increaseItem(configId, leagueCode, roleId, id, count, getExpireTime(dicItem.refreshType)); + returnGoods.push({ id, count, itemType: GVG_RETURN_ITEM_TYPE.GVG_ITEM }); + pushGoods.push({ id, count: item.count, inc: count, expireTime: item.expireTime, reason }); + } + if(pushGoods.length > 0) { + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LEAGUE_ITEM_UPDATE, { items: pushGoods }, sid); + saveGVGItemChangeLog(roleId, leagueCode, pushGoods, reason); + } + return returnGoods; +} + +function getExpireTime(refreshType: number) { + if(refreshType == LEAGUE_ITEM_REFRESH_TYPE.DAILY) { + return getZeroPoint() + DAY_TO_SECOND; + } + return getFutureTime(); +} + +/** + * 消耗道具 + * @param roleId + * @param leagueCode + * @param sid + * @param leagueItems GVG内专用道具 + * @param items 普通背包道具 + * @param reason + * @returns + */ +export async function handleGVGCost(roleId: string, leagueCode: string, sid: string, leagueItems: RewardInter[], items: RewardInter[], reason: ITEM_CHANGE_REASON) { + let { configId } = getGVGConfig(); + // 检查本地道具数量 + const curItems = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, leagueItems.map(cur => cur.id)); + for(let { id, count } of leagueItems) { + let curItem = curItems.find(cur => cur.id == id); + if(!curItem || curItem.count < count) { + return false; + } + } + const itemResult = await handleCost(roleId, sid, items, reason); + if(!itemResult) return false; + + const decreaseResult = await GVGUserItemModel.decreaseItem(configId, leagueCode, roleId, leagueItems); + const pushGoods = decreaseResult.map(item => { + let leagueItem = leagueItems.find(cur => cur.id == item.id); + return { id: item.id, count: item.count, expireTime: item.expireTime, inc: leagueItem?.count } + }); + if(pushGoods.length > 0) { + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.LEAGUE_ITEM_UPDATE, { items: pushGoods }, sid); + saveGVGItemChangeLog(roleId, leagueCode, pushGoods, reason); + } + return true; +} + +export function getProduceCoinCnt(items: RewardInter[]) { + let produceCoinCnt = 0; + for(let { id, count } of items) { + if(id == GVG_ITEM.PRODUCE_COIN) { + produceCoinCnt = count; break; + } + } + return produceCoinCnt; +} + +export function combinePushItem(targetItems: RewardInter[], dicItems: RewardInter[]) { + for(let { id, count } of dicItems) { + let obj = targetItems.find(obj => obj.id == id); + if(!obj) { + targetItems.push({ id, count }); + } else { + obj.count += count; + } + } +} diff --git a/game-server/app/services/gvg/gvgPrepareService.ts b/game-server/app/services/gvg/gvgPrepareService.ts index 03392d802..af591885f 100644 --- a/game-server/app/services/gvg/gvgPrepareService.ts +++ b/game-server/app/services/gvg/gvgPrepareService.ts @@ -1,539 +1,539 @@ -import { BackendSession } from "pinus"; -import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, GVG_RESOURCE_TYPE, GVG_SEED_TYPE, GVG_TECH_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE } from "../../consts"; -import { GVGLeagueFarmModel, GVGLeagueFarmType } from "../../db/GVGLeagueFarm"; -import { GVGLeaguePrepareModel, GVGLeaguePrepareType, Tech } from "../../db/GVGLeaguePrepare"; -import { GVGUserDailyDataModel, GVGUserDailyDataType } from "../../db/GVGUserDailyData"; -import { Contribute, GVGUserDataModel } from "../../db/GVGUserData"; -import { GVGUserItemModel } from "../../db/GVGUserItem"; -import { LeagueField } from "../../domain/gvgField/returnData"; -import { calLeagueLv, gameData, getFieldMaxAddType } from "../../pubUtils/data"; -import { GVG } from "../../pubUtils/dicParam"; -import { RewardInter } from "../../pubUtils/interface"; -import { nowSeconds } from "../../pubUtils/timeUtil"; -import { arrToMap, getArrayOfNumber, getRandEelm, decodeIdCntArrayStr, parseGoodStr, sortArrRandom } from "../../pubUtils/util"; -import { addGVGReward, combinePushItem, getProduceCoinCnt } from "./gvgItemService"; -import { getGVGConfig, getGVGPeriodData } from "./gvgService"; -import { GVGVestigeRankModel } from "../../db/GVGVestigeRank"; -import { addLeagueLvUpMessage, addResourceRecord } from "./gvgRecService"; -import { GVGLeagueType } from "../../db/GVGLeague"; -import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService"; -import { sendMailByContent } from "../mailService"; - -export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) { - const dicTech = gameData.gvgTech.get(techId); - if(!dicTech) return false; - - let hasOrUnlock = dicTech.prepositionId.length == 0; - for(let andArr of dicTech.prepositionId) { // or关系 - let hasAndUnlock = true; - for(let id of andArr) { // and关系 - if(!checkTechIsIng(id, activeQueue, techQueue)) { - hasAndUnlock = false; break; - } - } - if(hasAndUnlock) hasOrUnlock = true; - } - return hasOrUnlock; -} - -export function checkTechIsIng(techId: number, activeQueue: number[], techQueue: Tech[]) { - return techQueue.findIndex(cur => cur.id == techId) != -1 || activeQueue.indexOf(techId) != -1 -} - -export function checkTechProgress(techId: number, techQueue: Tech[]) { - let queue = techQueue.find(cur => cur.id == techId); - return queue && queue.progress == 0; -} - -export function calProducerContribute(obj: { food: number, mineral: number, wood: number }) { - let { food = 0, mineral = 0, wood = 0 } = obj||{}; - let ratio = decodeIdCntArrayStr(GVG.GVG_PRODUCE_GAME_RATIO, 1); - let foodRatio = ratio.get(GVG_RESOURCE_TYPE.FOOD.toString())||0; - let mineralRatio = ratio.get(GVG_RESOURCE_TYPE.MINERAL.toString())||0; - let woodRatio = ratio.get(GVG_RESOURCE_TYPE.WOOD.toString())||0; - return food * foodRatio + mineral * mineralRatio + wood * woodRatio; -} - -export function calFighterContribute(obj: { score: number }) { - return obj?.score||0 -} - -export async function getGVGActive(leagueCode: string, roleId: string) { - let { configId } = getGVGConfig(); - let result = await GVGUserDataModel.findByRole(configId, leagueCode, roleId); - return result?.active||0; -} - -/** - * 获得活跃 - * @param leagueCode - * @param roleId - * @param type GVG_ACTIVE_TYPE - * @returns - */ -export async function addGVGActive(leagueCode: string, roleId: string, type: GVG_ACTIVE_TYPE, count = 1) { - let { configId } = getGVGConfig(); - - let add = gameData.gvgActive.get(type)||0; - let result = await GVGUserDataModel.addActive(configId, leagueCode, roleId, type, add * count); - return result.active; -} - -export async function addGVGTechActive(leagueCode: string, roleId: string) { - let { configId } = getGVGConfig(); - let check = await GVGUserDailyDataModel.checkGetTechActive(configId, leagueCode, roleId); - if(!check) { - await GVGUserDailyDataModel.setHasGetTechActive(configId, leagueCode, roleId); - return await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.TECH_ACTIVATE); - } else { - const data = await GVGUserDataModel.findByRole(configId, leagueCode, roleId); - return data?.active||0; - } -} - -export function getGVGDailyItems(job: number) { - return job == LEAGUE_JOB.PRODUCER? parseGoodStr(GVG.GVG_PRODUCER_GET): parseGoodStr(GVG.GVG_FIGHTER_GET); -} - -export async function getDailyLoginReward(roleId: string, roleName: string, sid: string, leagueCode: string, job: number) { - let { configId } = getGVGConfig(); - if(job && !await GVGUserDailyDataModel.checkHasLogin(configId, leagueCode, roleId)) { - // 发每日奖励 - await GVGUserDailyDataModel.setHasLogin(configId, leagueCode, roleId); - let leagueGoods = await addGVGReward(roleId, roleName, leagueCode, sid, getGVGDailyItems(job), [], ITEM_CHANGE_REASON.GVG_LOGIN) - let active = await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.LOGIN); - return { active, reward: leagueGoods } - } - return null; -} - -export function getMyContribute(userDailyData: GVGUserDailyDataType, myRanks: {vestigeId: number, rank: number}[]) { - let score = 0; - for(let { vestigeId, rank} of myRanks) { - let dicRankMap = gameData.gvgVestige.get(vestigeId); - if(dicRankMap && dicRankMap.get(rank)) score += dicRankMap.get(rank).score; - } - return { - food: userDailyData?.food||0, - mineral: userDailyData?.mineral||0, - wood: userDailyData?.wood||0, - score: userDailyData?.score||score, - } -} - -/** - * 资源 - * @param leagueCode 联军id - * @param roleId 玩家id - * @param resourceType 资源类型 - * @param count 数量 - * @returns - */ -export async function addResource(myLeague: GVGLeagueType, roleId: string, roleName: string, resourceType: GVG_RESOURCE_TYPE, count: number, sid?: string) { - let { leagueCode } = myLeague; - let { configId } = getGVGConfig(); - let resources = getResourceCnt(resourceType, count); - if(!resources) return false; - let { food = 0, mineral = 0, wood = 0 } = resources; - - // 联军更新资源 - let league = await GVGLeaguePrepareModel.addResource(configId, leagueCode, food, mineral, wood); - let originLv = league?.lv||1; - // 联军升级 - let lv = calLeagueLv(league.resources); - league = await GVGLeaguePrepareModel.setLv(configId, leagueCode, lv); - // 个人贡献更新 - await GVGUserDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood); - // 个人今日贡献更新 - let userDailyData = await GVGUserDailyDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood); - let myRanks = await GVGVestigeRankModel.findAllByRole(roleId); - - let myContribute = getMyContribute(userDailyData, myRanks); - addResourceRecord(roleId, roleName, leagueCode, resourceType, count); - if(lv > originLv) addLeagueLvUpMessage(roleId, roleName, myLeague, lv); - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode, job: LEAGUE_JOB.PRODUCER, sumContribute: calProducerContribute(myContribute) }, sid); - - return { resources: league.resources, leagueLv: league.lv, myContribute } -} - -export function checkResourceAndLv(gvgPrepare: GVGLeaguePrepareType, type: GVG_RESOURCE_TYPE) { - if(!gvgPrepare) return true; - let { lv, resources } = gvgPrepare; - let dicGVGLeagueLv = gameData.gvgLeagueLv.get(lv); - if(!dicGVGLeagueLv) return false; - - if(type == GVG_RESOURCE_TYPE.FOOD) { - return resources.food < dicGVGLeagueLv.food; - } else if (type == GVG_RESOURCE_TYPE.MINERAL) { - return resources.mineral < dicGVGLeagueLv.mineral; - } else if (type == GVG_RESOURCE_TYPE.WOOD) { - return resources.wood < dicGVGLeagueLv.wood; - } - - return false -} - -function getResourceCnt(resourceType: GVG_RESOURCE_TYPE, count: number) { - switch(resourceType) { - case GVG_RESOURCE_TYPE.FOOD: - return { food: count }; - case GVG_RESOURCE_TYPE.MINERAL: - return { mineral: count }; - case GVG_RESOURCE_TYPE.WOOD: - return { wood: count }; - } -} - -export async function lockField(leagueCode: string, roleId: string, roleName: string, farmId: number) { - let { configId } = getGVGConfig(); - const produceCoinCnt = await getLockFieldCnt(leagueCode, roleId); - if(produceCoinCnt == 0) return - - const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId); - // 查询现有的田 - let { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField } = calCntFromFarms(farmId, leagueFarms, roleId); - if(allLands.length <= 0 || myLockField >= produceCoinCnt) return; // 田数量不足 or 已经锁过了 - - let allAdd = calAddType(myFieldCnt, myAddTypeCntMap, maxAddTypeCntMap, produceCoinCnt - myLockField); - let randLand = sortArrRandom(getRandEelm(allLands, produceCoinCnt - myLockField)); - let lands: { fieldId: number, addType: number }[] = []; - for(let fieldId of randLand) { - let addType = 0; - for(let [_addType, addCnt] of allAdd) { - if(addCnt > 0) { - addType = _addType; - allAdd.set(_addType, addCnt - 1); - break; - } - } - lands.push({ fieldId, addType }); - } - // 更新田 - let dicFarm = gameData.gvgResource.get(farmId); - await GVGLeagueFarmModel.lockFields(configId, leagueCode, farmId, dicFarm?.type, roleId, roleName, lands); - return await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId); -} - -function calCntFromFarms(farmId: number, leagueFarms: GVGLeagueFarmType[], roleId: string) { - let maxAddTypeCntMap = getFieldMaxAddType(farmId); // 加成田最大数量 - let myAddTypeCntMap = new Map(); - let myFieldCnt = 0; // 玩家已有的田有 - let myLockField = 0; // 玩家没有种只是锁住了的田 - let allLands = getArrayOfNumber(gameData.gvgResource.get(farmId)?.sum??0); // 全部可使用的田 - for(let leagueFarm of leagueFarms) { - // 加成 - for(let {addType, roleId: addTypeRoleId} of leagueFarm.addTypes) { - maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - 1); - if(addTypeRoleId == roleId) { - if(!myAddTypeCntMap.has(addType)) myAddTypeCntMap.set(addType, 0); - myAddTypeCntMap.set(addType, myAddTypeCntMap.get(addType) + 1); - } - } - if(leagueFarm.unlockTime >= nowSeconds()) { - let index = allLands.indexOf(leagueFarm.fieldId); - if(index > -1) allLands.splice(index, 1); - } - - // 玩家数据 - if(leagueFarm.lockRoleId == roleId && leagueFarm.unlockTime >= nowSeconds()) { - myFieldCnt++; - if(leagueFarm.harvestTime == 0) myLockField++; - } - } - return { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField } -} - -/** - * - * @param myFieldCnt 我已种的田的数量 - * @param myAddTypeCntMap 我已种的田的有加成的田分别的数量 - * @param maxAddTypeCntMap 联军最多可以加成田的数量 - * @param count 本次可以加的田 - * @returns - */ -function calAddType(myFieldCnt: number, myAddTypeCntMap: Map, maxAddTypeCntMap: Map, count: number) { - let result = new Map(); // 加成类型, 数量 - - for(let [addType, ratio] of gameData.gvgPlayerFieldAddType) { // 按比例加田 - let maxCnt = maxAddTypeCntMap.get(addType)||0; - if(maxCnt == 0) continue; - let needCnt = Math.floor((myFieldCnt + count) * ratio / 100); // 玩家按照比例需要的加成数量 - let cnt = myAddTypeCntMap.get(addType)||0; // 我当前的加成数量 - let resultCnt = needCnt - cnt; - if(resultCnt < 0) resultCnt = 0; - if(resultCnt > maxCnt) resultCnt = maxCnt; - maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - resultCnt); - result.set(addType, resultCnt); - } - return result; -} - -export async function rollbackUnPlantFields(cost: RewardInter[], plantResult: GVGLeagueFarmType[], session: BackendSession, leagueCode: string) { - const roleId = session.get('roleId'); - const roleName = session.get('roleName'); - const sid = session.get('sid'); - let add: RewardInter[] = []; - for(let { id, count } of cost) add.push({ id, count }); - for(let { seedType } of plantResult) { - let index = add.findIndex(({ id }) => id == getItemIdOfSeedType(seedType)); - if(index != -1) { - add[index].count --; - if(add[index].count <= 0) add.splice(index); - } - } - await addGVGReward(roleId, roleName, leagueCode, sid, add, [], ITEM_CHANGE_REASON.PLANT_ROLLBACK); - return add; -} - -// 计算实际消耗的种子 -export function getCostSeedReward(plantResult: GVGLeagueFarmType[]) { - const reward: RewardInter[] = [], leagueReward: RewardInter[] = []; - for(let { seedType } of plantResult) { - let itemId = getItemIdOfSeedType(seedType); - let dicGVGItem = gameData.gvgItem.get(itemId); - if(!dicGVGItem) continue; - for(let { id, count } of dicGVGItem.reward) { - let rewardObj = reward.find(({ id }) => id == id); - rewardObj? rewardObj.count += count: reward.push({ id, count: count }); - } - for(let { id, count } of dicGVGItem.leagueReward) { - let rewardObj = leagueReward.find(({ id }) => id == id); - rewardObj? rewardObj.count += count: leagueReward.push({ id, count: count }); - } - } - return { reward, leagueReward } -} - -export function getItemIdOfSeedType(seedType: GVG_SEED_TYPE) { - switch(seedType) { - case GVG_SEED_TYPE.WHEAT: - return GVG_ITEM.WHEAT; - case GVG_SEED_TYPE.CORN: - return GVG_ITEM.CORN; - case GVG_SEED_TYPE.RICE: - return GVG_ITEM.RICE; - } -} - -export async function getLockFieldCnt(leagueCode: string, roleId: string) { - let { configId } = getGVGConfig(); - const itemIds = [GVG_ITEM.WHEAT, GVG_ITEM.CORN, GVG_ITEM.RICE, GVG_ITEM.PRODUCE_COIN]; - const items = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, itemIds); - return items.reduce((pre, cur) => pre + cur.count, 0); -} - -export async function getmyContributeRank(leagueCode: string, members: { roleId: string }[], targetRoleId: string) { - let { configId } = getGVGConfig(); - - const roleIds = members.map(member => member.roleId); - const userDatas = await GVGUserDataModel.findByRoles(configId, leagueCode, roleIds); - userDatas.sort((a, b) => calProducerContribute(b.contribute) - calProducerContribute(a.contribute)); - for(let i = 0; i < userDatas.length; i++) { - if(userDatas[i].roleId == targetRoleId) return i + 1; - } - return 0 -} - -export async function getLeagueFarmShowResult(leagueCode: string, roleId: string, farmId: number, needField = true) { - let { configId } = getGVGConfig(); - const leagueFarms = await GVGLeagueFarmModel.findLockedByFarmId(configId, leagueCode, farmId); - if(!needField) return { farmId, count: leagueFarms.length }; - - const fields = await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId); - const result = fields.map(field => new LeagueField(field)); - return { farmId, count: leagueFarms.length, fields: result } -} - -export function calFarmOutput(seedType: number, addType: number, farmId: number, cities: number[], activeTech: number[]) { - // 种子基础产量 * ( 1 + 格子加成 + 农庄等级加成 + 战力城池加成 + 科技树加成) - let itemId = getItemIdOfSeedType(seedType); - let dicGVGItem = gameData.gvgItem.get(itemId); - let dicFarm = gameData.gvgResource.get(farmId); - if(!dicGVGItem || !dicFarm) return { output: 0, outputStr: '' }; - let { value: foodBase } = dicGVGItem; - let addRatio = seedType == addType? GVG.GVG_SP_FIELD_ADD * 100: 0; - let farmRatio = dicFarm.fieldAdd; - let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.FOOD); - let techRatio = getTechAdd(activeTech); - - return { - output: Math.floor(foodBase * (1 + (addRatio + farmRatio + cityRatio + techRatio)/100)), - outputStr: `Math.floor(${foodBase} * (1 + (${addRatio} + ${farmRatio} + ${cityRatio} + ${techRatio})/100))` - } -} - -export async function sumOutputByResults(myResultFields: GVGLeagueFarmType[]) { - let [foodSum = 0, rewardSum = new Array(), leagueRewardSum = new Array(), activeSum = 0] = []; - for(let { seedType, output: food } of myResultFields) { - let itemId = getItemIdOfSeedType(seedType); - let dicGVGItem = gameData.gvgItem.get(itemId); - if(!dicGVGItem) continue; - let { reward, leagueReward, leagueConsume } = dicGVGItem; - let produceCoin = getProduceCoinCnt(leagueConsume); - foodSum += food; - for(let { id, count } of reward) { - let rewardObj = rewardSum.find(cur => cur.id == id); - rewardObj? rewardObj.count += count: rewardSum.push({id, count}); - } - for(let { id, count } of leagueReward) { - let rewardObj = leagueRewardSum.find(cur => cur.id == id); - rewardObj? rewardObj.count += count: leagueRewardSum.push({id, count}); - } - activeSum += produceCoin; - } - return { foodSum, rewardSum, leagueRewardSum, activeSum } -} - -/** - * 计算挖矿产量 - * @param farmId 矿场id - * @param result 小游戏的结果 - * @param cities 上周占领城镇加成 - * @param activeTech 千机阁加成 - * @returns - */ -export function calMineOutput(farmId: number, result: [{ type: number, count: number }], cities: number[], activeTech: number[]) { - // =(100*1.5【中铁块单块产量倍数】*4【可挖出的中铁块数量】+100*2【大铁块单块产量倍数】*8【可挖出的大铁块数量】+100*3【特大铁块单块产量倍数】*8【可挖出的特大铁块数量】)*(1+0.5【大城产量加成】) - let dicMine = gameData.gvgResource.get(farmId); - if(!dicMine) return { output: 0, outputStr: '' }; - let output = 0, addStrArr = []; - for(let { type, count } of result) { - let dic = dicMine.mineralValue.find(cur => cur.type == type); - if(!dic) continue; - output += dic.output * count; - addStrArr.push(`${dic.output}*${count}`); - } - let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.MINERAL); - let techRatio = getTechAdd(activeTech); - return { - output: Math.floor(output * (1 + (cityRatio + techRatio)/100)), - outputStr: `Math.floor(${addStrArr.join('+')} * (1 + (${cityRatio} + ${techRatio})/100))` - } -} - -/** - * 计算木块产量 - * @param farmId 林场id - * @param result 小游戏的结果 - * @param cities 上周占领城镇加成 - * @param activeTech 千机阁加成 - * @returns - */ -export function calForestryOutput(farmId: number, result: number, cities: number[], activeTech: number[]) { - // =100*2【10级木堆木块单块基础产量倍数】*(1+0.3【城镇加成倍数】)*40【使用铁斧头最大分块】 - let dicForestry = gameData.gvgResource.get(farmId); - if(!dicForestry) return { output: 0, outputStr: '' }; - let base = dicForestry.woodOutput; - let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.WOOD); - let techRatio = getTechAdd(activeTech); - return { - output: Math.floor( base * (1 + (cityRatio + techRatio)/100) * result), - outputStr: `Math.floor(${base} * (1 + (${cityRatio} + ${techRatio})/100) * ${result})` - } - -} - -// 城池加成,多城池取最大加成 -function getCitiesAdd(cities: number[], resourceType: number) { - let outputAdd: number = 0; - for(let cityId of cities) { - let dicCity = gameData.gvgCity.get(cityId); - let dicCityAdd = gameData.gvgCityAdd.get(dicCity?.cityType); - if(!dicCity || !dicCityAdd) continue; - if(resourceType == GVG_RESOURCE_TYPE.FOOD) { - outputAdd += dicCityAdd.foodAdd; - } else if (resourceType == GVG_RESOURCE_TYPE.MINERAL) { - outputAdd += dicCityAdd.mineralAdd; - } else if (resourceType == GVG_RESOURCE_TYPE.WOOD) { - outputAdd += dicCityAdd.woodAdd; - } - } - return outputAdd; -} - -// 科技树加成 叠加 -function getTechAdd(activeTech: number[]) { - let ratio = 0; - for(let techId of activeTech) { - let dicTech = gameData.gvgTech.get(techId); - if(dicTech.type == GVG_TECH_TYPE.PRODUCE_UP) { - ratio += dicTech.param[0]; - } - } - return ratio; -} - -// 锁定 -export async function lockMineOrForestry(leagueCode: string, roleId: string, farmId: number, itemId: number) { - let { configId } = getGVGConfig(); - const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId); - // 查询现有的田 - let fieldId = getUnlockedMine(farmId, leagueFarms); - if(!fieldId) return null; - - let dicFarm = gameData.gvgResource.get(farmId); - - let lockResult = await GVGLeagueFarmModel.lockMineOrForestry(configId, leagueCode, farmId, dicFarm?.type, roleId, fieldId, itemId); - if(!lockResult) return null; - - return lockResult; -} - -function getUnlockedMine(farmId: number, leagueFarms: GVGLeagueFarmType[]) { - let leagueFarmMap = arrToMap(leagueFarms, obj => obj.fieldId); - let fieldId = 0; - let sum = gameData.gvgResource.get(farmId)?.sum??0; - for(let i = 1; i <= sum; i++) { - if(!leagueFarmMap.has(i)) { - fieldId = i; break; - } - } - return fieldId; -} - -export function checkItemCanUserInFarm(farmId: number, itemId: number) { - let dicFarm = gameData.gvgResource.get(farmId); - let dicGVGItem = gameData.gvgItem.get(itemId); - if(!dicFarm || !dicGVGItem) return false; - return dicFarm.type == dicGVGItem.type; -} - -// 推送千机阁状态变化 -export async function pushTechChange(guildCodes: string[], isActive: boolean, id: number, progress: number, maxProgress: number) { - for(let guildCode of guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_CHANGE, { - id, progress, maxProgress, isActive - }); - } -} - -export async function pushTechRollback(guildCodes: string[], ids: number[]) { - for(let guildCode of guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_ROLLBACK, { - ids - }); - } -} - -export async function sendUngotBoxReward(configId: number, leagueCode: string, roleId: string, sid: string) { - let { period } = getGVGPeriodData(); - if(period != GVG_PERIOD.BATTLE) return; - let userData = await GVGUserDataModel.checkBox(configId, leagueCode, roleId); - if(userData) { - let { contribute = new Contribute(), box = [] } = userData||{}; - - let rewards: RewardInter[] = [], leagueReward: RewardInter[] = [], receiveBoxes: number[] = []; - for(let [boxId, dicBox] of gameData.gvgContributeBox) { - if(box.indexOf(boxId) != -1) continue; - let sumContribute = dicBox.job == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); - if(sumContribute < dicBox.boxPoint) continue; - receiveBoxes.push(boxId); - combinePushItem(rewards, dicBox.boxReward); - combinePushItem(leagueReward, dicBox.boxLeagueReward); - } - if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, sid, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); - if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.GVG_BOX_REWARD, roleId, { params: [`${configId}`, receiveBoxes.join()], goods: rewards }); - - await GVGUserDataModel.receiveBoxes(configId, leagueCode, roleId, receiveBoxes); - } -} +import { BackendSession } from "pinus"; +import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, GVG_RESOURCE_TYPE, GVG_SEED_TYPE, GVG_TECH_TYPE, ITEM_CHANGE_REASON, LEAGUE_JOB, MAIL_TYPE, PUSH_ROUTE } from "@consts"; +import { GVGLeagueFarmModel, GVGLeagueFarmType } from "@db/GVGLeagueFarm"; +import { GVGLeaguePrepareModel, GVGLeaguePrepareType, Tech } from "@db/GVGLeaguePrepare"; +import { GVGUserDailyDataModel, GVGUserDailyDataType } from "@db/GVGUserDailyData"; +import { Contribute, GVGUserDataModel } from "@db/GVGUserData"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { LeagueField } from "@domain/gvgField/returnData"; +import { calLeagueLv, gameData, getFieldMaxAddType } from "@pubUtils/data"; +import { GVG } from "@pubUtils/dicParam"; +import { RewardInter } from "@pubUtils/interface"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { arrToMap, getArrayOfNumber, getRandEelm, decodeIdCntArrayStr, parseGoodStr, sortArrRandom } from "@pubUtils/util"; +import { addGVGReward, combinePushItem, getProduceCoinCnt } from "./gvgItemService"; +import { getGVGConfig, getGVGPeriodData } from "./gvgService"; +import { GVGVestigeRankModel } from "@db/GVGVestigeRank"; +import { addLeagueLvUpMessage, addResourceRecord } from "./gvgRecService"; +import { GVGLeagueType } from "@db/GVGLeague"; +import { sendMessageToGuildWithSuc, sendMessageToUserWithSuc } from "../pushService"; +import { sendMailByContent } from "../mailService"; + +export function checkPreTech(techId: number, activeQueue: number[], techQueue: Tech[]) { + const dicTech = gameData.gvgTech.get(techId); + if(!dicTech) return false; + + let hasOrUnlock = dicTech.prepositionId.length == 0; + for(let andArr of dicTech.prepositionId) { // or关系 + let hasAndUnlock = true; + for(let id of andArr) { // and关系 + if(!checkTechIsIng(id, activeQueue, techQueue)) { + hasAndUnlock = false; break; + } + } + if(hasAndUnlock) hasOrUnlock = true; + } + return hasOrUnlock; +} + +export function checkTechIsIng(techId: number, activeQueue: number[], techQueue: Tech[]) { + return techQueue.findIndex(cur => cur.id == techId) != -1 || activeQueue.indexOf(techId) != -1 +} + +export function checkTechProgress(techId: number, techQueue: Tech[]) { + let queue = techQueue.find(cur => cur.id == techId); + return queue && queue.progress == 0; +} + +export function calProducerContribute(obj: { food: number, mineral: number, wood: number }) { + let { food = 0, mineral = 0, wood = 0 } = obj||{}; + let ratio = decodeIdCntArrayStr(GVG.GVG_PRODUCE_GAME_RATIO, 1); + let foodRatio = ratio.get(GVG_RESOURCE_TYPE.FOOD.toString())||0; + let mineralRatio = ratio.get(GVG_RESOURCE_TYPE.MINERAL.toString())||0; + let woodRatio = ratio.get(GVG_RESOURCE_TYPE.WOOD.toString())||0; + return food * foodRatio + mineral * mineralRatio + wood * woodRatio; +} + +export function calFighterContribute(obj: { score: number }) { + return obj?.score||0 +} + +export async function getGVGActive(leagueCode: string, roleId: string) { + let { configId } = getGVGConfig(); + let result = await GVGUserDataModel.findByRole(configId, leagueCode, roleId); + return result?.active||0; +} + +/** + * 获得活跃 + * @param leagueCode + * @param roleId + * @param type GVG_ACTIVE_TYPE + * @returns + */ +export async function addGVGActive(leagueCode: string, roleId: string, type: GVG_ACTIVE_TYPE, count = 1) { + let { configId } = getGVGConfig(); + + let add = gameData.gvgActive.get(type)||0; + let result = await GVGUserDataModel.addActive(configId, leagueCode, roleId, type, add * count); + return result.active; +} + +export async function addGVGTechActive(leagueCode: string, roleId: string) { + let { configId } = getGVGConfig(); + let check = await GVGUserDailyDataModel.checkGetTechActive(configId, leagueCode, roleId); + if(!check) { + await GVGUserDailyDataModel.setHasGetTechActive(configId, leagueCode, roleId); + return await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.TECH_ACTIVATE); + } else { + const data = await GVGUserDataModel.findByRole(configId, leagueCode, roleId); + return data?.active||0; + } +} + +export function getGVGDailyItems(job: number) { + return job == LEAGUE_JOB.PRODUCER? parseGoodStr(GVG.GVG_PRODUCER_GET): parseGoodStr(GVG.GVG_FIGHTER_GET); +} + +export async function getDailyLoginReward(roleId: string, roleName: string, sid: string, leagueCode: string, job: number) { + let { configId } = getGVGConfig(); + if(job && !await GVGUserDailyDataModel.checkHasLogin(configId, leagueCode, roleId)) { + // 发每日奖励 + await GVGUserDailyDataModel.setHasLogin(configId, leagueCode, roleId); + let leagueGoods = await addGVGReward(roleId, roleName, leagueCode, sid, getGVGDailyItems(job), [], ITEM_CHANGE_REASON.GVG_LOGIN) + let active = await addGVGActive(leagueCode, roleId, GVG_ACTIVE_TYPE.LOGIN); + return { active, reward: leagueGoods } + } + return null; +} + +export function getMyContribute(userDailyData: GVGUserDailyDataType, myRanks: {vestigeId: number, rank: number}[]) { + let score = 0; + for(let { vestigeId, rank} of myRanks) { + let dicRankMap = gameData.gvgVestige.get(vestigeId); + if(dicRankMap && dicRankMap.get(rank)) score += dicRankMap.get(rank).score; + } + return { + food: userDailyData?.food||0, + mineral: userDailyData?.mineral||0, + wood: userDailyData?.wood||0, + score: userDailyData?.score||score, + } +} + +/** + * 资源 + * @param leagueCode 联军id + * @param roleId 玩家id + * @param resourceType 资源类型 + * @param count 数量 + * @returns + */ +export async function addResource(myLeague: GVGLeagueType, roleId: string, roleName: string, resourceType: GVG_RESOURCE_TYPE, count: number, sid?: string) { + let { leagueCode } = myLeague; + let { configId } = getGVGConfig(); + let resources = getResourceCnt(resourceType, count); + if(!resources) return false; + let { food = 0, mineral = 0, wood = 0 } = resources; + + // 联军更新资源 + let league = await GVGLeaguePrepareModel.addResource(configId, leagueCode, food, mineral, wood); + let originLv = league?.lv||1; + // 联军升级 + let lv = calLeagueLv(league.resources); + league = await GVGLeaguePrepareModel.setLv(configId, leagueCode, lv); + // 个人贡献更新 + await GVGUserDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood); + // 个人今日贡献更新 + let userDailyData = await GVGUserDailyDataModel.addResource(configId, leagueCode, roleId, food, mineral, wood); + let myRanks = await GVGVestigeRankModel.findAllByRole(roleId); + + let myContribute = getMyContribute(userDailyData, myRanks); + addResourceRecord(roleId, roleName, leagueCode, resourceType, count); + if(lv > originLv) addLeagueLvUpMessage(roleId, roleName, myLeague, lv); + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_CONTRIBUTE_UPDATE, { leagueCode, job: LEAGUE_JOB.PRODUCER, sumContribute: calProducerContribute(myContribute) }, sid); + + return { resources: league.resources, leagueLv: league.lv, myContribute } +} + +export function checkResourceAndLv(gvgPrepare: GVGLeaguePrepareType, type: GVG_RESOURCE_TYPE) { + if(!gvgPrepare) return true; + let { lv, resources } = gvgPrepare; + let dicGVGLeagueLv = gameData.gvgLeagueLv.get(lv); + if(!dicGVGLeagueLv) return false; + + if(type == GVG_RESOURCE_TYPE.FOOD) { + return resources.food < dicGVGLeagueLv.food; + } else if (type == GVG_RESOURCE_TYPE.MINERAL) { + return resources.mineral < dicGVGLeagueLv.mineral; + } else if (type == GVG_RESOURCE_TYPE.WOOD) { + return resources.wood < dicGVGLeagueLv.wood; + } + + return false +} + +function getResourceCnt(resourceType: GVG_RESOURCE_TYPE, count: number) { + switch(resourceType) { + case GVG_RESOURCE_TYPE.FOOD: + return { food: count }; + case GVG_RESOURCE_TYPE.MINERAL: + return { mineral: count }; + case GVG_RESOURCE_TYPE.WOOD: + return { wood: count }; + } +} + +export async function lockField(leagueCode: string, roleId: string, roleName: string, farmId: number) { + let { configId } = getGVGConfig(); + const produceCoinCnt = await getLockFieldCnt(leagueCode, roleId); + if(produceCoinCnt == 0) return + + const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId); + // 查询现有的田 + let { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField } = calCntFromFarms(farmId, leagueFarms, roleId); + if(allLands.length <= 0 || myLockField >= produceCoinCnt) return; // 田数量不足 or 已经锁过了 + + let allAdd = calAddType(myFieldCnt, myAddTypeCntMap, maxAddTypeCntMap, produceCoinCnt - myLockField); + let randLand = sortArrRandom(getRandEelm(allLands, produceCoinCnt - myLockField)); + let lands: { fieldId: number, addType: number }[] = []; + for(let fieldId of randLand) { + let addType = 0; + for(let [_addType, addCnt] of allAdd) { + if(addCnt > 0) { + addType = _addType; + allAdd.set(_addType, addCnt - 1); + break; + } + } + lands.push({ fieldId, addType }); + } + // 更新田 + let dicFarm = gameData.gvgResource.get(farmId); + await GVGLeagueFarmModel.lockFields(configId, leagueCode, farmId, dicFarm?.type, roleId, roleName, lands); + return await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId); +} + +function calCntFromFarms(farmId: number, leagueFarms: GVGLeagueFarmType[], roleId: string) { + let maxAddTypeCntMap = getFieldMaxAddType(farmId); // 加成田最大数量 + let myAddTypeCntMap = new Map(); + let myFieldCnt = 0; // 玩家已有的田有 + let myLockField = 0; // 玩家没有种只是锁住了的田 + let allLands = getArrayOfNumber(gameData.gvgResource.get(farmId)?.sum??0); // 全部可使用的田 + for(let leagueFarm of leagueFarms) { + // 加成 + for(let {addType, roleId: addTypeRoleId} of leagueFarm.addTypes) { + maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - 1); + if(addTypeRoleId == roleId) { + if(!myAddTypeCntMap.has(addType)) myAddTypeCntMap.set(addType, 0); + myAddTypeCntMap.set(addType, myAddTypeCntMap.get(addType) + 1); + } + } + if(leagueFarm.unlockTime >= nowSeconds()) { + let index = allLands.indexOf(leagueFarm.fieldId); + if(index > -1) allLands.splice(index, 1); + } + + // 玩家数据 + if(leagueFarm.lockRoleId == roleId && leagueFarm.unlockTime >= nowSeconds()) { + myFieldCnt++; + if(leagueFarm.harvestTime == 0) myLockField++; + } + } + return { maxAddTypeCntMap, myAddTypeCntMap, allLands, myFieldCnt, myLockField } +} + +/** + * + * @param myFieldCnt 我已种的田的数量 + * @param myAddTypeCntMap 我已种的田的有加成的田分别的数量 + * @param maxAddTypeCntMap 联军最多可以加成田的数量 + * @param count 本次可以加的田 + * @returns + */ +function calAddType(myFieldCnt: number, myAddTypeCntMap: Map, maxAddTypeCntMap: Map, count: number) { + let result = new Map(); // 加成类型, 数量 + + for(let [addType, ratio] of gameData.gvgPlayerFieldAddType) { // 按比例加田 + let maxCnt = maxAddTypeCntMap.get(addType)||0; + if(maxCnt == 0) continue; + let needCnt = Math.floor((myFieldCnt + count) * ratio / 100); // 玩家按照比例需要的加成数量 + let cnt = myAddTypeCntMap.get(addType)||0; // 我当前的加成数量 + let resultCnt = needCnt - cnt; + if(resultCnt < 0) resultCnt = 0; + if(resultCnt > maxCnt) resultCnt = maxCnt; + maxAddTypeCntMap.set(addType, maxAddTypeCntMap.get(addType) - resultCnt); + result.set(addType, resultCnt); + } + return result; +} + +export async function rollbackUnPlantFields(cost: RewardInter[], plantResult: GVGLeagueFarmType[], session: BackendSession, leagueCode: string) { + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + let add: RewardInter[] = []; + for(let { id, count } of cost) add.push({ id, count }); + for(let { seedType } of plantResult) { + let index = add.findIndex(({ id }) => id == getItemIdOfSeedType(seedType)); + if(index != -1) { + add[index].count --; + if(add[index].count <= 0) add.splice(index); + } + } + await addGVGReward(roleId, roleName, leagueCode, sid, add, [], ITEM_CHANGE_REASON.PLANT_ROLLBACK); + return add; +} + +// 计算实际消耗的种子 +export function getCostSeedReward(plantResult: GVGLeagueFarmType[]) { + const reward: RewardInter[] = [], leagueReward: RewardInter[] = []; + for(let { seedType } of plantResult) { + let itemId = getItemIdOfSeedType(seedType); + let dicGVGItem = gameData.gvgItem.get(itemId); + if(!dicGVGItem) continue; + for(let { id, count } of dicGVGItem.reward) { + let rewardObj = reward.find(({ id }) => id == id); + rewardObj? rewardObj.count += count: reward.push({ id, count: count }); + } + for(let { id, count } of dicGVGItem.leagueReward) { + let rewardObj = leagueReward.find(({ id }) => id == id); + rewardObj? rewardObj.count += count: leagueReward.push({ id, count: count }); + } + } + return { reward, leagueReward } +} + +export function getItemIdOfSeedType(seedType: GVG_SEED_TYPE) { + switch(seedType) { + case GVG_SEED_TYPE.WHEAT: + return GVG_ITEM.WHEAT; + case GVG_SEED_TYPE.CORN: + return GVG_ITEM.CORN; + case GVG_SEED_TYPE.RICE: + return GVG_ITEM.RICE; + } +} + +export async function getLockFieldCnt(leagueCode: string, roleId: string) { + let { configId } = getGVGConfig(); + const itemIds = [GVG_ITEM.WHEAT, GVG_ITEM.CORN, GVG_ITEM.RICE, GVG_ITEM.PRODUCE_COIN]; + const items = await GVGUserItemModel.findByRoleAndIds(configId, leagueCode, roleId, itemIds); + return items.reduce((pre, cur) => pre + cur.count, 0); +} + +export async function getmyContributeRank(leagueCode: string, members: { roleId: string }[], targetRoleId: string) { + let { configId } = getGVGConfig(); + + const roleIds = members.map(member => member.roleId); + const userDatas = await GVGUserDataModel.findByRoles(configId, leagueCode, roleIds); + userDatas.sort((a, b) => calProducerContribute(b.contribute) - calProducerContribute(a.contribute)); + for(let i = 0; i < userDatas.length; i++) { + if(userDatas[i].roleId == targetRoleId) return i + 1; + } + return 0 +} + +export async function getLeagueFarmShowResult(leagueCode: string, roleId: string, farmId: number, needField = true) { + let { configId } = getGVGConfig(); + const leagueFarms = await GVGLeagueFarmModel.findLockedByFarmId(configId, leagueCode, farmId); + if(!needField) return { farmId, count: leagueFarms.length }; + + const fields = await GVGLeagueFarmModel.findByFarmIdAndRoleId(configId, leagueCode, farmId, roleId); + const result = fields.map(field => new LeagueField(field)); + return { farmId, count: leagueFarms.length, fields: result } +} + +export function calFarmOutput(seedType: number, addType: number, farmId: number, cities: number[], activeTech: number[]) { + // 种子基础产量 * ( 1 + 格子加成 + 农庄等级加成 + 战力城池加成 + 科技树加成) + let itemId = getItemIdOfSeedType(seedType); + let dicGVGItem = gameData.gvgItem.get(itemId); + let dicFarm = gameData.gvgResource.get(farmId); + if(!dicGVGItem || !dicFarm) return { output: 0, outputStr: '' }; + let { value: foodBase } = dicGVGItem; + let addRatio = seedType == addType? GVG.GVG_SP_FIELD_ADD * 100: 0; + let farmRatio = dicFarm.fieldAdd; + let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.FOOD); + let techRatio = getTechAdd(activeTech); + + return { + output: Math.floor(foodBase * (1 + (addRatio + farmRatio + cityRatio + techRatio)/100)), + outputStr: `Math.floor(${foodBase} * (1 + (${addRatio} + ${farmRatio} + ${cityRatio} + ${techRatio})/100))` + } +} + +export async function sumOutputByResults(myResultFields: GVGLeagueFarmType[]) { + let [foodSum = 0, rewardSum = new Array(), leagueRewardSum = new Array(), activeSum = 0] = []; + for(let { seedType, output: food } of myResultFields) { + let itemId = getItemIdOfSeedType(seedType); + let dicGVGItem = gameData.gvgItem.get(itemId); + if(!dicGVGItem) continue; + let { reward, leagueReward, leagueConsume } = dicGVGItem; + let produceCoin = getProduceCoinCnt(leagueConsume); + foodSum += food; + for(let { id, count } of reward) { + let rewardObj = rewardSum.find(cur => cur.id == id); + rewardObj? rewardObj.count += count: rewardSum.push({id, count}); + } + for(let { id, count } of leagueReward) { + let rewardObj = leagueRewardSum.find(cur => cur.id == id); + rewardObj? rewardObj.count += count: leagueRewardSum.push({id, count}); + } + activeSum += produceCoin; + } + return { foodSum, rewardSum, leagueRewardSum, activeSum } +} + +/** + * 计算挖矿产量 + * @param farmId 矿场id + * @param result 小游戏的结果 + * @param cities 上周占领城镇加成 + * @param activeTech 千机阁加成 + * @returns + */ +export function calMineOutput(farmId: number, result: [{ type: number, count: number }], cities: number[], activeTech: number[]) { + // =(100*1.5【中铁块单块产量倍数】*4【可挖出的中铁块数量】+100*2【大铁块单块产量倍数】*8【可挖出的大铁块数量】+100*3【特大铁块单块产量倍数】*8【可挖出的特大铁块数量】)*(1+0.5【大城产量加成】) + let dicMine = gameData.gvgResource.get(farmId); + if(!dicMine) return { output: 0, outputStr: '' }; + let output = 0, addStrArr = []; + for(let { type, count } of result) { + let dic = dicMine.mineralValue.find(cur => cur.type == type); + if(!dic) continue; + output += dic.output * count; + addStrArr.push(`${dic.output}*${count}`); + } + let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.MINERAL); + let techRatio = getTechAdd(activeTech); + return { + output: Math.floor(output * (1 + (cityRatio + techRatio)/100)), + outputStr: `Math.floor(${addStrArr.join('+')} * (1 + (${cityRatio} + ${techRatio})/100))` + } +} + +/** + * 计算木块产量 + * @param farmId 林场id + * @param result 小游戏的结果 + * @param cities 上周占领城镇加成 + * @param activeTech 千机阁加成 + * @returns + */ +export function calForestryOutput(farmId: number, result: number, cities: number[], activeTech: number[]) { + // =100*2【10级木堆木块单块基础产量倍数】*(1+0.3【城镇加成倍数】)*40【使用铁斧头最大分块】 + let dicForestry = gameData.gvgResource.get(farmId); + if(!dicForestry) return { output: 0, outputStr: '' }; + let base = dicForestry.woodOutput; + let cityRatio = getCitiesAdd(cities, GVG_RESOURCE_TYPE.WOOD); + let techRatio = getTechAdd(activeTech); + return { + output: Math.floor( base * (1 + (cityRatio + techRatio)/100) * result), + outputStr: `Math.floor(${base} * (1 + (${cityRatio} + ${techRatio})/100) * ${result})` + } + +} + +// 城池加成,多城池取最大加成 +function getCitiesAdd(cities: number[], resourceType: number) { + let outputAdd: number = 0; + for(let cityId of cities) { + let dicCity = gameData.gvgCity.get(cityId); + let dicCityAdd = gameData.gvgCityAdd.get(dicCity?.cityType); + if(!dicCity || !dicCityAdd) continue; + if(resourceType == GVG_RESOURCE_TYPE.FOOD) { + outputAdd += dicCityAdd.foodAdd; + } else if (resourceType == GVG_RESOURCE_TYPE.MINERAL) { + outputAdd += dicCityAdd.mineralAdd; + } else if (resourceType == GVG_RESOURCE_TYPE.WOOD) { + outputAdd += dicCityAdd.woodAdd; + } + } + return outputAdd; +} + +// 科技树加成 叠加 +function getTechAdd(activeTech: number[]) { + let ratio = 0; + for(let techId of activeTech) { + let dicTech = gameData.gvgTech.get(techId); + if(dicTech.type == GVG_TECH_TYPE.PRODUCE_UP) { + ratio += dicTech.param[0]; + } + } + return ratio; +} + +// 锁定 +export async function lockMineOrForestry(leagueCode: string, roleId: string, farmId: number, itemId: number) { + let { configId } = getGVGConfig(); + const leagueFarms = await GVGLeagueFarmModel.findByFarmId(configId, leagueCode, farmId); + // 查询现有的田 + let fieldId = getUnlockedMine(farmId, leagueFarms); + if(!fieldId) return null; + + let dicFarm = gameData.gvgResource.get(farmId); + + let lockResult = await GVGLeagueFarmModel.lockMineOrForestry(configId, leagueCode, farmId, dicFarm?.type, roleId, fieldId, itemId); + if(!lockResult) return null; + + return lockResult; +} + +function getUnlockedMine(farmId: number, leagueFarms: GVGLeagueFarmType[]) { + let leagueFarmMap = arrToMap(leagueFarms, obj => obj.fieldId); + let fieldId = 0; + let sum = gameData.gvgResource.get(farmId)?.sum??0; + for(let i = 1; i <= sum; i++) { + if(!leagueFarmMap.has(i)) { + fieldId = i; break; + } + } + return fieldId; +} + +export function checkItemCanUserInFarm(farmId: number, itemId: number) { + let dicFarm = gameData.gvgResource.get(farmId); + let dicGVGItem = gameData.gvgItem.get(itemId); + if(!dicFarm || !dicGVGItem) return false; + return dicFarm.type == dicGVGItem.type; +} + +// 推送千机阁状态变化 +export async function pushTechChange(guildCodes: string[], isActive: boolean, id: number, progress: number, maxProgress: number) { + for(let guildCode of guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_CHANGE, { + id, progress, maxProgress, isActive + }); + } +} + +export async function pushTechRollback(guildCodes: string[], ids: number[]) { + for(let guildCode of guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_TECH_ROLLBACK, { + ids + }); + } +} + +export async function sendUngotBoxReward(configId: number, leagueCode: string, roleId: string, sid: string) { + let { period } = getGVGPeriodData(); + if(period != GVG_PERIOD.BATTLE) return; + let userData = await GVGUserDataModel.checkBox(configId, leagueCode, roleId); + if(userData) { + let { contribute = new Contribute(), box = [] } = userData||{}; + + let rewards: RewardInter[] = [], leagueReward: RewardInter[] = [], receiveBoxes: number[] = []; + for(let [boxId, dicBox] of gameData.gvgContributeBox) { + if(box.indexOf(boxId) != -1) continue; + let sumContribute = dicBox.job == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); + if(sumContribute < dicBox.boxPoint) continue; + receiveBoxes.push(boxId); + combinePushItem(rewards, dicBox.boxReward); + combinePushItem(leagueReward, dicBox.boxLeagueReward); + } + if(leagueReward.length > 0) await addGVGReward(roleId, '', leagueCode, sid, leagueReward, [], ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK); + if(rewards.length > 0) await sendMailByContent(MAIL_TYPE.GVG_BOX_REWARD, roleId, { params: [`${configId}`, receiveBoxes.join()], goods: rewards }); + + await GVGUserDataModel.receiveBoxes(configId, leagueCode, roleId, receiveBoxes); + } +} diff --git a/game-server/app/services/gvg/gvgRecService.ts b/game-server/app/services/gvg/gvgRecService.ts index f6b48968e..e530c387b 100644 --- a/game-server/app/services/gvg/gvgRecService.ts +++ b/game-server/app/services/gvg/gvgRecService.ts @@ -1,205 +1,205 @@ - -// 动态 -import { CHANNEL_PREFIX, GVG_REC_ID, GVG_REC_TYPE, GVG_RESOURCE_TYPE, MSG_SOURCE, MSG_TYPE, PUSH_ROUTE } from "../../consts"; -import { GVGBattleRecType } from "../../db/GVGBattleRec"; -import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague"; -import { GVGRecModel, GVGRecUpdate } from "../../db/GVGRec"; -import { GVGVestigeRecType } from "../../db/GVGVestigeRec"; -import { gameData } from "../../pubUtils/data"; -import { nowSeconds } from "../../pubUtils/timeUtil"; -import { createGroupMsg, pushGroupMsgToRoom } from "../chatService"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { getGVGConfig } from "./gvgService"; - -// 加入军团 -export async function guildJoinLeagueRecord(leagueCode: string, guildName: string) { - await leagueJoinOrQuitGuild(leagueCode, guildName, GVG_REC_ID.LEAGUE_JOIN_GUILD); -} - -// 退出军团 -export async function guildQuitLeagueRecord(leagueCode: string, guildName: string) { - await leagueJoinOrQuitGuild(leagueCode, guildName, GVG_REC_ID.LEAGUE_QUIT_GUILD); -} - -async function leagueJoinOrQuitGuild(leagueCode: string, guildName: string, recId: GVG_REC_ID.LEAGUE_JOIN_GUILD|GVG_REC_ID.LEAGUE_QUIT_GUILD) { - let { configId } = getGVGConfig(); - let params = [guildName]; - await GVGRecModel.addRec({ leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId, createTime: nowSeconds(), params }) -} - -export async function addLeagueRenameRecord(leagueCode: string, leagueName: string) { - let { configId } = getGVGConfig(); - let params = [leagueName]; - await GVGRecModel.addRec({ leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.LEAGUE_RENAME, createTime: nowSeconds(), params }) -} - -// 获得资源 -export async function addResourceRecord(roleId: string, roleName: string, leagueCode: string, resourceType: GVG_RESOURCE_TYPE, output: number) { - let { configId } = getGVGConfig(); - let params = [roleName, getResourceNameByType(resourceType), `${output}`]; - await GVGRecModel.addRec({ roleId, leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.ADD_RESOURCE, createTime: nowSeconds(), params }) -} - -function getResourceNameByType(resourceType: GVG_RESOURCE_TYPE) { - switch(resourceType) { - case GVG_RESOURCE_TYPE.FOOD: return '粮食'; - case GVG_RESOURCE_TYPE.MINERAL: return '矿物'; - case GVG_RESOURCE_TYPE.WOOD: return '木堆'; - } -} - -export async function addVestigeBattleEndRec(rec: GVGVestigeRecType) { - if(!rec) return; - let { configId, vestigeId, groupKey } = rec; - let vestigeName = gameData.gvgVestigeName.get(vestigeId); - if(rec.defenseInfo && rec.defenseInfo.isRobot) { // 对手是机器人,驻扎动态 - let { roleId, roleName, leagueCode, newRank, isSuccess } = rec.attackInfo; - if(isSuccess) { - let params = [ roleName, vestigeName, `第${newRank}名`]; - await GVGRecModel.addRec({ roleId, leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.SETTLE_POINT, createTime: nowSeconds(), params }); - } - } - if(rec.defenseInfo && !rec.defenseInfo.isRobot && rec.attackInfo.leagueCode != rec.defenseInfo.leagueCode) { - let { leagueName, newRank, isSuccess } = rec.attackInfo; - let { roleId, leagueCode, roleName } = rec.defenseInfo; - if(isSuccess) { - let params = [ roleName, vestigeName, `第${newRank}名`, leagueName]; - await GVGRecModel.addRec({ roleId, leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.POINT_BE_GRAB, createTime: nowSeconds(), params }); - } - } -} - -export async function addVestigeLeagueRankRec(configId: number, groupKey: string, ranks: { rank: number, field: string }[]) { - await GVGRecModel.addRecs(ranks.map(({ rank, field: leagueCode }) => { - let params = [ `第${rank}名`]; - return { leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.VESTIGE_RANK, createTime: nowSeconds(), params }; - })); -} - -export async function addBattleEndRec(rec: GVGBattleRecType) { - let { isSuccess, attackTeamAfter: attackTeam, defenseTeamAfter: defenseTeam, configId, groupKey } = rec; - let { roleId: defenseRoleId, leagueCode: defenseLeague, cityId, index: defenseIndex, curTeamBreak: defenseBreak, originPointId: defenseOriginPoint, roleName: defenseName } = defenseTeam; - let { roleId: attackRoleId, leagueCode: attackLeague, index: attackIndex, roleName: attackName} = attackTeam; - - let params = new GVGRecUpArr(configId, cityId, groupKey, nowSeconds()); - if(isSuccess) { - if(!defenseTeam.isRobot) params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_BE_ATTACKED_FAIL, [attackName, `队伍${defenseIndex}`]); - params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_ATTACK_SUCCESS, [`队伍${attackIndex}`, defenseName]); - if(defenseBreak && defenseOriginPoint > 0 ) { - if(!defenseTeam.isRobot) { - params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_LOST_POINT, [attackName, `队伍${defenseIndex}`, getPointName(defenseOriginPoint)]); - } - params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_GET_POINT, [`队伍${attackIndex}`, defenseName, getPointName(defenseOriginPoint)]); - } - } else { - if(!defenseTeam.isRobot) params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_BE_ATTACKED_SUCCESS, [attackName, `队伍${defenseIndex}`]); - params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_ATTACK_FAIL, [`队伍${attackIndex}`, defenseName]); - } - - await GVGRecModel.addRecs(params.getUpdateParam()); - let mapByRoleId = params.getMapByRoleId(); - for(let [roleId, recs] of mapByRoleId) { - if(recs.length > 0) sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_REC_ADD, { recs }); - } -} - -class GVGRecUpArr { - private arr: GVGRecUpdate[] = []; - private configId: number; - private cityId: number; - private groupKey: string; - private createTime: number; - - constructor(configId: number, cityId: number, groupKey: string, createTime: number) { - this.configId = configId; - this.cityId = cityId; - this.groupKey = groupKey; - this.createTime = createTime; - } - - public pushRec(roleId: string, leagueCode: string, type: GVG_REC_TYPE, recId: GVG_REC_ID, params: string[]) { - this.arr.push({ - configId: this.configId, cityId: this.cityId, groupKey: this.groupKey, createTime: this.createTime, - roleId, leagueCode, type, recId, params - }) - } - - public getUpdateParam() { - return this.arr; - } - - public getMapByRoleId() { - let map = new Map(); - for(let { roleId, recId, params } of this.arr) { - if(!map.has(roleId)) map.set(roleId, []); - map.get(roleId).push({ recId, params }); - } - return map - } -} - -function getPointName(pointId: number) { - let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); - let dicArea = gameData.gvgArea.get(dicAreaPoint?.areaId); - if(!dicArea) return ''; - return dicArea.areaName||''; -} - -// function getCityName(cityId: number) { -// let dicCity = gameData.gvgCity.get(cityId); -// return dicCity?.cityName||''; -// } - -// export async function addTeamSettleRec(team: GVGTeamType) { -// let { roleId, roleName, leagueCode, configId, cityId, pointId, groupKey } = team; -// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_CITY, recId: GVG_REC_ID.CITY_TEAM_SETTLE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); -// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_LEAGUE, recId: GVG_REC_ID.LEAGUE_TEAM_SETTLE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); -// } - -// export async function addTeamLeaveRec(team: GVGTeamType, pointId: number) { -// let { roleId, roleName, leagueCode, configId, cityId, groupKey } = team; -// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_LEAGUE, recId: GVG_REC_ID.LEAGUE_TEAM_LEAVE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); -// } - - -// —————— 频道消息 —————— -export async function addLeagueLvUpMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, lv: number) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_LV_UP, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, lv }), '', '', getGuildCodeString(myLeague)); - await pushGroupMsgToRoom(msgData); -} - -export async function changeNoticeMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, notice: string) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_NOTICE, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, notice }), '', '', getGuildCodeString(myLeague)); - await pushGroupMsgToRoom(msgData); -} - -export function getGuildCodeString(myLeague: GVGLeagueType) { - let guildCodes = myLeague?.guildCodes||[]; - return guildCodes.join('|') -} - -export async function addTechActivateMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, techId: number) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_TECH_ACTIVATE, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, techId }), '', '', getGuildCodeString(myLeague)); - await pushGroupMsgToRoom(msgData); -} - -export async function addTechUnlockMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, techId: number) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_TECH_UNLOCK, JSON.stringify({ leagueCode: myLeague.leagueCode, leaderName: roleName, techId }), '', '', getGuildCodeString(myLeague)); - await pushGroupMsgToRoom(msgData); -} - -export async function addVestigeRankMessage(ranks: { rank: number, field: string }[]) { - let leagueCodes = ranks.map(cur => cur.field); - let leagues = await GVGLeagueModel.findByCodesWithoutPopulate(leagueCodes, 'leagueCode name guildCodes'); - for(let { rank, field: leagueCode } of ranks) { - let league = leagues.find(cur => cur.leagueCode == leagueCode); - if(!league) continue; - const msgData = await createGroupMsg('', '', CHANNEL_PREFIX.LEAGUE, leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_VESTIGE_ACCOUNT, JSON.stringify({ leagueCode: league.leagueCode, name: league.name, rank }), '', '', getGuildCodeString(league)); - await pushGroupMsgToRoom(msgData); - } -} - -export async function addCityGuardMessage(myLeague: GVGLeagueType, cityId: number) { - const msgData = await createGroupMsg('', '', CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_OCCUPY_CITY, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, cityId }), '', '', getGuildCodeString(myLeague)); - await pushGroupMsgToRoom(msgData); -} \ No newline at end of file + +// 动态 +import { CHANNEL_PREFIX, GVG_REC_ID, GVG_REC_TYPE, GVG_RESOURCE_TYPE, MSG_SOURCE, MSG_TYPE, PUSH_ROUTE } from "@consts"; +import { GVGBattleRecType } from "@db/GVGBattleRec"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import { GVGRecModel, GVGRecUpdate } from "@db/GVGRec"; +import { GVGVestigeRecType } from "@db/GVGVestigeRec"; +import { gameData } from "@pubUtils/data"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { createGroupMsg, pushGroupMsgToRoom } from "../chatService"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { getGVGConfig } from "./gvgService"; + +// 加入军团 +export async function guildJoinLeagueRecord(leagueCode: string, guildName: string) { + await leagueJoinOrQuitGuild(leagueCode, guildName, GVG_REC_ID.LEAGUE_JOIN_GUILD); +} + +// 退出军团 +export async function guildQuitLeagueRecord(leagueCode: string, guildName: string) { + await leagueJoinOrQuitGuild(leagueCode, guildName, GVG_REC_ID.LEAGUE_QUIT_GUILD); +} + +async function leagueJoinOrQuitGuild(leagueCode: string, guildName: string, recId: GVG_REC_ID.LEAGUE_JOIN_GUILD|GVG_REC_ID.LEAGUE_QUIT_GUILD) { + let { configId } = getGVGConfig(); + let params = [guildName]; + await GVGRecModel.addRec({ leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId, createTime: nowSeconds(), params }) +} + +export async function addLeagueRenameRecord(leagueCode: string, leagueName: string) { + let { configId } = getGVGConfig(); + let params = [leagueName]; + await GVGRecModel.addRec({ leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.LEAGUE_RENAME, createTime: nowSeconds(), params }) +} + +// 获得资源 +export async function addResourceRecord(roleId: string, roleName: string, leagueCode: string, resourceType: GVG_RESOURCE_TYPE, output: number) { + let { configId } = getGVGConfig(); + let params = [roleName, getResourceNameByType(resourceType), `${output}`]; + await GVGRecModel.addRec({ roleId, leagueCode, configId, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.ADD_RESOURCE, createTime: nowSeconds(), params }) +} + +function getResourceNameByType(resourceType: GVG_RESOURCE_TYPE) { + switch(resourceType) { + case GVG_RESOURCE_TYPE.FOOD: return '粮食'; + case GVG_RESOURCE_TYPE.MINERAL: return '矿物'; + case GVG_RESOURCE_TYPE.WOOD: return '木堆'; + } +} + +export async function addVestigeBattleEndRec(rec: GVGVestigeRecType) { + if(!rec) return; + let { configId, vestigeId, groupKey } = rec; + let vestigeName = gameData.gvgVestigeName.get(vestigeId); + if(rec.defenseInfo && rec.defenseInfo.isRobot) { // 对手是机器人,驻扎动态 + let { roleId, roleName, leagueCode, newRank, isSuccess } = rec.attackInfo; + if(isSuccess) { + let params = [ roleName, vestigeName, `第${newRank}名`]; + await GVGRecModel.addRec({ roleId, leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.SETTLE_POINT, createTime: nowSeconds(), params }); + } + } + if(rec.defenseInfo && !rec.defenseInfo.isRobot && rec.attackInfo.leagueCode != rec.defenseInfo.leagueCode) { + let { leagueName, newRank, isSuccess } = rec.attackInfo; + let { roleId, leagueCode, roleName } = rec.defenseInfo; + if(isSuccess) { + let params = [ roleName, vestigeName, `第${newRank}名`, leagueName]; + await GVGRecModel.addRec({ roleId, leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.POINT_BE_GRAB, createTime: nowSeconds(), params }); + } + } +} + +export async function addVestigeLeagueRankRec(configId: number, groupKey: string, ranks: { rank: number, field: string }[]) { + await GVGRecModel.addRecs(ranks.map(({ rank, field: leagueCode }) => { + let params = [ `第${rank}名`]; + return { leagueCode, configId, groupKey, type: GVG_REC_TYPE.PREPARE, recId: GVG_REC_ID.VESTIGE_RANK, createTime: nowSeconds(), params }; + })); +} + +export async function addBattleEndRec(rec: GVGBattleRecType) { + let { isSuccess, attackTeamAfter: attackTeam, defenseTeamAfter: defenseTeam, configId, groupKey } = rec; + let { roleId: defenseRoleId, leagueCode: defenseLeague, cityId, index: defenseIndex, curTeamBreak: defenseBreak, originPointId: defenseOriginPoint, roleName: defenseName } = defenseTeam; + let { roleId: attackRoleId, leagueCode: attackLeague, index: attackIndex, roleName: attackName} = attackTeam; + + let params = new GVGRecUpArr(configId, cityId, groupKey, nowSeconds()); + if(isSuccess) { + if(!defenseTeam.isRobot) params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_BE_ATTACKED_FAIL, [attackName, `队伍${defenseIndex}`]); + params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_ATTACK_SUCCESS, [`队伍${attackIndex}`, defenseName]); + if(defenseBreak && defenseOriginPoint > 0 ) { + if(!defenseTeam.isRobot) { + params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_LOST_POINT, [attackName, `队伍${defenseIndex}`, getPointName(defenseOriginPoint)]); + } + params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_GET_POINT, [`队伍${attackIndex}`, defenseName, getPointName(defenseOriginPoint)]); + } + } else { + if(!defenseTeam.isRobot) params.pushRec(defenseRoleId, defenseLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_BE_ATTACKED_SUCCESS, [attackName, `队伍${defenseIndex}`]); + params.pushRec(attackRoleId, attackLeague, GVG_REC_TYPE.BATTLE_BY_ROLE, GVG_REC_ID.TEAM_ATTACK_FAIL, [`队伍${attackIndex}`, defenseName]); + } + + await GVGRecModel.addRecs(params.getUpdateParam()); + let mapByRoleId = params.getMapByRoleId(); + for(let [roleId, recs] of mapByRoleId) { + if(recs.length > 0) sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_REC_ADD, { recs }); + } +} + +class GVGRecUpArr { + private arr: GVGRecUpdate[] = []; + private configId: number; + private cityId: number; + private groupKey: string; + private createTime: number; + + constructor(configId: number, cityId: number, groupKey: string, createTime: number) { + this.configId = configId; + this.cityId = cityId; + this.groupKey = groupKey; + this.createTime = createTime; + } + + public pushRec(roleId: string, leagueCode: string, type: GVG_REC_TYPE, recId: GVG_REC_ID, params: string[]) { + this.arr.push({ + configId: this.configId, cityId: this.cityId, groupKey: this.groupKey, createTime: this.createTime, + roleId, leagueCode, type, recId, params + }) + } + + public getUpdateParam() { + return this.arr; + } + + public getMapByRoleId() { + let map = new Map(); + for(let { roleId, recId, params } of this.arr) { + if(!map.has(roleId)) map.set(roleId, []); + map.get(roleId).push({ recId, params }); + } + return map + } +} + +function getPointName(pointId: number) { + let dicAreaPoint = gameData.gvgAreaPoint.get(pointId); + let dicArea = gameData.gvgArea.get(dicAreaPoint?.areaId); + if(!dicArea) return ''; + return dicArea.areaName||''; +} + +// function getCityName(cityId: number) { +// let dicCity = gameData.gvgCity.get(cityId); +// return dicCity?.cityName||''; +// } + +// export async function addTeamSettleRec(team: GVGTeamType) { +// let { roleId, roleName, leagueCode, configId, cityId, pointId, groupKey } = team; +// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_CITY, recId: GVG_REC_ID.CITY_TEAM_SETTLE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); +// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_LEAGUE, recId: GVG_REC_ID.LEAGUE_TEAM_SETTLE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); +// } + +// export async function addTeamLeaveRec(team: GVGTeamType, pointId: number) { +// let { roleId, roleName, leagueCode, configId, cityId, groupKey } = team; +// await GVGRecModel.addRec({ roleId, leagueCode, configId, cityId, groupKey, type: GVG_REC_TYPE.BATTLE_BY_LEAGUE, recId: GVG_REC_ID.LEAGUE_TEAM_LEAVE, createTime: nowSeconds(), params: [`${roleName}`, getPointName(pointId)] }); +// } + + +// —————— 频道消息 —————— +export async function addLeagueLvUpMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, lv: number) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_LV_UP, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, lv }), '', '', getGuildCodeString(myLeague)); + await pushGroupMsgToRoom(msgData); +} + +export async function changeNoticeMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, notice: string) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_NOTICE, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, notice }), '', '', getGuildCodeString(myLeague)); + await pushGroupMsgToRoom(msgData); +} + +export function getGuildCodeString(myLeague: GVGLeagueType) { + let guildCodes = myLeague?.guildCodes||[]; + return guildCodes.join('|') +} + +export async function addTechActivateMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, techId: number) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_TECH_ACTIVATE, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, techId }), '', '', getGuildCodeString(myLeague)); + await pushGroupMsgToRoom(msgData); +} + +export async function addTechUnlockMessage(roleId: string, roleName: string, myLeague: GVGLeagueType, techId: number) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_TECH_UNLOCK, JSON.stringify({ leagueCode: myLeague.leagueCode, leaderName: roleName, techId }), '', '', getGuildCodeString(myLeague)); + await pushGroupMsgToRoom(msgData); +} + +export async function addVestigeRankMessage(ranks: { rank: number, field: string }[]) { + let leagueCodes = ranks.map(cur => cur.field); + let leagues = await GVGLeagueModel.findByCodesWithoutPopulate(leagueCodes, 'leagueCode name guildCodes'); + for(let { rank, field: leagueCode } of ranks) { + let league = leagues.find(cur => cur.leagueCode == leagueCode); + if(!league) continue; + const msgData = await createGroupMsg('', '', CHANNEL_PREFIX.LEAGUE, leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_VESTIGE_ACCOUNT, JSON.stringify({ leagueCode: league.leagueCode, name: league.name, rank }), '', '', getGuildCodeString(league)); + await pushGroupMsgToRoom(msgData); + } +} + +export async function addCityGuardMessage(myLeague: GVGLeagueType, cityId: number) { + const msgData = await createGroupMsg('', '', CHANNEL_PREFIX.LEAGUE, myLeague.leagueCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GVG_OCCUPY_CITY, JSON.stringify({ leagueCode: myLeague.leagueCode, name: myLeague.name, cityId }), '', '', getGuildCodeString(myLeague)); + await pushGroupMsgToRoom(msgData); +} diff --git a/game-server/app/services/gvg/gvgService.ts b/game-server/app/services/gvg/gvgService.ts index d0d9ec333..a88ebc506 100644 --- a/game-server/app/services/gvg/gvgService.ts +++ b/game-server/app/services/gvg/gvgService.ts @@ -1,339 +1,339 @@ -import { pinus } from "pinus"; -import { GVGConfigModel, GVGConfigType } from "../../db/GVGConfig"; -import { getSeconds, getTimeFun, nowSeconds, WEEK_TO_SECOND } from "../../pubUtils/timeUtil"; -import { getServerCreateTime } from "../redisService"; -import { GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_JOB, PUSH_ROUTE } from "../../consts"; -import { GVGLeagueModel, GVGLeagueType } from "../../db/GVGLeague"; -import { GVGLeaguePrepareModel } from "../../db/GVGLeaguePrepare"; -import { gameData } from "../../pubUtils/data"; -import { getRandSingleEelm } from "../../pubUtils/util"; -import { GVG } from "../../pubUtils/dicParam"; -import { GuildModel, GuildType } from "../../db/Guild"; -import { GVGLeagueApplyModel } from "../../db/GVGLeagueApply"; -import { GVGMainData, LeagueContributeInfo } from "../../domain/gvgField/returnData"; -import { Contribute, GVGUserDataModel, GVGUserDataType } from "../../db/GVGUserData"; -import { GVGUserItemModel } from "../../db/GVGUserItem"; -import { GVGUserTaskModel } from "../../db/GVGUserTask"; -import { getMyAuth } from "./gvgTeamService"; -import { pick } from "underscore"; -import { calFighterContribute, calProducerContribute } from "./gvgPrepareService"; -import { calVestigeLeagueBoxRewards, getFightTimeByPeriod } from "./gvgFightService"; -import { GVGVestigeLeagueRankModel } from "../../db/GVGVestigeLeagueRank"; -import { GVGVestigeSumRankModel } from "../../db/GVGVestigeSumRank"; -import { GVGTeamModel } from "../../db/GVGTeam"; -import { sendMessageToGuildWithSuc } from "../pushService"; -import { GVGCityModel } from "../../db/GVGCity"; -import { GVGRoleDataModel } from "../../db/GVGRoleData"; -import { getGVGGroupIdOfServer } from "../serverService"; -import { UserGuildModel } from "../../db/UserGuild"; - -// 定时器相关 -export async function createNewGVGConfig() { - let { teamTime, prepareTime, battleTime, scheduleTime } = getPeriodTime(); - const config = await GVGConfigModel.createNewConfig(teamTime, prepareTime, battleTime, scheduleTime); - try { - await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); - await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); - await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); - await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); - await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); - await pinus.app.rpc.guild?.guildRemote?.clearBattleMemory.broadcast(); - } catch(e) { - console.log('remote未初始完'); - } - // 每周自动解散一些联军 - let autoLeagues = await GVGLeagueModel.findAutoCreateLeague(); - let needDissmissLeagueId: string[] = [], needDissmissLeagueCodes: string[] = []; - for(let league of autoLeagues) { - let groupKey = await getGroupKey(league.serverId); - if(!await GVGCityModel.checkLeagueHasGuard(groupKey, league.leagueCode)) { - needDissmissLeagueId.push(league._id); - needDissmissLeagueCodes.push(league.leagueCode); - } - } - await GVGLeagueModel.dismissByIds(needDissmissLeagueId); - await GuildModel.leagueAutoDismiss(needDissmissLeagueCodes); - for(let league of autoLeagues) { - if(needDissmissLeagueCodes.indexOf(league.leagueCode) == -1) continue; - for(let guildCode of league.guildCodes) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_DISSMISS, { leagueCode: league.leagueCode }) - } - } - - await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast(); - return config; -} - -// 获取各个周期的时间,大约每周日5点的时候刷的 -export function getPeriodTime() { - let now = new Date(); - let curDay = now.getDay(); // 今天星期几 - - let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM); - let prepareConfig = gameData.gvgPeriod.get(GVG_PERIOD.PREPARE); - let battleConfig = gameData.gvgPeriod.get(GVG_PERIOD.BATTLE); - - // 如果现在是周日,那么就是本周期的组队开始时间,如果是其他日子(启动初始化),就是下周期的组队开始时间 - let _teamTime = getTimeFun().getTimeWithWeek(teamConfig.startDay); - let _prepareTime = getTimeFun().getTimeWithWeek(prepareConfig.startDay); - let _battleTime = getTimeFun().getTimeWithWeek(battleConfig.startDay); - console.log('_teamTime: ', _teamTime); - - let teamTime = curDay == 0? _teamTime: _teamTime - 7 * 86400; - let prepareTime = curDay == 0? _prepareTime + 7 * 86400: _prepareTime; - let battleTime = curDay == 0? _battleTime + 7 * 86400: _battleTime; - let scheduleTime = teamTime + 7 * 86400; - - return { teamTime, prepareTime, battleTime, scheduleTime } -} - -export async function getGVGConfigFromRemote() { - let serverType = pinus.app.getServerType(); - if(serverType == 'guild') { - return getGVGConfig(); - } else { - let guildServers = pinus.app.getServersByType('guild'); - let server = getRandSingleEelm(guildServers); - return await pinus.app.rpc.guild.guildRemote.getGVGConfig.toServer(server.id); - } -} - -export async function setGVGConfig(config?: GVGConfigType) { - if(!config) { - config = await GVGConfigModel.findConfig(); - } - if(config.teamTime > nowSeconds()) { - config = null; - } - pinus.app.set('gvgConfigId', config?.configId||0); - pinus.app.set('gvgTeamTime', config?.teamTime||0); - pinus.app.set('gvgPrepareTime', config?.prepareTime||0); - pinus.app.set('gvgBattleTime', config?.battleTime||0); - pinus.app.set('gvgScheduleTime', config?.scheduleTime||0); -} - -/** - * 获取当前的赛期id - * @returns - */ -export function getGVGConfig() { - let configId: number = pinus.app.get('gvgConfigId'); - let teamTime: number = pinus.app.get('gvgTeamTime'); - let prepareTime: number = pinus.app.get('gvgPrepareTime'); - let battleTime: number = pinus.app.get('gvgBattleTime'); - let scheduleTime: number = pinus.app.get('gvgScheduleTime'); - return { configId, teamTime, prepareTime, battleTime, scheduleTime } -} - -export function getServerTypeByTime(openTime: number) { - let today = nowSeconds(); - if(today - openTime < WEEK_TO_SECOND) return GVG_SERVER_TYPE.NO; - let toWeek = getCurrentTeamTime(today); - let openWeek = getCurrentTeamTime(openTime); - let n = Math.floor((toWeek - openWeek) / WEEK_TO_SECOND); - let day = new Date(openTime * 1000).getDay(); - if(day == 6) n--; // 周六开服的服务器延后一周开启跨服 - return n <= GVG.GVG_CROSS_SERVICE_STARTTIME? GVG_SERVER_TYPE.SINGLE: GVG_SERVER_TYPE.MULTI; -} - -function getCurrentTeamTime(time: number) { - let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM); - // 本周日 - let _teamTime = getTimeFun(time).getTimeWithWeek(teamConfig.startDay, teamConfig.startHour, teamConfig.startMinute, teamConfig.startSecond); - return _teamTime > time? _teamTime - WEEK_TO_SECOND: _teamTime; -} - -export async function getGVGServerType(serverId: number) { - let openTime = await getServerCreateTime(serverId); - return getServerTypeByTime(openTime) -} - -export function getGVGPeriodData() { - let { configId, teamTime, prepareTime, battleTime, scheduleTime } = getGVGConfig(); - let period = getCurPeriod(); - let countdownTime = teamTime; - switch(period) { - case GVG_PERIOD.TEAM: { - countdownTime = prepareTime; break; - } - case GVG_PERIOD.PREPARE: { - countdownTime = battleTime; break; - } - case GVG_PERIOD.BATTLE: { - countdownTime = scheduleTime; break; - } - } - - // console.log('######## getGVGPeriodData', configId, teamTime, prepareTime, battleTime, scheduleTime) - return { configId, period, countdownTime }; -} - -export function getCurPeriod() { - let { teamTime, prepareTime, battleTime, scheduleTime } = getGVGConfig(); - return getPeriodByTime(teamTime, prepareTime, battleTime, scheduleTime) -} - -export function getPeriodByTime(teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) { - let now = nowSeconds(); - if(now >= teamTime && now < prepareTime) { - return GVG_PERIOD.TEAM; - } else if (now >= prepareTime && now < battleTime) { - return GVG_PERIOD.PREPARE; - } else if (now >= battleTime && now < scheduleTime){ - return GVG_PERIOD.BATTLE; - } else { - return GVG_PERIOD.NO; - } -} - -export async function initLeaguePrepare() { - const config = await GVGConfigModel.findConfig(); - if(!config) return; - const leagues = await GVGLeagueModel.findAllLeague(); - let groupKeyByServerId = new Map(); - for(let { leagueCode, memberCnt, serverId } of leagues) { - let groupKey = groupKeyByServerId.get(serverId); - if(!groupKey) { - groupKey = await getGroupKey(serverId); - groupKeyByServerId.set(serverId, groupKey); - } - - await GVGLeaguePrepareModel.initData(config.configId, groupKey, leagueCode, memberCnt); - } -} - -export async function getGVGInfoInGuild(roleId: string, guild: GuildType) { - let hasLeague = !!guild.leagueCode; - let serverId = guild.serverId; - let { configId, period, countdownTime } = getGVGPeriodData(); - let { startFightTime, endFightTime } = getFightTimeByPeriod(period); - let type = await getGVGServerType(serverId); - - if(hasLeague && configId > 0) { - return { - hasLeague, - configId, period, countdownTime, - type, - applyCnt: await getApplyCnt(guild.leagueCode), - ...await getMainData(roleId, guild.leagueCode, configId, period, countdownTime, type), - leagueDetailRank: await getLeagueRankBox(configId, guild.leagueCode, roleId), - myTeamCnt: await GVGTeamModel.getTeamCntByRole(roleId), - startFightTime, endFightTime - } - } else { - return { - hasLeague, - configId, period, countdownTime, - startFightTime, endFightTime, - type, - invitationCnt: await getInviteCnt(guild.code) - } - } -} - -export async function calLeagueCe(league: GVGLeagueType) { - const guildCodes = league?.guildCodes||[]; - const guilds = await GuildModel.findByCodes(guildCodes); - return guilds.reduce((pre, guild) => pre + guild.guildCe, 0); -} - -// 检查当前赛季阶段 -export async function checkGVGPeriod(p : GVG_PERIOD) { - let { period } = getGVGPeriodData(); - return period == p; -} - -// —————— 红点相关 —————— // -// 邀请 -export async function getInviteCnt(guildCode: string) { - let invitation = await GVGLeagueApplyModel.findInviteFromGuildWithoutPopulate(guildCode); - return invitation.length -} - -// 申请 -export async function getApplyCnt(leagueCode: string) { - let applies = await GVGLeagueApplyModel.findApplyFromLeagueWithoutPopulate(leagueCode); - return applies.length -} - -export async function getMainData(roleId: string, leagueCode: string, configId: number, period: number, countdownTime: number, serverType: number) { - let data = new GVGMainData(configId, period, countdownTime, serverType); - - let league = await GVGLeagueModel.findByCode(leagueCode); - if(league) { - data.setLeague(league, {}); - - let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, league.leagueCode); - data.setLeagueParpare(leaguePrepare); - data.setTechQueue(leaguePrepare?.techQueue||[]); - - let userData = await GVGUserDataModel.findByRole(configId, league.leagueCode, roleId); - let roleData = await GVGRoleDataModel.findByRole(configId, roleId); - let items = await GVGUserItemModel.findByRole(configId, league.leagueCode, roleId); - let tasks = await GVGUserTaskModel.findByRole(configId, league.leagueCode, roleId); - data.setPlayerInfo(userData, roleData, getMyAuth(league, roleId), undefined, undefined, items, tasks); - data.setLeagueCe(await calLeagueCe(league)); - data.setConstribute(await getContribute(userData)); - } - - let myInfo = pick(data.myInfo, ['auth', 'items', 'tasks', 'receivedLv']); - return { ...pick(data, ['guildCnt', 'leagueLv', 'techQueue', 'constribute']), myInfo } -} - -export async function getContribute(myUserData: GVGUserDataType) { - const { contribute = new Contribute(), box = [] } = myUserData||{}; - - const result: LeagueContributeInfo[] = []; - for(let curJob of [LEAGUE_JOB.PRODUCER, LEAGUE_JOB.FIGHTER]) { - let sumContribute = curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); - let boxReceived = box.filter(boxId => { - let dicBox = gameData.gvgContributeBox.get(boxId); - return dicBox.job == curJob; - }); - let disObj = new LeagueContributeInfo(curJob, sumContribute, boxReceived); - result.push(disObj) - } - return result; -} - -export async function getLeagueRankBox(configId: number, leagueCode: string, roleId: string) { - let joinTime = await getMemberJoinLeagueTime(leagueCode, roleId); - let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, leagueCode, roleId, joinTime); - let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); - let { canReceiveBox } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); - return { canReceiveBox } -} - -export async function getGroupKey(serverId: number) { - let serverType = await getGVGServerType(serverId); - if(serverType == GVG_SERVER_TYPE.SINGLE) { - return `s${serverId}`; - } else { - let groupId = await getGVGGroupIdOfServer(serverId); - return `g${groupId}`; - } -} - -/** - * 之前gvgLeague表的members没有记录加入联军时间,所以如果查询没有time的话,根据userGuild的time来更新一下这个数据 - * - * 获取玩家加入联军时间 - * @param leagueCode 联军id - * @param roleId - * @param league 联军表数据 - * @returns - */ -export async function getMemberJoinLeagueTime(leagueCode: string, roleId: string, league?: GVGLeagueType) { - if(!league) league = await GVGLeagueModel.findByCode(leagueCode, 'members'); - let members = league?.members||[]; - let member = members.find(cur => cur.roleId == roleId); - if(!member) return 0; - if(!member.time) { - let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt'); - let time = getSeconds(userGuild.createdAt); - await GVGLeagueModel.setMemberTime(leagueCode, roleId, time); - return time; - } - return member.time; -} \ No newline at end of file +import { pinus } from "pinus"; +import { GVGConfigModel, GVGConfigType } from "@db/GVGConfig"; +import { getSeconds, getTimeFun, nowSeconds, WEEK_TO_SECOND } from "@pubUtils/timeUtil"; +import { getServerCreateTime } from "../redisService"; +import { GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_JOB, PUSH_ROUTE } from "@consts"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import { GVGLeaguePrepareModel } from "@db/GVGLeaguePrepare"; +import { gameData } from "@pubUtils/data"; +import { getRandSingleEelm } from "@pubUtils/util"; +import { GVG } from "@pubUtils/dicParam"; +import { GuildModel, GuildType } from "@db/Guild"; +import { GVGLeagueApplyModel } from "@db/GVGLeagueApply"; +import { GVGMainData, LeagueContributeInfo } from "@domain/gvgField/returnData"; +import { Contribute, GVGUserDataModel, GVGUserDataType } from "@db/GVGUserData"; +import { GVGUserItemModel } from "@db/GVGUserItem"; +import { GVGUserTaskModel } from "@db/GVGUserTask"; +import { getMyAuth } from "./gvgTeamService"; +import { pick } from "underscore"; +import { calFighterContribute, calProducerContribute } from "./gvgPrepareService"; +import { calVestigeLeagueBoxRewards, getFightTimeByPeriod } from "./gvgFightService"; +import { GVGVestigeLeagueRankModel } from "@db/GVGVestigeLeagueRank"; +import { GVGVestigeSumRankModel } from "@db/GVGVestigeSumRank"; +import { GVGTeamModel } from "@db/GVGTeam"; +import { sendMessageToGuildWithSuc } from "../pushService"; +import { GVGCityModel } from "@db/GVGCity"; +import { GVGRoleDataModel } from "@db/GVGRoleData"; +import { getGVGGroupIdOfServer } from "../serverService"; +import { UserGuildModel } from "@db/UserGuild"; + +// 定时器相关 +export async function createNewGVGConfig() { + let { teamTime, prepareTime, battleTime, scheduleTime } = getPeriodTime(); + const config = await GVGConfigModel.createNewConfig(teamTime, prepareTime, battleTime, scheduleTime); + try { + await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); + await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); + await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); + await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); + await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); + await pinus.app.rpc.guild?.guildRemote?.clearBattleMemory.broadcast(); + } catch(e) { + console.log('remote未初始完'); + } + // 每周自动解散一些联军 + let autoLeagues = await GVGLeagueModel.findAutoCreateLeague(); + let needDissmissLeagueId: string[] = [], needDissmissLeagueCodes: string[] = []; + for(let league of autoLeagues) { + let groupKey = await getGroupKey(league.serverId); + if(!await GVGCityModel.checkLeagueHasGuard(groupKey, league.leagueCode)) { + needDissmissLeagueId.push(league._id); + needDissmissLeagueCodes.push(league.leagueCode); + } + } + await GVGLeagueModel.dismissByIds(needDissmissLeagueId); + await GuildModel.leagueAutoDismiss(needDissmissLeagueCodes); + for(let league of autoLeagues) { + if(needDissmissLeagueCodes.indexOf(league.leagueCode) == -1) continue; + for(let guildCode of league.guildCodes) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.LEAGUE_DISSMISS, { leagueCode: league.leagueCode }) + } + } + + await pinus.app.rpc.systimer.systimerRemote.initGVGConfigSchedule.broadcast(); + return config; +} + +// 获取各个周期的时间,大约每周日5点的时候刷的 +export function getPeriodTime() { + let now = new Date(); + let curDay = now.getDay(); // 今天星期几 + + let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM); + let prepareConfig = gameData.gvgPeriod.get(GVG_PERIOD.PREPARE); + let battleConfig = gameData.gvgPeriod.get(GVG_PERIOD.BATTLE); + + // 如果现在是周日,那么就是本周期的组队开始时间,如果是其他日子(启动初始化),就是下周期的组队开始时间 + let _teamTime = getTimeFun().getTimeWithWeek(teamConfig.startDay); + let _prepareTime = getTimeFun().getTimeWithWeek(prepareConfig.startDay); + let _battleTime = getTimeFun().getTimeWithWeek(battleConfig.startDay); + console.log('_teamTime: ', _teamTime); + + let teamTime = curDay == 0? _teamTime: _teamTime - 7 * 86400; + let prepareTime = curDay == 0? _prepareTime + 7 * 86400: _prepareTime; + let battleTime = curDay == 0? _battleTime + 7 * 86400: _battleTime; + let scheduleTime = teamTime + 7 * 86400; + + return { teamTime, prepareTime, battleTime, scheduleTime } +} + +export async function getGVGConfigFromRemote() { + let serverType = pinus.app.getServerType(); + if(serverType == 'guild') { + return getGVGConfig(); + } else { + let guildServers = pinus.app.getServersByType('guild'); + let server = getRandSingleEelm(guildServers); + return await pinus.app.rpc.guild.guildRemote.getGVGConfig.toServer(server.id); + } +} + +export async function setGVGConfig(config?: GVGConfigType) { + if(!config) { + config = await GVGConfigModel.findConfig(); + } + if(config.teamTime > nowSeconds()) { + config = null; + } + pinus.app.set('gvgConfigId', config?.configId||0); + pinus.app.set('gvgTeamTime', config?.teamTime||0); + pinus.app.set('gvgPrepareTime', config?.prepareTime||0); + pinus.app.set('gvgBattleTime', config?.battleTime||0); + pinus.app.set('gvgScheduleTime', config?.scheduleTime||0); +} + +/** + * 获取当前的赛期id + * @returns + */ +export function getGVGConfig() { + let configId: number = pinus.app.get('gvgConfigId'); + let teamTime: number = pinus.app.get('gvgTeamTime'); + let prepareTime: number = pinus.app.get('gvgPrepareTime'); + let battleTime: number = pinus.app.get('gvgBattleTime'); + let scheduleTime: number = pinus.app.get('gvgScheduleTime'); + return { configId, teamTime, prepareTime, battleTime, scheduleTime } +} + +export function getServerTypeByTime(openTime: number) { + let today = nowSeconds(); + if(today - openTime < WEEK_TO_SECOND) return GVG_SERVER_TYPE.NO; + let toWeek = getCurrentTeamTime(today); + let openWeek = getCurrentTeamTime(openTime); + let n = Math.floor((toWeek - openWeek) / WEEK_TO_SECOND); + let day = new Date(openTime * 1000).getDay(); + if(day == 6) n--; // 周六开服的服务器延后一周开启跨服 + return n <= GVG.GVG_CROSS_SERVICE_STARTTIME? GVG_SERVER_TYPE.SINGLE: GVG_SERVER_TYPE.MULTI; +} + +function getCurrentTeamTime(time: number) { + let teamConfig = gameData.gvgPeriod.get(GVG_PERIOD.TEAM); + // 本周日 + let _teamTime = getTimeFun(time).getTimeWithWeek(teamConfig.startDay, teamConfig.startHour, teamConfig.startMinute, teamConfig.startSecond); + return _teamTime > time? _teamTime - WEEK_TO_SECOND: _teamTime; +} + +export async function getGVGServerType(serverId: number) { + let openTime = await getServerCreateTime(serverId); + return getServerTypeByTime(openTime) +} + +export function getGVGPeriodData() { + let { configId, teamTime, prepareTime, battleTime, scheduleTime } = getGVGConfig(); + let period = getCurPeriod(); + let countdownTime = teamTime; + switch(period) { + case GVG_PERIOD.TEAM: { + countdownTime = prepareTime; break; + } + case GVG_PERIOD.PREPARE: { + countdownTime = battleTime; break; + } + case GVG_PERIOD.BATTLE: { + countdownTime = scheduleTime; break; + } + } + + // console.log('######## getGVGPeriodData', configId, teamTime, prepareTime, battleTime, scheduleTime) + return { configId, period, countdownTime }; +} + +export function getCurPeriod() { + let { teamTime, prepareTime, battleTime, scheduleTime } = getGVGConfig(); + return getPeriodByTime(teamTime, prepareTime, battleTime, scheduleTime) +} + +export function getPeriodByTime(teamTime: number, prepareTime: number, battleTime: number, scheduleTime: number) { + let now = nowSeconds(); + if(now >= teamTime && now < prepareTime) { + return GVG_PERIOD.TEAM; + } else if (now >= prepareTime && now < battleTime) { + return GVG_PERIOD.PREPARE; + } else if (now >= battleTime && now < scheduleTime){ + return GVG_PERIOD.BATTLE; + } else { + return GVG_PERIOD.NO; + } +} + +export async function initLeaguePrepare() { + const config = await GVGConfigModel.findConfig(); + if(!config) return; + const leagues = await GVGLeagueModel.findAllLeague(); + let groupKeyByServerId = new Map(); + for(let { leagueCode, memberCnt, serverId } of leagues) { + let groupKey = groupKeyByServerId.get(serverId); + if(!groupKey) { + groupKey = await getGroupKey(serverId); + groupKeyByServerId.set(serverId, groupKey); + } + + await GVGLeaguePrepareModel.initData(config.configId, groupKey, leagueCode, memberCnt); + } +} + +export async function getGVGInfoInGuild(roleId: string, guild: GuildType) { + let hasLeague = !!guild.leagueCode; + let serverId = guild.serverId; + let { configId, period, countdownTime } = getGVGPeriodData(); + let { startFightTime, endFightTime } = getFightTimeByPeriod(period); + let type = await getGVGServerType(serverId); + + if(hasLeague && configId > 0) { + return { + hasLeague, + configId, period, countdownTime, + type, + applyCnt: await getApplyCnt(guild.leagueCode), + ...await getMainData(roleId, guild.leagueCode, configId, period, countdownTime, type), + leagueDetailRank: await getLeagueRankBox(configId, guild.leagueCode, roleId), + myTeamCnt: await GVGTeamModel.getTeamCntByRole(roleId), + startFightTime, endFightTime + } + } else { + return { + hasLeague, + configId, period, countdownTime, + startFightTime, endFightTime, + type, + invitationCnt: await getInviteCnt(guild.code) + } + } +} + +export async function calLeagueCe(league: GVGLeagueType) { + const guildCodes = league?.guildCodes||[]; + const guilds = await GuildModel.findByCodes(guildCodes); + return guilds.reduce((pre, guild) => pre + guild.guildCe, 0); +} + +// 检查当前赛季阶段 +export async function checkGVGPeriod(p : GVG_PERIOD) { + let { period } = getGVGPeriodData(); + return period == p; +} + +// —————— 红点相关 —————— // +// 邀请 +export async function getInviteCnt(guildCode: string) { + let invitation = await GVGLeagueApplyModel.findInviteFromGuildWithoutPopulate(guildCode); + return invitation.length +} + +// 申请 +export async function getApplyCnt(leagueCode: string) { + let applies = await GVGLeagueApplyModel.findApplyFromLeagueWithoutPopulate(leagueCode); + return applies.length +} + +export async function getMainData(roleId: string, leagueCode: string, configId: number, period: number, countdownTime: number, serverType: number) { + let data = new GVGMainData(configId, period, countdownTime, serverType); + + let league = await GVGLeagueModel.findByCode(leagueCode); + if(league) { + data.setLeague(league, {}); + + let leaguePrepare = await GVGLeaguePrepareModel.findByLeague(configId, league.leagueCode); + data.setLeagueParpare(leaguePrepare); + data.setTechQueue(leaguePrepare?.techQueue||[]); + + let userData = await GVGUserDataModel.findByRole(configId, league.leagueCode, roleId); + let roleData = await GVGRoleDataModel.findByRole(configId, roleId); + let items = await GVGUserItemModel.findByRole(configId, league.leagueCode, roleId); + let tasks = await GVGUserTaskModel.findByRole(configId, league.leagueCode, roleId); + data.setPlayerInfo(userData, roleData, getMyAuth(league, roleId), undefined, undefined, items, tasks); + data.setLeagueCe(await calLeagueCe(league)); + data.setConstribute(await getContribute(userData)); + } + + let myInfo = pick(data.myInfo, ['auth', 'items', 'tasks', 'receivedLv']); + return { ...pick(data, ['guildCnt', 'leagueLv', 'techQueue', 'constribute']), myInfo } +} + +export async function getContribute(myUserData: GVGUserDataType) { + const { contribute = new Contribute(), box = [] } = myUserData||{}; + + const result: LeagueContributeInfo[] = []; + for(let curJob of [LEAGUE_JOB.PRODUCER, LEAGUE_JOB.FIGHTER]) { + let sumContribute = curJob == LEAGUE_JOB.PRODUCER? calProducerContribute(contribute): calFighterContribute(contribute); + let boxReceived = box.filter(boxId => { + let dicBox = gameData.gvgContributeBox.get(boxId); + return dicBox.job == curJob; + }); + let disObj = new LeagueContributeInfo(curJob, sumContribute, boxReceived); + result.push(disObj) + } + return result; +} + +export async function getLeagueRankBox(configId: number, leagueCode: string, roleId: string) { + let joinTime = await getMemberJoinLeagueTime(leagueCode, roleId); + let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, leagueCode, roleId, joinTime); + let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId); + let { canReceiveBox } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks); + return { canReceiveBox } +} + +export async function getGroupKey(serverId: number) { + let serverType = await getGVGServerType(serverId); + if(serverType == GVG_SERVER_TYPE.SINGLE) { + return `s${serverId}`; + } else { + let groupId = await getGVGGroupIdOfServer(serverId); + return `g${groupId}`; + } +} + +/** + * 之前gvgLeague表的members没有记录加入联军时间,所以如果查询没有time的话,根据userGuild的time来更新一下这个数据 + * + * 获取玩家加入联军时间 + * @param leagueCode 联军id + * @param roleId + * @param league 联军表数据 + * @returns + */ +export async function getMemberJoinLeagueTime(leagueCode: string, roleId: string, league?: GVGLeagueType) { + if(!league) league = await GVGLeagueModel.findByCode(leagueCode, 'members'); + let members = league?.members||[]; + let member = members.find(cur => cur.roleId == roleId); + if(!member) return 0; + if(!member.time) { + let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt'); + let time = getSeconds(userGuild.createdAt); + await GVGLeagueModel.setMemberTime(leagueCode, roleId, time); + return time; + } + return member.time; +} diff --git a/game-server/app/services/gvg/gvgTeamService.ts b/game-server/app/services/gvg/gvgTeamService.ts index a58766d71..5169bf126 100644 --- a/game-server/app/services/gvg/gvgTeamService.ts +++ b/game-server/app/services/gvg/gvgTeamService.ts @@ -1,265 +1,265 @@ -// 和gvg组建期相关的方法 - -import { pinus } from "pinus"; -import { GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from "../../consts"; -import { GuildModel, GuildType } from "../../db/Guild"; -import { GVGCityModel } from "../../db/GVGCity"; -import { GVGCityAreaPointModel } from "../../db/GVGCityAreaPoint"; -import { GVGLeagueModel, GVGLeagueType, GVGLeagueUpdate } from "../../db/GVGLeague"; -import { GVGLeagueApplyModel, GVGLeagueApplyType } from "../../db/GVGLeagueApply"; -import { GVGLeaguePrepareModel, GVGLeaguePrepareType } from "../../db/GVGLeaguePrepare"; -import { GVGTeamModel } from "../../db/GVGTeam"; -import { RoleType } from "../../db/Role"; -import { UserGuildModel } from "../../db/UserGuild"; -import { LeagueGuildInfo, LeagueListInfo } from "../../domain/gvgField/returnData"; -import { LeagueLeader } from "../../domain/rank"; -import { GVG } from "../../pubUtils/dicParam"; -import { getZeroPointD } from "../../pubUtils/timeUtil"; -import { resResult } from "../../pubUtils/util"; -import { updateUserInfo } from "../redisService"; -import { getGVGBattleData } from "../memoryCache/gvgBattleData"; -import { guildJoinLeagueRecord } from "./gvgRecService"; -import { calLeagueCe, getCurPeriod, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from "./gvgService"; - -/** - * 自动创建联军 - * @param guildCode 创建联军的那个军团 - * @returns GVGLeagueType - */ -export async function autoCreateLeague(guildCode: string) { - let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); - if(!guild || guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return; - - let { configId, period } = getGVGPeriodData(); - if(period == GVG_PERIOD.PREPARE) { - let league = await createLeague(guild, {}); - let groupKey = await getGroupKey(guild.serverId); - await GVGLeaguePrepareModel.initData(configId, groupKey, league.leagueCode, guild.memberCnt); - return league; - } -} - -/** - * 创建联军 - * @param guild 创建联军的那个军团 - * @param params 联军的一些初始数据 - * @returns - */ -export async function createLeague(guild: GuildType, params: GVGLeagueUpdate) { - let serverType = await getGVGServerType(guild.serverId); - params.type = serverType; - params.serverId = guild.serverId; - const league = await GVGLeagueModel.createLeague(guild, params); - await GuildModel.joinLeague(guild.code, league.leagueCode); - return league; -} - -/** - * 获取在联军中的职位 - * @param league - * @param roleId - * @returns - */ -export function getMyAuth(league: GVGLeagueType, roleId: string) { - let members = league.members; - let member = members.find(cur => cur.roleId == roleId); - return member?.auth?? LEAGUE_AUTH.MEMBER; -} - -/** - * 加入联军的当天如果是在准备期,这天不能去参加内政 - * @param roleId - * @returns - */ -export async function checkCanPrepare(roleId: string) { - let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt'); - let today = getZeroPointD(); - return userGuild.createdAt < today; -} - -/** - * 是否可以选择职能,如果选择的人数超过了就不可以选 - * @param myJob - * @param league - * @returns - */ -export function checkCanChooseJob(myJob: number, league: GVGLeaguePrepareType) { - if(myJob > 0) return false; - if(!league) return false; - let { producerCnt, fighterCnt, maxMemberCnt } = league; - return producerCnt + fighterCnt <= maxMemberCnt; -} - -/** - * 获取申请数据 - * @param apply 本条申请原数据 - * @param serverNames 全服务器的名字from redis - * @param invitations 本联军向其他军团发出的邀请 - * @returns - */ -export function getLeagueApplyData(apply: GVGLeagueApplyType, serverNames: any, invitations: GVGLeagueApplyType[] ) { - let data = new LeagueGuildInfo(apply.guild, serverNames); - let hasInvited = !!invitations.find(cur => cur.guildCode == apply.guildCode); - data.setHasInvited(hasInvited); - return data; -} - -/** - * 获取邀请数据 - * @param invite 本条邀请原数据 - * @param serverNames 全服务器的名字from redis - * @param applies 本军团向其他联军发出的申请 - * @returns - */ -export async function getLeagueInviteData(invite: GVGLeagueApplyType, serverNames: any, applies: GVGLeagueApplyType[]) { - let data = new LeagueListInfo(invite.league, serverNames); - let hasApply = !!applies.find(cur => cur.leagueCode == invite.guildCode); - data.setHasApply(hasApply); - data.setLeagueCe(await calLeagueCe(invite.league)) - return data; -} - -/** - * 联军加入军团 - * @param myLeague - * @param targetGuildCode - * @returns - */ -export async function joinGuildToLeague(league: GVGLeagueType, targetGuildCode: string) { - const hasApply = await GVGLeagueApplyModel.checkApply(league.leagueCode, targetGuildCode, GVG_APPLY_TYPE.ALL); - if(!hasApply) { - return resResult(STATUS.GUILD_NOT_APPLY); - } - if(league.guildCnt >= GVG.GVG_LEAGUE_COMPOSE) { - return resResult(STATUS.LEAGUE_IS_GUILD_MAX); - } - let hisLeague = await GVGLeagueModel.findLeagueByGuild(targetGuildCode); - if(hisLeague) { - await GVGLeagueApplyModel.deleteApply(targetGuildCode, league.leagueCode); - return resResult(STATUS.TARGET_GUILD_HAS_LEAGUE); - } - - const targetGuild = await GuildModel.findByCode(targetGuildCode, null, '+members'); - if(!targetGuild) return resResult(STATUS.TARGET_GUILD_NOT_FOUND); - if(targetGuild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH); - - league = await GVGLeagueModel.joinGuild(league.leagueCode, targetGuild); - - await GuildModel.joinLeague(targetGuildCode, league.leagueCode); - guildJoinLeagueRecord(league.leagueCode, targetGuild.name); - - return resResult(STATUS.SUCCESS, league); -} - -/** - * 检查是否可以进行组建联军等操作 - * @param serverId - * @param serverType - * @returns - */ -export async function checkCanManage(serverId: number, serverType?: number) { - if(!serverType) serverType = await getGVGServerType(serverId); - if(serverType != GVG_SERVER_TYPE.MULTI) return resResult(STATUS.GVG_TEAM_SERVER_TYPE_ERR); - let { period } = getGVGPeriodData(); - if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); - return resResult(STATUS.SUCCESS); -} - -/** - * 一些操作只能由军团的团长才能操作 - * @param guildCode - * @param roleId - * @param guild - * @returns - */ -export async function checkGuildLeader(guildCode: string, roleId: string, guild?: GuildType) { - if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); - if(!guild) return resResult(STATUS.GVG_HAS_NO_AUTH); - if(guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH); - - const userGuild = await UserGuildModel.getMyGuild(roleId, 'auth'); - if(!userGuild || userGuild.auth != GUILD_AUTH.LEADER) return resResult(STATUS.GVG_HAS_NO_AUTH); - return resResult(STATUS.SUCCESS); -} - -/** - * 检查联军的操作 - * @param roleId - * @param myLeague - * @param type - * @returns - */ -export async function checkLeagueAuth(roleId: string, myLeague: GVGLeagueType, type: LEAGUE_MANAGE_TYPE) { - const auth = getMyAuth(myLeague, roleId); - console.log('****', auth) - const needAuth = getAuthFromManageType(type); - return needAuth.indexOf(auth) > -1 -} - -function getAuthFromManageType(type: LEAGUE_MANAGE_TYPE) { - switch(type) { - case LEAGUE_MANAGE_TYPE.HANDLE_APPLY: - case LEAGUE_MANAGE_TYPE.INVITE: - case LEAGUE_MANAGE_TYPE.KICK: - case LEAGUE_MANAGE_TYPE.DISSMISS: - case LEAGUE_MANAGE_TYPE.ABDICATE: - case LEAGUE_MANAGE_TYPE.RERUIT: - return [LEAGUE_AUTH.LEADER]; - case LEAGUE_MANAGE_TYPE.QUIT: - case LEAGUE_MANAGE_TYPE.BE_ABDICATED: - return [LEAGUE_AUTH.SUB_LEADER]; - case LEAGUE_MANAGE_TYPE.SET_INFO: - case LEAGUE_MANAGE_TYPE.SEND_MAIL: - case LEAGUE_MANAGE_TYPE.UNLOCK_TECH: - case LEAGUE_MANAGE_TYPE.SET_TARGET_CITY: - case LEAGUE_MANAGE_TYPE.SET_NOTICE: - return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER]; - case LEAGUE_MANAGE_TYPE.ACTIVATE_TECH: - return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER, LEAGUE_AUTH.MEMBER]; - } -} - -export async function memberJoinGuildToLeague(guild: GuildType, role: RoleType) { - if(!guild.leagueCode) return; - await GVGLeagueModel.joinMember(guild.leagueCode, role.roleId, guild.code); -} - -export async function memberQuitGuildToLeague(guild: GuildType, role: RoleType) { - if(!guild.leagueCode) return; - await GVGLeagueModel.quitMember(guild.leagueCode, role.roleId); -} - -export async function guildDismissToLeague(guild: GuildType) { - if(!guild.leagueCode) return; - await GVGLeagueModel.quitGuild(guild.leagueCode, guild); -} - -export async function guildAbdicateToLeague(guild: GuildType, fromRoleId: string, toRole: RoleType) { - if(!guild.leagueCode) return; - await GVGLeagueModel.abdicateGuild(guild.leagueCode, fromRoleId, toRole.roleId, toRole._id); - await updateUserInfo(REDIS_KEY.LEAGUE_INFO, guild.leagueCode, [{ field: 'leader', value: new LeagueLeader(toRole) }]); -} - -export async function updateGVGBattleLeagueInfo(serverId: number, leagueCode: string, info: { leagueName?: string, icon?: number }) { - await GVGTeamModel.updateLeagueName(leagueCode, info.leagueName); - await GVGCityModel.updateLeagueInfo(leagueCode, info.leagueName, info.icon); - await GVGCityAreaPointModel.updateLeagueName(leagueCode, info.leagueName) - if(info.leagueName) await pinus.app.rpc.guild.guildRemote.updateLeagueNameMem.broadcast(serverId, leagueCode, info.leagueName); -} - -export async function updateLeagueNameMem(serverId: number, leagueCode: string, leagueName: string ) { - let groupKey = await getGroupKey(serverId); - let teamObj = getGVGBattleData(groupKey); - teamObj.updateLeagueInfo(leagueCode, leagueName); -} - -export async function updateGVGBattleRoleInfo(serverId: number, roleId: string, info: { roleName?: string, lv?: number }) { - await GVGTeamModel.updateRoleInfo(roleId, info); - await pinus.app.rpc.guild.guildRemote.updateTeamRoleInfoMem.broadcast(serverId, roleId, info); -} - -export async function updateTeamRoleInfoMem(serverId: number, roleId: string, info: { roleName?: string, lv?: number } ) { - let groupKey = await getGroupKey(serverId); - let teamObj = getGVGBattleData(groupKey); - teamObj.updateRoleInfo(roleId, info); -} \ No newline at end of file +// 和gvg组建期相关的方法 + +import { pinus } from "pinus"; +import { GUILD_AUTH, GVG_APPLY_TYPE, GVG_PERIOD, GVG_SERVER_TYPE, LEAGUE_AUTH, LEAGUE_MANAGE_TYPE, PUSH_ROUTE, REDIS_KEY, STATUS } from "@consts"; +import { GuildModel, GuildType } from "@db/Guild"; +import { GVGCityModel } from "@db/GVGCity"; +import { GVGCityAreaPointModel } from "@db/GVGCityAreaPoint"; +import { GVGLeagueModel, GVGLeagueType, GVGLeagueUpdate } from "@db/GVGLeague"; +import { GVGLeagueApplyModel, GVGLeagueApplyType } from "@db/GVGLeagueApply"; +import { GVGLeaguePrepareModel, GVGLeaguePrepareType } from "@db/GVGLeaguePrepare"; +import { GVGTeamModel } from "@db/GVGTeam"; +import { RoleType } from "@db/Role"; +import { UserGuildModel } from "@db/UserGuild"; +import { LeagueGuildInfo, LeagueListInfo } from "@domain/gvgField/returnData"; +import { LeagueLeader } from "@domain/rank"; +import { GVG } from "@pubUtils/dicParam"; +import { getZeroPointD } from "@pubUtils/timeUtil"; +import { resResult } from "@pubUtils/util"; +import { updateUserInfo } from "../redisService"; +import { getGVGBattleData } from "../memoryCache/gvgBattleData"; +import { guildJoinLeagueRecord } from "./gvgRecService"; +import { calLeagueCe, getCurPeriod, getGroupKey, getGVGConfig, getGVGPeriodData, getGVGServerType } from "./gvgService"; + +/** + * 自动创建联军 + * @param guildCode 创建联军的那个军团 + * @returns GVGLeagueType + */ +export async function autoCreateLeague(guildCode: string) { + let guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); + if(!guild || guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return; + + let { configId, period } = getGVGPeriodData(); + if(period == GVG_PERIOD.PREPARE) { + let league = await createLeague(guild, {}); + let groupKey = await getGroupKey(guild.serverId); + await GVGLeaguePrepareModel.initData(configId, groupKey, league.leagueCode, guild.memberCnt); + return league; + } +} + +/** + * 创建联军 + * @param guild 创建联军的那个军团 + * @param params 联军的一些初始数据 + * @returns + */ +export async function createLeague(guild: GuildType, params: GVGLeagueUpdate) { + let serverType = await getGVGServerType(guild.serverId); + params.type = serverType; + params.serverId = guild.serverId; + const league = await GVGLeagueModel.createLeague(guild, params); + await GuildModel.joinLeague(guild.code, league.leagueCode); + return league; +} + +/** + * 获取在联军中的职位 + * @param league + * @param roleId + * @returns + */ +export function getMyAuth(league: GVGLeagueType, roleId: string) { + let members = league.members; + let member = members.find(cur => cur.roleId == roleId); + return member?.auth?? LEAGUE_AUTH.MEMBER; +} + +/** + * 加入联军的当天如果是在准备期,这天不能去参加内政 + * @param roleId + * @returns + */ +export async function checkCanPrepare(roleId: string) { + let userGuild = await UserGuildModel.getMyGuild(roleId, 'createdAt'); + let today = getZeroPointD(); + return userGuild.createdAt < today; +} + +/** + * 是否可以选择职能,如果选择的人数超过了就不可以选 + * @param myJob + * @param league + * @returns + */ +export function checkCanChooseJob(myJob: number, league: GVGLeaguePrepareType) { + if(myJob > 0) return false; + if(!league) return false; + let { producerCnt, fighterCnt, maxMemberCnt } = league; + return producerCnt + fighterCnt <= maxMemberCnt; +} + +/** + * 获取申请数据 + * @param apply 本条申请原数据 + * @param serverNames 全服务器的名字from redis + * @param invitations 本联军向其他军团发出的邀请 + * @returns + */ +export function getLeagueApplyData(apply: GVGLeagueApplyType, serverNames: any, invitations: GVGLeagueApplyType[] ) { + let data = new LeagueGuildInfo(apply.guild, serverNames); + let hasInvited = !!invitations.find(cur => cur.guildCode == apply.guildCode); + data.setHasInvited(hasInvited); + return data; +} + +/** + * 获取邀请数据 + * @param invite 本条邀请原数据 + * @param serverNames 全服务器的名字from redis + * @param applies 本军团向其他联军发出的申请 + * @returns + */ +export async function getLeagueInviteData(invite: GVGLeagueApplyType, serverNames: any, applies: GVGLeagueApplyType[]) { + let data = new LeagueListInfo(invite.league, serverNames); + let hasApply = !!applies.find(cur => cur.leagueCode == invite.guildCode); + data.setHasApply(hasApply); + data.setLeagueCe(await calLeagueCe(invite.league)) + return data; +} + +/** + * 联军加入军团 + * @param myLeague + * @param targetGuildCode + * @returns + */ +export async function joinGuildToLeague(league: GVGLeagueType, targetGuildCode: string) { + const hasApply = await GVGLeagueApplyModel.checkApply(league.leagueCode, targetGuildCode, GVG_APPLY_TYPE.ALL); + if(!hasApply) { + return resResult(STATUS.GUILD_NOT_APPLY); + } + if(league.guildCnt >= GVG.GVG_LEAGUE_COMPOSE) { + return resResult(STATUS.LEAGUE_IS_GUILD_MAX); + } + let hisLeague = await GVGLeagueModel.findLeagueByGuild(targetGuildCode); + if(hisLeague) { + await GVGLeagueApplyModel.deleteApply(targetGuildCode, league.leagueCode); + return resResult(STATUS.TARGET_GUILD_HAS_LEAGUE); + } + + const targetGuild = await GuildModel.findByCode(targetGuildCode, null, '+members'); + if(!targetGuild) return resResult(STATUS.TARGET_GUILD_NOT_FOUND); + if(targetGuild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH); + + league = await GVGLeagueModel.joinGuild(league.leagueCode, targetGuild); + + await GuildModel.joinLeague(targetGuildCode, league.leagueCode); + guildJoinLeagueRecord(league.leagueCode, targetGuild.name); + + return resResult(STATUS.SUCCESS, league); +} + +/** + * 检查是否可以进行组建联军等操作 + * @param serverId + * @param serverType + * @returns + */ +export async function checkCanManage(serverId: number, serverType?: number) { + if(!serverType) serverType = await getGVGServerType(serverId); + if(serverType != GVG_SERVER_TYPE.MULTI) return resResult(STATUS.GVG_TEAM_SERVER_TYPE_ERR); + let { period } = getGVGPeriodData(); + if(period != GVG_PERIOD.TEAM) return resResult(STATUS.GVG_NOT_TEAM_PERIOD); + return resResult(STATUS.SUCCESS); +} + +/** + * 一些操作只能由军团的团长才能操作 + * @param guildCode + * @param roleId + * @param guild + * @returns + */ +export async function checkGuildLeader(guildCode: string, roleId: string, guild?: GuildType) { + if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members +serverId'); + if(!guild) return resResult(STATUS.GVG_HAS_NO_AUTH); + if(guild.lv < GVG.GVG_ARMY_LEAGUE_TIME) return resResult(STATUS.GUILD_LV_NOT_ENOUGH); + + const userGuild = await UserGuildModel.getMyGuild(roleId, 'auth'); + if(!userGuild || userGuild.auth != GUILD_AUTH.LEADER) return resResult(STATUS.GVG_HAS_NO_AUTH); + return resResult(STATUS.SUCCESS); +} + +/** + * 检查联军的操作 + * @param roleId + * @param myLeague + * @param type + * @returns + */ +export async function checkLeagueAuth(roleId: string, myLeague: GVGLeagueType, type: LEAGUE_MANAGE_TYPE) { + const auth = getMyAuth(myLeague, roleId); + console.log('****', auth) + const needAuth = getAuthFromManageType(type); + return needAuth.indexOf(auth) > -1 +} + +function getAuthFromManageType(type: LEAGUE_MANAGE_TYPE) { + switch(type) { + case LEAGUE_MANAGE_TYPE.HANDLE_APPLY: + case LEAGUE_MANAGE_TYPE.INVITE: + case LEAGUE_MANAGE_TYPE.KICK: + case LEAGUE_MANAGE_TYPE.DISSMISS: + case LEAGUE_MANAGE_TYPE.ABDICATE: + case LEAGUE_MANAGE_TYPE.RERUIT: + return [LEAGUE_AUTH.LEADER]; + case LEAGUE_MANAGE_TYPE.QUIT: + case LEAGUE_MANAGE_TYPE.BE_ABDICATED: + return [LEAGUE_AUTH.SUB_LEADER]; + case LEAGUE_MANAGE_TYPE.SET_INFO: + case LEAGUE_MANAGE_TYPE.SEND_MAIL: + case LEAGUE_MANAGE_TYPE.UNLOCK_TECH: + case LEAGUE_MANAGE_TYPE.SET_TARGET_CITY: + case LEAGUE_MANAGE_TYPE.SET_NOTICE: + return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER]; + case LEAGUE_MANAGE_TYPE.ACTIVATE_TECH: + return [LEAGUE_AUTH.LEADER, LEAGUE_AUTH.SUB_LEADER, LEAGUE_AUTH.MEMBER]; + } +} + +export async function memberJoinGuildToLeague(guild: GuildType, role: RoleType) { + if(!guild.leagueCode) return; + await GVGLeagueModel.joinMember(guild.leagueCode, role.roleId, guild.code); +} + +export async function memberQuitGuildToLeague(guild: GuildType, role: RoleType) { + if(!guild.leagueCode) return; + await GVGLeagueModel.quitMember(guild.leagueCode, role.roleId); +} + +export async function guildDismissToLeague(guild: GuildType) { + if(!guild.leagueCode) return; + await GVGLeagueModel.quitGuild(guild.leagueCode, guild); +} + +export async function guildAbdicateToLeague(guild: GuildType, fromRoleId: string, toRole: RoleType) { + if(!guild.leagueCode) return; + await GVGLeagueModel.abdicateGuild(guild.leagueCode, fromRoleId, toRole.roleId, toRole._id); + await updateUserInfo(REDIS_KEY.LEAGUE_INFO, guild.leagueCode, [{ field: 'leader', value: new LeagueLeader(toRole) }]); +} + +export async function updateGVGBattleLeagueInfo(serverId: number, leagueCode: string, info: { leagueName?: string, icon?: number }) { + await GVGTeamModel.updateLeagueName(leagueCode, info.leagueName); + await GVGCityModel.updateLeagueInfo(leagueCode, info.leagueName, info.icon); + await GVGCityAreaPointModel.updateLeagueName(leagueCode, info.leagueName) + if(info.leagueName) await pinus.app.rpc.guild.guildRemote.updateLeagueNameMem.broadcast(serverId, leagueCode, info.leagueName); +} + +export async function updateLeagueNameMem(serverId: number, leagueCode: string, leagueName: string ) { + let groupKey = await getGroupKey(serverId); + let teamObj = getGVGBattleData(groupKey); + teamObj.updateLeagueInfo(leagueCode, leagueName); +} + +export async function updateGVGBattleRoleInfo(serverId: number, roleId: string, info: { roleName?: string, lv?: number }) { + await GVGTeamModel.updateRoleInfo(roleId, info); + await pinus.app.rpc.guild.guildRemote.updateTeamRoleInfoMem.broadcast(serverId, roleId, info); +} + +export async function updateTeamRoleInfoMem(serverId: number, roleId: string, info: { roleName?: string, lv?: number } ) { + let groupKey = await getGroupKey(serverId); + let teamObj = getGVGBattleData(groupKey); + teamObj.updateRoleInfo(roleId, info); +} diff --git a/game-server/app/services/ladderService.ts b/game-server/app/services/ladderService.ts index fb0e85c73..19c53374a 100644 --- a/game-server/app/services/ladderService.ts +++ b/game-server/app/services/ladderService.ts @@ -1,454 +1,454 @@ -import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_SERVER_GAP_TIME, LADDER_STATUS, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, TA_USERSET_TYPE } from "../consts"; -import { ArtifactModel } from "../db/Artifact"; -import { HeroModel, HeroType } from "../db/Hero"; -import { LadderMatchModel, LadderMatchType, LadderUpdateInter } from "../db/LadderMatch"; -import { LadderMatchRecModel, LadderMatchRecType } from "../db/LadderMatchRec"; -import { RoleModel, RoleType } from "../db/Role"; -import { LadderDataReturn, LadderDefense, LadderOppDetailReturn, LadderOppPlayerHeroInfo, LadderOppPlayerInDB, LadderOppPlayerInfo, LadderOppPlayerReturn } from "../domain/battleField/ladder"; -import { RoleAndGuildRankInfo, RoleRankInfo } from "../domain/rank"; -import { gameData, getDicLadderMatchByMyRank, getLadderRankReward } from "../pubUtils/data"; -import { EXTERIOR, LADDER } from "../pubUtils/dicParam"; -import { ItemInter, RewardInter } from "../pubUtils/interface"; -import { getRandValueByMinMax, shouldRefresh } from "../pubUtils/util"; -import { pushIconShow } from "./connectorService"; -import { sendMailByContent } from "./mailService"; -import { getHeroesAttributes } from "./playerCeService"; -import { sendMessageToUserWithSuc } from "./pushService"; -import { Rank } from "./rankService"; -import { getLadderDefCe, saveLadderDefCeByData } from "./redisService"; -import { addItems } from "./role/rewardService"; -import { combineItems } from "./role/util"; -import { reportTAUserSet } from "./sdkService"; -import { WarReward } from "./warRewardService"; - -export function refreshLadderDaily(ladderData: LadderMatchType) { - - let { refOppCnt = 0, buyCnt = 0, challengeCnt = 0, refDaily } = ladderData; - let curTime = new Date(); - let shouldRefOpp = shouldRefresh(refDaily, curTime); - if (shouldRefOpp) { - refOppCnt = 0; buyCnt = 0; challengeCnt = 0; refDaily = curTime; - } - return { - shouldRefOpp, - refOppCnt, refDaily, buyCnt, challengeCnt, - } -} - -export function getBuyCntCost(buyCnt: number, incCnt: number) { - let items: ItemInter[] = []; - for(let i = 1; i <= incCnt; i++) { - let cost = getSingleBuyCost(buyCnt + i); - if(!cost) return false; - items.push(cost); - } - return combineItems(items); -} - -function getSingleBuyCost(buyCnt: number) { - for(let { id, count, times } of gameData.ladderConsume) { - if(buyCnt <= times) { - return { id, count } - } - } - return false -} - -export async function getLadderData(roleId: string, needOppPlayer: boolean) { - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if(!ladderData) { - let role = await RoleModel.findByRoleId(roleId); - ladderData = await LadderMatchModel.createLadder({ serverId: role.serverId, roleId: role.roleId, role: role._id }); - } - - // 刷新次数 - let refOppObj = refreshLadderDaily(ladderData); - if(refOppObj.shouldRefOpp) { - ladderData = await LadderMatchModel.updateByRoleId(roleId, refOppObj); - } - - let ladderRec = await LadderMatchRecModel.findNotCompleteRecByRoleId(roleId); - - let result = new LadderDataReturn(); - result.setLadderData(ladderData, ladderRec); - - if(needOppPlayer) { - let oppPlayersReturn = await getLadderEnemies(ladderData); - result.setOppPlayers(oppPlayersReturn); - } - return result; -} - -export async function getLadderEnemies(ladderData: LadderMatchType) { - let oppPlayers = ladderData.oppPlayers||[]; - if(!oppPlayers || oppPlayers.length) { - return await getOppPlayerDetailByDb(ladderData.serverId, ladderData.oppPlayers); - } else { - return await refreshLadderEnemies(ladderData); - } -} - -async function getOppPlayerDetailByDb(serverId: number, oppPlayers: LadderOppPlayerInDB[]) { - let oppPlayersReturn: LadderOppPlayerReturn[] = []; - for(let oppPlayer of oppPlayers) { - let player = await generateOppPlayer(serverId, oppPlayer.rank); - oppPlayersReturn.push(player); - } - return oppPlayersReturn; -} - -// 获取redis当中的玩家排名数据 -export async function getLadderMatchByRank(serverId: number, max: number|'+inf', min: number|'-inf') { - let r = new Rank(REDIS_KEY.LADDER, { serverId }, false, 4000); - let rawResults = await r.getRankByRangeRaw(max, min, false); - return rawResults.map(cur => ({ rank: cur.scores[0], roleId: cur.field })) -} - -export async function refreshLadderEnemies(ladderData: LadderMatchType, update: LadderUpdateInter = {}) { - let rankNumbers = randOppRankNumbers(ladderData.rank); // 随机出想要的排名 - return await generateOppPlayers(rankNumbers, ladderData.serverId, ladderData.roleId, update); -} - -export async function generateOppPlayers(rankNumbers: number[], serverId: number, roleId: string, update: LadderUpdateInter = {}) { - let min = rankNumbers[0], max = rankNumbers[rankNumbers.length - 1]; - let ranks = await getLadderMatchByRank(serverId, max, min); - - let oppPlayers: LadderOppPlayerReturn[] = [], oppPlayersSave: LadderOppPlayerInDB[] = []; - for(let rank of rankNumbers) { - let player = await generateOppPlayer(serverId, rank); - oppPlayersSave.push({ rank }); - oppPlayers.push(player); - } - await LadderMatchModel.updateByRoleId(roleId, { ...update, oppPlayers: oppPlayersSave }); - return oppPlayers -} - -async function generateOppPlayer(serverId: number, rank: number) { - let r = new Rank(REDIS_KEY.LADDER, { serverId }, false); - let result = new LadderOppPlayerReturn(rank); - if(rank < 3001) { - let players = await r.getRankByRange(rank, rank, false, true); - if(players.length > 0) { - let player = players[0]; - let defCe = await getLadderDefCe(player.roleId); - result.setByRedis(player, parseInt(`${defCe}`)); - } - } - if(!result.roleId) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); - result.setByRobot(dicLadderDifficultRatio); - } - return result; -} - -function randOppRankNumbers(myRank: number) { - let dicLadderMatch = getDicLadderMatchByMyRank(myRank); - if(!dicLadderMatch) return new Array(5).fill(3001); - - let beforeRanks = randomRank(true, myRank, dicLadderMatch.rangeBeforeMax, dicLadderMatch.rangeBeforeNum); - let afterRanks = randomRank(false, myRank, dicLadderMatch.rangeAfterMax, dicLadderMatch.rangeAfterNum); - - let topTen = getNumberArr(1, 10); - let ranks = [...topTen, ...beforeRanks, ...afterRanks]; - return uniqueArr(ranks.sort((a, b) => a - b)); -} - -export function uniqueArr(arr: T[]) { - return arr.filter( (item, index, arr) => { - //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 - return arr.indexOf(item) === index; - }); -} - -export function getNumberArr(from: number, to: number) { - let arr: number[] = []; - for(let i = from; i <= to; i++) { - if(i > 0) arr.push(i); - } - return arr; -} - -function randomRank(isBefore: boolean, myRank: number, range: number, len: number) { - if(range == 0 || len == 0) return []; - let arr: number[] = []; - let n = Math.floor(range / len); - for(let i = 0; i < len; i++) { - let rand = getRandValueByMinMax(n * i + 1, n * (i + 1) + 1, 0); // 因为这个的范围是[min, max),而想要的是 (n * i, n * (i - 1)] - if(rand) { - let ratio = isBefore? -1: 1; - let rank = myRank + ratio * rand; - if( rank > 3001) rank = 3002; - arr.push(rank); - } - } - return arr; -} - -export function checkRank(myRank: number, targetRank: number) { - let dicLadderMatch = getDicLadderMatchByMyRank(myRank); - if(!dicLadderMatch) { - if(myRank == 0 && targetRank == 3001) return true; - return false - } - if(myRank == targetRank) return false; - if(targetRank <= 10) { - return dicLadderMatch.topChallenge == 1; - } else { - if(myRank < targetRank) { // 向后打 - if(myRank + dicLadderMatch.rangeAfterMax < targetRank) return false; - } else { // 向前打 - if(myRank - dicLadderMatch.rangeBeforeMax > targetRank) return false; - } - } - - return true; -} - -export async function getLadderOppStatus(ladderData: LadderMatchType, targetRoleId: string, myRank: number, rank: number) { - if(ladderData.rank != myRank) return { status: LADDER_OPP_STATUS.MY_RANK_CHANGE }; - let isRobot = targetRoleId.startsWith('robot'); - - if(isRobot) { - if(rank <= 3000) { - let hisLadderData = await LadderMatchRecModel.checkByRank(ladderData.serverId, `robot${rank}`); - if(hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; - - let ladderMatch = await LadderMatchModel.isRankExist(ladderData.serverId, rank); - if(ladderMatch) { - return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; - } - } - - return { status: LADDER_OPP_STATUS.BATTLE, isRobot: true }; - } else { - let ladderMatch = await LadderMatchModel.findByRoleId(targetRoleId); - if(!ladderMatch || ladderMatch.rank != rank) { - return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; - } - let hisLadderData = await LadderMatchModel.lock(ladderData.serverId, targetRoleId, rank); - if(!hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; - - return { status: LADDER_OPP_STATUS.BATTLE, isRobot: false, hisLadderData }; - } -} - -/** - * - * @param isRobot 是否是机器 - * @param isDefense 是攻还是守方 - * @param rank 排名 - * @param ladderData 需要populate过的ladderMatch表 - * @returns - */ -export async function generateInitRecInfo(isRobot: boolean, isDefense: boolean, rank: number, ladderData: LadderMatchType) { - if(isRobot) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); - let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); - let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId)||[]; - - let heroes: LadderOppPlayerHeroInfo[] = []; - for(let json of dicWarJson) { - if(json.relation == 2) { - let hero = new LadderOppPlayerHeroInfo(); - hero.setByWarJson(json); - heroes.push(hero); - } - } - let info = new LadderOppPlayerInfo(); - info.initByRobot(dicLadderDifficultRatio, heroes, isDefense); - return info; - } else { - let defCe = calculateDefCeByDefense(ladderData.defense); - let role = ladderData.role; - let heroes: LadderOppPlayerHeroInfo[] = []; - if(isDefense) { // 防守方可以将武将也存入,攻方要等出战 - let defenseHeroes = ladderData.defense?.heroes||[]; - for(let defenseHero of defenseHeroes) { - let hero = new LadderOppPlayerHeroInfo(); - let dbHero = defenseHero.hero; - hero.setByDefenseHero(dbHero); - if(dbHero && dbHero.artifact) { - let artifact = await ArtifactModel.findbySeqId(role.roleId, dbHero.artifact); - hero.setArtifact(artifact); - } - if(defenseHero.subHid) { - let subHero = await HeroModel.findByHidAndRole(defenseHero.subHid, role.roleId, 'hid skinId'); - hero.setSubHero(subHero) - } - heroes.push(hero); - } - } - let info = new LadderOppPlayerInfo(); - info.initByPlayer(rank, role, heroes, defCe, isDefense); - return info; - } -} - -function calculateDefCeByDefense(defense: LadderDefense) { - if(!defense) return 0; - let ce = 0; - for(let hero of defense.heroes) { - ce += hero.ce; - } - return ce; -} - -export async function ladderTimeWillout(battleCode: string, status: LADDER_STATUS) { - console.log('######### ladderTimeWillout') - if (status == LADDER_STATUS.BATTLE) { - let rec = await LadderMatchRecModel.findByBattleCode(battleCode); - await sendMessageToUserWithSuc(rec.roleId1, PUSH_ROUTE.LADDER_BATTLE_STOP, { battleCode }); - } -} - -export async function ladderTimeout(battleCode: string, status: LADDER_STATUS) { - console.log('######### ladderTimeout') - let rec = await LadderMatchRecModel.timeout(battleCode); - // console.log('##### rec.defenseInfo', rec.defenseInfo, rec.defenseInfo.isRobot, rec.defenseInfo.roleId) - if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId); - - if(status == LADDER_STATUS.CHECK) { - await sendMessageToUserWithSuc(rec.roleId1, PUSH_ROUTE.LADDER_CHECK_STOP, { battleCode }); - } -} - -/** - * 结算时候设置排行、发送推送、刷新对手、发送跑马灯 - * @param ladderMatch - * @param isAtk - * @returns - */ -export async function battleEndWhenChange(atkLadderMatch: LadderMatchType, defLadderMatch: LadderMatchType, needRefresh: boolean) { - await updateLadderRedis(atkLadderMatch); - await updateLadderRedis(defLadderMatch); - - if(atkLadderMatch) reportTAUserSet(TA_USERSET_TYPE.SET, atkLadderMatch.roleId, { ladder_rank: atkLadderMatch.rank }); - if(defLadderMatch) reportTAUserSet(TA_USERSET_TYPE.SET, defLadderMatch.roleId, { ladder_rank: defLadderMatch.rank }); - - await refreshOpp(defLadderMatch, needRefresh); - return await refreshOpp(atkLadderMatch, needRefresh); -} - -async function updateLadderRedis(ladderMatch: LadderMatchType) { - if(!ladderMatch) return; - // 更新redis - if(ladderMatch.rank > 0 && ladderMatch.rank < 3001) { - let r = new Rank(REDIS_KEY.LADDER, { serverId: ladderMatch.serverId }); - await r.setRankWithRoleInfo(ladderMatch.roleId, ladderMatch.rank, 0); - await saveLadderDefCeByData(ladderMatch.roleId, ladderMatch); - } -} - -async function refreshOpp(ladderMatch: LadderMatchType, needRefresh: boolean) { - if(!ladderMatch) return [] - // 刷新对手 - if(needRefresh) { - let oppPlayers = await refreshLadderEnemies(ladderMatch); - await sendMessageToUserWithSuc(ladderMatch.roleId, PUSH_ROUTE.LADDER_RANK_UPDATE, { - oldRank: ladderMatch.oldRank, - newRank: ladderMatch.rank, - oppPlayers - }); - return oppPlayers - } else { - return [] - } -} - -export async function ladderBattleEndReward(roleId: string, roleName: string, sid: string, rank: number, isSuccess: boolean, historyRank: number, num: number) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); - if(!dicLadderDifficultRatio) return { battleGoods: [], breakGoods: [] }; - let warReward = new WarReward(roleId, roleName, sid, dicLadderDifficultRatio.gkId, isSuccess); - warReward.setLadderReward(dicLadderDifficultRatio.randomWinReward, true); - warReward.setLadderReward(dicLadderDifficultRatio.randomFailReward, false); - let battleGoods = await warReward.saveReward(num); - let breakRewards: RewardInter[] = []; - for(let i = historyRank - 1; i >= rank; i--) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(i); - breakRewards.push(...(dicLadderDifficultRatio?.onceReward||[])); - } - let breakGoods = breakRewards.length > 0? await addItems(roleId, roleName, sid, combineItems(breakRewards), ITEM_CHANGE_REASON.LADDER_BATTLE_REWARD): []; - return { battleGoods, breakGoods }; -} - -export function completeLadderRanks(ranks: RoleAndGuildRankInfo[], serverId: number) { - let result: RoleAndGuildRankInfo[] = []; - for(let i = 1; i <= 200; i++) { - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(i); - let { head, ce, spine, level } = dicLadderDifficultRatio; - let rank = ranks.find(cur => cur.rank == i); - if(rank) { - result.push(rank); - } else { - let rank = new RoleAndGuildRankInfo(i, 0); - rank.setByField(`robot${i}`, LADDER.LADDER_ROBOT_NAME, head, EXTERIOR.EXTERIOR_FACECASE, spine, level, 1, '', ce, ce, serverId ); - result.push(rank); - } - } - return result; -} - -export function completeRanks(ranks: RoleAndGuildRankInfo[]) { - let max = Math.max(...ranks.map(cur => cur.rank), 0); - if(max > 200) max = 200; - let result: RoleAndGuildRankInfo[] = []; - for(let i = 1; i <= max; i++) { - let rank = ranks.find(cur => cur.rank == i); - if(rank) { - result.push(rank); - } else { - let rank = new RoleAndGuildRankInfo(i, 0); - result.push(rank); - } - } - return result; -} - -export async function sendLadderDailyReward(serverId: number) { - let ranks = await getLadderMatchByRank(serverId, '+inf', '-inf'); - for(let { rank, roleId } of ranks) { - let dicRankReward = getLadderRankReward(rank); - if(dicRankReward && dicRankReward.reward && dicRankReward.reward.length > 0) { - await sendMailByContent(MAIL_TYPE.LADDER, roleId, { params: [`${rank}`], goods: dicRankReward.reward }); - } - } -} - -export async function getLadderOppDetailData(rec: LadderMatchRecType) { - let isRobot = rec.defenseInfo.isRobot; - let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank); - let result = new LadderOppDetailReturn(rec); - if(isRobot) { - result.setByRobot(dicLadderDifficultRatio); - } else { - let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(rec.roleId2); - let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); - let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); - let artifactSeids = [], subHids: number[] = []; - for(let { hero, subHid } of hisLadderData.defense.heroes) { - let dbHero = hero; - if(dbHero) artifactSeids.push(dbHero.artifact); - if(subHid) subHids.push(subHid); - } - - let artifacts = await ArtifactModel.findbySeqIds(rec.roleId2, artifactSeids); - let subHeroes = await HeroModel.findByHidRange(subHids, rec.roleId2, 'hid skinId'); - result.setByPlayer(hisLadderData, dicWarJson, artifacts, subHeroes); - let attrByHid = await getHeroesAttributes(rec.roleId2); - for(let [hid, attribute] of attrByHid) { - result.setAttribute(hid, attribute.getAttributesToString()); - } - } - return result; -} - -export async function pushLadderIconShow(roleId: string, ladderIconShow:boolean) { - if (!roleId) return; - await pushIconShow(roleId, ladderIconShow); -} - -export async function getIsExistLadderDefense(roleId: string) { - let ladderData = await LadderMatchModel.findByRoleId(roleId); - if (!ladderData || !ladderData.defense || !ladderData.defense.heroes) return false; - return true; -} \ No newline at end of file +import { ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_SERVER_GAP_TIME, LADDER_STATUS, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, TA_USERSET_TYPE } from "@consts"; +import { ArtifactModel } from "@db/Artifact"; +import { HeroModel, HeroType } from "@db/Hero"; +import { LadderMatchModel, LadderMatchType, LadderUpdateInter } from "@db/LadderMatch"; +import { LadderMatchRecModel, LadderMatchRecType } from "@db/LadderMatchRec"; +import { RoleModel, RoleType } from "@db/Role"; +import { LadderDataReturn, LadderDefense, LadderOppDetailReturn, LadderOppPlayerHeroInfo, LadderOppPlayerInDB, LadderOppPlayerInfo, LadderOppPlayerReturn } from "@domain/battleField/ladder"; +import { RoleAndGuildRankInfo, RoleRankInfo } from "@domain/rank"; +import { gameData, getDicLadderMatchByMyRank, getLadderRankReward } from "@pubUtils/data"; +import { EXTERIOR, LADDER } from "@pubUtils/dicParam"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; +import { getRandValueByMinMax, shouldRefresh } from "@pubUtils/util"; +import { pushIconShow } from "./connectorService"; +import { sendMailByContent } from "./mailService"; +import { getHeroesAttributes } from "./playerCeService"; +import { sendMessageToUserWithSuc } from "./pushService"; +import { Rank } from "./rankService"; +import { getLadderDefCe, saveLadderDefCeByData } from "./redisService"; +import { addItems } from "./role/rewardService"; +import { combineItems } from "./role/util"; +import { reportTAUserSet } from "./sdkService"; +import { WarReward } from "./warRewardService"; + +export function refreshLadderDaily(ladderData: LadderMatchType) { + + let { refOppCnt = 0, buyCnt = 0, challengeCnt = 0, refDaily } = ladderData; + let curTime = new Date(); + let shouldRefOpp = shouldRefresh(refDaily, curTime); + if (shouldRefOpp) { + refOppCnt = 0; buyCnt = 0; challengeCnt = 0; refDaily = curTime; + } + return { + shouldRefOpp, + refOppCnt, refDaily, buyCnt, challengeCnt, + } +} + +export function getBuyCntCost(buyCnt: number, incCnt: number) { + let items: ItemInter[] = []; + for(let i = 1; i <= incCnt; i++) { + let cost = getSingleBuyCost(buyCnt + i); + if(!cost) return false; + items.push(cost); + } + return combineItems(items); +} + +function getSingleBuyCost(buyCnt: number) { + for(let { id, count, times } of gameData.ladderConsume) { + if(buyCnt <= times) { + return { id, count } + } + } + return false +} + +export async function getLadderData(roleId: string, needOppPlayer: boolean) { + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if(!ladderData) { + let role = await RoleModel.findByRoleId(roleId); + ladderData = await LadderMatchModel.createLadder({ serverId: role.serverId, roleId: role.roleId, role: role._id }); + } + + // 刷新次数 + let refOppObj = refreshLadderDaily(ladderData); + if(refOppObj.shouldRefOpp) { + ladderData = await LadderMatchModel.updateByRoleId(roleId, refOppObj); + } + + let ladderRec = await LadderMatchRecModel.findNotCompleteRecByRoleId(roleId); + + let result = new LadderDataReturn(); + result.setLadderData(ladderData, ladderRec); + + if(needOppPlayer) { + let oppPlayersReturn = await getLadderEnemies(ladderData); + result.setOppPlayers(oppPlayersReturn); + } + return result; +} + +export async function getLadderEnemies(ladderData: LadderMatchType) { + let oppPlayers = ladderData.oppPlayers||[]; + if(!oppPlayers || oppPlayers.length) { + return await getOppPlayerDetailByDb(ladderData.serverId, ladderData.oppPlayers); + } else { + return await refreshLadderEnemies(ladderData); + } +} + +async function getOppPlayerDetailByDb(serverId: number, oppPlayers: LadderOppPlayerInDB[]) { + let oppPlayersReturn: LadderOppPlayerReturn[] = []; + for(let oppPlayer of oppPlayers) { + let player = await generateOppPlayer(serverId, oppPlayer.rank); + oppPlayersReturn.push(player); + } + return oppPlayersReturn; +} + +// 获取redis当中的玩家排名数据 +export async function getLadderMatchByRank(serverId: number, max: number|'+inf', min: number|'-inf') { + let r = new Rank(REDIS_KEY.LADDER, { serverId }, false, 4000); + let rawResults = await r.getRankByRangeRaw(max, min, false); + return rawResults.map(cur => ({ rank: cur.scores[0], roleId: cur.field })) +} + +export async function refreshLadderEnemies(ladderData: LadderMatchType, update: LadderUpdateInter = {}) { + let rankNumbers = randOppRankNumbers(ladderData.rank); // 随机出想要的排名 + return await generateOppPlayers(rankNumbers, ladderData.serverId, ladderData.roleId, update); +} + +export async function generateOppPlayers(rankNumbers: number[], serverId: number, roleId: string, update: LadderUpdateInter = {}) { + let min = rankNumbers[0], max = rankNumbers[rankNumbers.length - 1]; + let ranks = await getLadderMatchByRank(serverId, max, min); + + let oppPlayers: LadderOppPlayerReturn[] = [], oppPlayersSave: LadderOppPlayerInDB[] = []; + for(let rank of rankNumbers) { + let player = await generateOppPlayer(serverId, rank); + oppPlayersSave.push({ rank }); + oppPlayers.push(player); + } + await LadderMatchModel.updateByRoleId(roleId, { ...update, oppPlayers: oppPlayersSave }); + return oppPlayers +} + +async function generateOppPlayer(serverId: number, rank: number) { + let r = new Rank(REDIS_KEY.LADDER, { serverId }, false); + let result = new LadderOppPlayerReturn(rank); + if(rank < 3001) { + let players = await r.getRankByRange(rank, rank, false, true); + if(players.length > 0) { + let player = players[0]; + let defCe = await getLadderDefCe(player.roleId); + result.setByRedis(player, parseInt(`${defCe}`)); + } + } + if(!result.roleId) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); + result.setByRobot(dicLadderDifficultRatio); + } + return result; +} + +function randOppRankNumbers(myRank: number) { + let dicLadderMatch = getDicLadderMatchByMyRank(myRank); + if(!dicLadderMatch) return new Array(5).fill(3001); + + let beforeRanks = randomRank(true, myRank, dicLadderMatch.rangeBeforeMax, dicLadderMatch.rangeBeforeNum); + let afterRanks = randomRank(false, myRank, dicLadderMatch.rangeAfterMax, dicLadderMatch.rangeAfterNum); + + let topTen = getNumberArr(1, 10); + let ranks = [...topTen, ...beforeRanks, ...afterRanks]; + return uniqueArr(ranks.sort((a, b) => a - b)); +} + +export function uniqueArr(arr: T[]) { + return arr.filter( (item, index, arr) => { + //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 + return arr.indexOf(item) === index; + }); +} + +export function getNumberArr(from: number, to: number) { + let arr: number[] = []; + for(let i = from; i <= to; i++) { + if(i > 0) arr.push(i); + } + return arr; +} + +function randomRank(isBefore: boolean, myRank: number, range: number, len: number) { + if(range == 0 || len == 0) return []; + let arr: number[] = []; + let n = Math.floor(range / len); + for(let i = 0; i < len; i++) { + let rand = getRandValueByMinMax(n * i + 1, n * (i + 1) + 1, 0); // 因为这个的范围是[min, max),而想要的是 (n * i, n * (i - 1)] + if(rand) { + let ratio = isBefore? -1: 1; + let rank = myRank + ratio * rand; + if( rank > 3001) rank = 3002; + arr.push(rank); + } + } + return arr; +} + +export function checkRank(myRank: number, targetRank: number) { + let dicLadderMatch = getDicLadderMatchByMyRank(myRank); + if(!dicLadderMatch) { + if(myRank == 0 && targetRank == 3001) return true; + return false + } + if(myRank == targetRank) return false; + if(targetRank <= 10) { + return dicLadderMatch.topChallenge == 1; + } else { + if(myRank < targetRank) { // 向后打 + if(myRank + dicLadderMatch.rangeAfterMax < targetRank) return false; + } else { // 向前打 + if(myRank - dicLadderMatch.rangeBeforeMax > targetRank) return false; + } + } + + return true; +} + +export async function getLadderOppStatus(ladderData: LadderMatchType, targetRoleId: string, myRank: number, rank: number) { + if(ladderData.rank != myRank) return { status: LADDER_OPP_STATUS.MY_RANK_CHANGE }; + let isRobot = targetRoleId.startsWith('robot'); + + if(isRobot) { + if(rank <= 3000) { + let hisLadderData = await LadderMatchRecModel.checkByRank(ladderData.serverId, `robot${rank}`); + if(hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; + + let ladderMatch = await LadderMatchModel.isRankExist(ladderData.serverId, rank); + if(ladderMatch) { + return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + } + } + + return { status: LADDER_OPP_STATUS.BATTLE, isRobot: true }; + } else { + let ladderMatch = await LadderMatchModel.findByRoleId(targetRoleId); + if(!ladderMatch || ladderMatch.rank != rank) { + return { status: LADDER_OPP_STATUS.OPP_RANK_CHANGE }; + } + let hisLadderData = await LadderMatchModel.lock(ladderData.serverId, targetRoleId, rank); + if(!hisLadderData) return { status: LADDER_OPP_STATUS.OPP_IS_LOCKED }; + + return { status: LADDER_OPP_STATUS.BATTLE, isRobot: false, hisLadderData }; + } +} + +/** + * + * @param isRobot 是否是机器 + * @param isDefense 是攻还是守方 + * @param rank 排名 + * @param ladderData 需要populate过的ladderMatch表 + * @returns + */ +export async function generateInitRecInfo(isRobot: boolean, isDefense: boolean, rank: number, ladderData: LadderMatchType) { + if(isRobot) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); + let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); + let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId)||[]; + + let heroes: LadderOppPlayerHeroInfo[] = []; + for(let json of dicWarJson) { + if(json.relation == 2) { + let hero = new LadderOppPlayerHeroInfo(); + hero.setByWarJson(json); + heroes.push(hero); + } + } + let info = new LadderOppPlayerInfo(); + info.initByRobot(dicLadderDifficultRatio, heroes, isDefense); + return info; + } else { + let defCe = calculateDefCeByDefense(ladderData.defense); + let role = ladderData.role; + let heroes: LadderOppPlayerHeroInfo[] = []; + if(isDefense) { // 防守方可以将武将也存入,攻方要等出战 + let defenseHeroes = ladderData.defense?.heroes||[]; + for(let defenseHero of defenseHeroes) { + let hero = new LadderOppPlayerHeroInfo(); + let dbHero = defenseHero.hero; + hero.setByDefenseHero(dbHero); + if(dbHero && dbHero.artifact) { + let artifact = await ArtifactModel.findbySeqId(role.roleId, dbHero.artifact); + hero.setArtifact(artifact); + } + if(defenseHero.subHid) { + let subHero = await HeroModel.findByHidAndRole(defenseHero.subHid, role.roleId, 'hid skinId'); + hero.setSubHero(subHero) + } + heroes.push(hero); + } + } + let info = new LadderOppPlayerInfo(); + info.initByPlayer(rank, role, heroes, defCe, isDefense); + return info; + } +} + +function calculateDefCeByDefense(defense: LadderDefense) { + if(!defense) return 0; + let ce = 0; + for(let hero of defense.heroes) { + ce += hero.ce; + } + return ce; +} + +export async function ladderTimeWillout(battleCode: string, status: LADDER_STATUS) { + console.log('######### ladderTimeWillout') + if (status == LADDER_STATUS.BATTLE) { + let rec = await LadderMatchRecModel.findByBattleCode(battleCode); + await sendMessageToUserWithSuc(rec.roleId1, PUSH_ROUTE.LADDER_BATTLE_STOP, { battleCode }); + } +} + +export async function ladderTimeout(battleCode: string, status: LADDER_STATUS) { + console.log('######### ladderTimeout') + let rec = await LadderMatchRecModel.timeout(battleCode); + // console.log('##### rec.defenseInfo', rec.defenseInfo, rec.defenseInfo.isRobot, rec.defenseInfo.roleId) + if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId); + + if(status == LADDER_STATUS.CHECK) { + await sendMessageToUserWithSuc(rec.roleId1, PUSH_ROUTE.LADDER_CHECK_STOP, { battleCode }); + } +} + +/** + * 结算时候设置排行、发送推送、刷新对手、发送跑马灯 + * @param ladderMatch + * @param isAtk + * @returns + */ +export async function battleEndWhenChange(atkLadderMatch: LadderMatchType, defLadderMatch: LadderMatchType, needRefresh: boolean) { + await updateLadderRedis(atkLadderMatch); + await updateLadderRedis(defLadderMatch); + + if(atkLadderMatch) reportTAUserSet(TA_USERSET_TYPE.SET, atkLadderMatch.roleId, { ladder_rank: atkLadderMatch.rank }); + if(defLadderMatch) reportTAUserSet(TA_USERSET_TYPE.SET, defLadderMatch.roleId, { ladder_rank: defLadderMatch.rank }); + + await refreshOpp(defLadderMatch, needRefresh); + return await refreshOpp(atkLadderMatch, needRefresh); +} + +async function updateLadderRedis(ladderMatch: LadderMatchType) { + if(!ladderMatch) return; + // 更新redis + if(ladderMatch.rank > 0 && ladderMatch.rank < 3001) { + let r = new Rank(REDIS_KEY.LADDER, { serverId: ladderMatch.serverId }); + await r.setRankWithRoleInfo(ladderMatch.roleId, ladderMatch.rank, 0); + await saveLadderDefCeByData(ladderMatch.roleId, ladderMatch); + } +} + +async function refreshOpp(ladderMatch: LadderMatchType, needRefresh: boolean) { + if(!ladderMatch) return [] + // 刷新对手 + if(needRefresh) { + let oppPlayers = await refreshLadderEnemies(ladderMatch); + await sendMessageToUserWithSuc(ladderMatch.roleId, PUSH_ROUTE.LADDER_RANK_UPDATE, { + oldRank: ladderMatch.oldRank, + newRank: ladderMatch.rank, + oppPlayers + }); + return oppPlayers + } else { + return [] + } +} + +export async function ladderBattleEndReward(roleId: string, roleName: string, sid: string, rank: number, isSuccess: boolean, historyRank: number, num: number) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank); + if(!dicLadderDifficultRatio) return { battleGoods: [], breakGoods: [] }; + let warReward = new WarReward(roleId, roleName, sid, dicLadderDifficultRatio.gkId, isSuccess); + warReward.setLadderReward(dicLadderDifficultRatio.randomWinReward, true); + warReward.setLadderReward(dicLadderDifficultRatio.randomFailReward, false); + let battleGoods = await warReward.saveReward(num); + let breakRewards: RewardInter[] = []; + for(let i = historyRank - 1; i >= rank; i--) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(i); + breakRewards.push(...(dicLadderDifficultRatio?.onceReward||[])); + } + let breakGoods = breakRewards.length > 0? await addItems(roleId, roleName, sid, combineItems(breakRewards), ITEM_CHANGE_REASON.LADDER_BATTLE_REWARD): []; + return { battleGoods, breakGoods }; +} + +export function completeLadderRanks(ranks: RoleAndGuildRankInfo[], serverId: number) { + let result: RoleAndGuildRankInfo[] = []; + for(let i = 1; i <= 200; i++) { + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(i); + let { head, ce, spine, level } = dicLadderDifficultRatio; + let rank = ranks.find(cur => cur.rank == i); + if(rank) { + result.push(rank); + } else { + let rank = new RoleAndGuildRankInfo(i, 0); + rank.setByField(`robot${i}`, LADDER.LADDER_ROBOT_NAME, head, EXTERIOR.EXTERIOR_FACECASE, spine, level, 1, '', ce, ce, serverId ); + result.push(rank); + } + } + return result; +} + +export function completeRanks(ranks: RoleAndGuildRankInfo[]) { + let max = Math.max(...ranks.map(cur => cur.rank), 0); + if(max > 200) max = 200; + let result: RoleAndGuildRankInfo[] = []; + for(let i = 1; i <= max; i++) { + let rank = ranks.find(cur => cur.rank == i); + if(rank) { + result.push(rank); + } else { + let rank = new RoleAndGuildRankInfo(i, 0); + result.push(rank); + } + } + return result; +} + +export async function sendLadderDailyReward(serverId: number) { + let ranks = await getLadderMatchByRank(serverId, '+inf', '-inf'); + for(let { rank, roleId } of ranks) { + let dicRankReward = getLadderRankReward(rank); + if(dicRankReward && dicRankReward.reward && dicRankReward.reward.length > 0) { + await sendMailByContent(MAIL_TYPE.LADDER, roleId, { params: [`${rank}`], goods: dicRankReward.reward }); + } + } +} + +export async function getLadderOppDetailData(rec: LadderMatchRecType) { + let isRobot = rec.defenseInfo.isRobot; + let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rec.defenseInfo.oldRank); + let result = new LadderOppDetailReturn(rec); + if(isRobot) { + result.setByRobot(dicLadderDifficultRatio); + } else { + let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(rec.roleId2); + let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId); + let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId); + let artifactSeids = [], subHids: number[] = []; + for(let { hero, subHid } of hisLadderData.defense.heroes) { + let dbHero = hero; + if(dbHero) artifactSeids.push(dbHero.artifact); + if(subHid) subHids.push(subHid); + } + + let artifacts = await ArtifactModel.findbySeqIds(rec.roleId2, artifactSeids); + let subHeroes = await HeroModel.findByHidRange(subHids, rec.roleId2, 'hid skinId'); + result.setByPlayer(hisLadderData, dicWarJson, artifacts, subHeroes); + let attrByHid = await getHeroesAttributes(rec.roleId2); + for(let [hid, attribute] of attrByHid) { + result.setAttribute(hid, attribute.getAttributesToString()); + } + } + return result; +} + +export async function pushLadderIconShow(roleId: string, ladderIconShow:boolean) { + if (!roleId) return; + await pushIconShow(roleId, ladderIconShow); +} + +export async function getIsExistLadderDefense(roleId: string) { + let ladderData = await LadderMatchModel.findByRoleId(roleId); + if (!ladderData || !ladderData.defense || !ladderData.defense.heroes) return false; + return true; +} diff --git a/game-server/app/services/log/memoryLogService.ts b/game-server/app/services/log/memoryLogService.ts index 65e5bdef9..ecaf8082d 100644 --- a/game-server/app/services/log/memoryLogService.ts +++ b/game-server/app/services/log/memoryLogService.ts @@ -1,117 +1,117 @@ -import { pinus } from "pinus"; -import { GUILD_ACTIVITY_TYPE, MEMORY_LOG_TYPE } from "../../consts"; -import { ActivityInRemote } from "../../domain/activityField/activityField"; -import { MemComBtlTeam } from "../../domain/battleField/ComBattleTeamField"; -import { saveMemoryLog, saveMemoryLogs } from "../../pubUtils/logUtil"; -import { getGAIndexInPinus } from "../guildActivity/guildActivityService"; - -// 将内存打印下来 -export async function saveMemory(type: MEMORY_LOG_TYPE) { - switch (type) { - case MEMORY_LOG_TYPE.ACTIVITY: - await _saveActivityMemory(); - break; - case MEMORY_LOG_TYPE.PVP_SEASON: - await _savePvpSeasonMemory(); - break; - case MEMORY_LOG_TYPE.GA_INDEX: - await _saveGuildActivityIndexMemory(); - break; - case MEMORY_LOG_TYPE.COMBATTLE: - await _saveComBattleMemory(); - break; - } -} - -async function _saveActivityMemory() { - await pinus.app.rpc.activity.activityRemote.saveActivityMemory.broadcast(); -} - -// activity服 -export async function saveActivityMemory() { - await saveMemoryLogs(pinus.app.getServerId(), [ - { memoryLogField: 'activities', memoryData: treatActivities(pinus.app.get('activities')) }, - { memoryLogField: 'activityByServer', memoryData: treatActivityByServer(pinus.app.get('activityByServer')) }, - { memoryLogField: 'activityByType', memoryData: treatActivityType(pinus.app.get('activityByType')) }, - { memoryLogField: 'groupToServer', memoryData: treatGroupToServer(pinus.app.get('groupToServer')) }, - ]); -} - -function treatActivities(activities: Map = new Map()) { - let result: ActivityInRemote[] = []; - for(let [_, activity] of activities) { - result.push(activity); - } - return JSON.stringify(result); -} - -function treatActivityByServer(activityByServer: Map = new Map()) { - let result: { serverId: number, activityIds: number[] }[] = []; - for(let [ serverId, activityIds ] of activityByServer) { - result.push({ serverId, activityIds }); - } - return JSON.stringify(result); -} - -function treatActivityType(activityByType: Map> = new Map()) { - let result: { serverId: number, type: number, activityIds: number[] }[] = []; - for(let [ serverId, typeToActivity ] of activityByType) { - for(let [ type, activityIds ] of typeToActivity) { - result.push({ serverId, type, activityIds }); - } - } - return JSON.stringify(result); -} - -function treatGroupToServer(groupToServer: Map = new Map()) { - let result: { groupId: number, serverIds: number[] }[] = []; - for(let [groupId, serverIds] of groupToServer) { - result.push({ groupId, serverIds }); - } - return JSON.stringify(result); -} - -async function _savePvpSeasonMemory() { - await pinus.app.rpc.battle.battleRemote.savePvpSeasonMemory.broadcast(); - await pinus.app.rpc.connector.connectorRemote.savePvpSeasonMemory.broadcast(); -} - -export async function savePvpSeasonMemory() { - let data = { - pvpSeasonNum: pinus.app.get('pvpSeasonNum'), - pvpSeasonStartTime: pinus.app.get('pvpSeasonStartTime'), - pvpSeasonEndTime: pinus.app.get('pvpSeasonEndTime'), - pvpSeasonRewardTime: pinus.app.get('pvpSeasonRewardTime'), - pvpSettleSeasonNum: pinus.app.get('pvpSettleSeasonNum') - } - await saveMemoryLog(pinus.app.getServerId(), 'pvpSeason', JSON.stringify(data)); -} - -async function _saveGuildActivityIndexMemory() { - await pinus.app.rpc.guild.guildActivityRemote.saveGuildActivityIndexMemory.broadcast(); -} - -export async function saveGuildActivityIndexMemory() { - let data = { - gateActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY), - cityActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY), - raceActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY), - } - await saveMemoryLog(pinus.app.getServerId(), 'gaIndex', JSON.stringify(data)); -} - -async function _saveComBattleMemory() { - await pinus.app.rpc.comBattle.comBattleRemote.saveComBattleMemory.broadcast(); -} - -export async function saveComBattleMemory() { - await saveMemoryLog(pinus.app.getServerId(), 'comBattle', treatTeamMap(pinus.app.get('teamMap'))); -} - -function treatTeamMap(teamMap: Map = new Map()) { - let result: MemComBtlTeam[] = []; - for(let [_teamCode, team] of teamMap) { - result.push(team); - } - return JSON.stringify(result); -} \ No newline at end of file +import { pinus } from "pinus"; +import { GUILD_ACTIVITY_TYPE, MEMORY_LOG_TYPE } from "@consts"; +import { ActivityInRemote } from "@domain/activityField/activityField"; +import { MemComBtlTeam } from "@domain/battleField/ComBattleTeamField"; +import { saveMemoryLog, saveMemoryLogs } from "@pubUtils/logUtil"; +import { getGAIndexInPinus } from "../guildActivity/guildActivityService"; + +// 将内存打印下来 +export async function saveMemory(type: MEMORY_LOG_TYPE) { + switch (type) { + case MEMORY_LOG_TYPE.ACTIVITY: + await _saveActivityMemory(); + break; + case MEMORY_LOG_TYPE.PVP_SEASON: + await _savePvpSeasonMemory(); + break; + case MEMORY_LOG_TYPE.GA_INDEX: + await _saveGuildActivityIndexMemory(); + break; + case MEMORY_LOG_TYPE.COMBATTLE: + await _saveComBattleMemory(); + break; + } +} + +async function _saveActivityMemory() { + await pinus.app.rpc.activity.activityRemote.saveActivityMemory.broadcast(); +} + +// activity服 +export async function saveActivityMemory() { + await saveMemoryLogs(pinus.app.getServerId(), [ + { memoryLogField: 'activities', memoryData: treatActivities(pinus.app.get('activities')) }, + { memoryLogField: 'activityByServer', memoryData: treatActivityByServer(pinus.app.get('activityByServer')) }, + { memoryLogField: 'activityByType', memoryData: treatActivityType(pinus.app.get('activityByType')) }, + { memoryLogField: 'groupToServer', memoryData: treatGroupToServer(pinus.app.get('groupToServer')) }, + ]); +} + +function treatActivities(activities: Map = new Map()) { + let result: ActivityInRemote[] = []; + for(let [_, activity] of activities) { + result.push(activity); + } + return JSON.stringify(result); +} + +function treatActivityByServer(activityByServer: Map = new Map()) { + let result: { serverId: number, activityIds: number[] }[] = []; + for(let [ serverId, activityIds ] of activityByServer) { + result.push({ serverId, activityIds }); + } + return JSON.stringify(result); +} + +function treatActivityType(activityByType: Map> = new Map()) { + let result: { serverId: number, type: number, activityIds: number[] }[] = []; + for(let [ serverId, typeToActivity ] of activityByType) { + for(let [ type, activityIds ] of typeToActivity) { + result.push({ serverId, type, activityIds }); + } + } + return JSON.stringify(result); +} + +function treatGroupToServer(groupToServer: Map = new Map()) { + let result: { groupId: number, serverIds: number[] }[] = []; + for(let [groupId, serverIds] of groupToServer) { + result.push({ groupId, serverIds }); + } + return JSON.stringify(result); +} + +async function _savePvpSeasonMemory() { + await pinus.app.rpc.battle.battleRemote.savePvpSeasonMemory.broadcast(); + await pinus.app.rpc.connector.connectorRemote.savePvpSeasonMemory.broadcast(); +} + +export async function savePvpSeasonMemory() { + let data = { + pvpSeasonNum: pinus.app.get('pvpSeasonNum'), + pvpSeasonStartTime: pinus.app.get('pvpSeasonStartTime'), + pvpSeasonEndTime: pinus.app.get('pvpSeasonEndTime'), + pvpSeasonRewardTime: pinus.app.get('pvpSeasonRewardTime'), + pvpSettleSeasonNum: pinus.app.get('pvpSettleSeasonNum') + } + await saveMemoryLog(pinus.app.getServerId(), 'pvpSeason', JSON.stringify(data)); +} + +async function _saveGuildActivityIndexMemory() { + await pinus.app.rpc.guild.guildActivityRemote.saveGuildActivityIndexMemory.broadcast(); +} + +export async function saveGuildActivityIndexMemory() { + let data = { + gateActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY), + cityActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY), + raceActivity: getGAIndexInPinus(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY), + } + await saveMemoryLog(pinus.app.getServerId(), 'gaIndex', JSON.stringify(data)); +} + +async function _saveComBattleMemory() { + await pinus.app.rpc.comBattle.comBattleRemote.saveComBattleMemory.broadcast(); +} + +export async function saveComBattleMemory() { + await saveMemoryLog(pinus.app.getServerId(), 'comBattle', treatTeamMap(pinus.app.get('teamMap'))); +} + +function treatTeamMap(teamMap: Map = new Map()) { + let result: MemComBtlTeam[] = []; + for(let [_teamCode, team] of teamMap) { + result.push(team); + } + return JSON.stringify(result); +} diff --git a/game-server/app/services/mailService.ts b/game-server/app/services/mailService.ts index dbc02ddd8..268ed6f6f 100644 --- a/game-server/app/services/mailService.ts +++ b/game-server/app/services/mailService.ts @@ -1,396 +1,396 @@ -import { RewardInter, pushMail, mailData } from "../pubUtils/interface"; -import { MailModel, MailType } from "../db/Mail"; -import { GroupMailModel, GroupMailType } from "../db/GroupMail"; -import { ServerMailModel, ServerMailType } from '../db/ServerMail'; -import { getRoleOnlineInfo } from "./redisService"; -import { pinus } from "pinus"; -import { gameData } from "../pubUtils/data"; -import { getCurDay, nowSeconds } from '../pubUtils/timeUtil'; -import { STATUS } from '../consts/statusCode'; -import { genCode, resResult } from '../pubUtils/util'; -import { GM_MAIL_TYPE, ITID, MAIL_STATUS, MAIL_TIME_TYPE, MAIL_TYPE, PUSH_ROUTE, SEND_NAME, SEND_TITLE } from "../consts"; -import { MailParam } from '../domain/roleField/mail'; -import { GMMailType, GMMailModel, GMMailTypeParam } from "../db/GMMail"; -import { getGuildChannelSid, getWorldChannelSid } from "./chatChannelService"; -import { GMMailRecordModel } from "../db/GMMailRecord"; -import { BAG } from "../pubUtils/dicParam"; -import { GuildModel, GuildType } from "../db/Guild"; -import moment = require("moment"); -import { sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToUsersWithSuc } from "./pushService"; -import { GVGLeagueModel, GVGLeagueType } from "../db/GVGLeague"; - -/** - * 获取邮件信息 - * @param {String} roleId 玩家id - * @param {Number} serverId 服务器id - */ -export async function getMails(roleId: string, serverId: number) { - let mails = await MailModel.findByRoleId(roleId)||[]; - let groupMails = await GroupMailModel.findByRoleId(roleId)||[]; - let serverMails = await ServerMailModel.findByRoleId(roleId, serverId)||[]; - - let list = getMailInfos(roleId, mails, groupMails, serverMails); - list.sort((a, b) => a.sendTime - b.sendTime); - return list; -} - -/** - * 根据数据库数据,生成返回数据 - * @param {String} roleId 玩家id - * @param {MailType[]} mails 单人邮件 - * @param {GroupMailType[]} groupMails 多人邮件 - * @param {ServerMailType[]} serverMails 全服邮件 - */ -function getMailInfos(roleId: string, mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { - let list: MailParam[] = []; // 结果 - for(let mail of mails) { - list.push(new MailParam( GM_MAIL_TYPE.SINGLE, mail, roleId)); - } - for(let mail of groupMails) { - list.push(new MailParam(GM_MAIL_TYPE.GROUP, mail, roleId)); - } - for(let mail of serverMails) { - list.push(new MailParam(GM_MAIL_TYPE.SERVER, mail, roleId)); - } - return list; -} - -export async function sendMailByContent(contentId: MAIL_TYPE, hisRoleId: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, dontSendReward?: boolean) { - - let f = new SendMailFun(); - let code = f.setWithContentId(contentId, params); - if(dontSendReward) f.setMailHide(); - await f.createSingleMails(code, [hisRoleId]); - await f.pushToUsers(); -} - -export async function sendMailToGuildByContent(contentId: MAIL_TYPE, guildCode: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, guild?: GuildType) { - if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members'); - if(!guild) return false; - let f = new SendMailFun(); - let code = f.setWithContentId(contentId, params); - await f.createGroupMails(code, guild.members, guildCode); - await f.pushToUsers(); - return true; -} - -export async function sendMailToLeagueByContent(contentId: MAIL_TYPE, leagueCode: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, league?: GVGLeagueType, dontSendReward?: boolean) { - console.log('###### sendMailToLeagueByContent', dontSendReward) - if(!league) league = await GVGLeagueModel.findByCodeWithoutPopulate(leagueCode); - if(!league) return false; - let f = new SendMailFun(); - let code = f.setWithContentId(contentId, params); - if(dontSendReward) f.setMailHide(); - await f.createGroupMails(code, league.members.map(cur => cur.roleId), null, leagueCode); - await f.pushToUsers(); - return true; -} - -export async function sendMailToManyPlayerByContent(contentId: MAIL_TYPE, roleIds: string[], params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }) { - let f = new SendMailFun(); - let code = f.setWithContentId(contentId, params); - await f.createGroupMails(code, roleIds); - await f.pushToUsers(); - return true; -} - -export async function sendMailsByGmMail(gmmails: GMMailType[]) { - let f = new SendMailFun(); - for(let gmmail of gmmails) { - let { receivers, mailType, sendTimes } = gmmail; - let code = await f.setWithGmMail(gmmail); - if(!code) continue; - let mapTemp = f.getMailTemp(code); - - if(sendTimes.indexOf(mapTemp.sendTime) == -1 && checkCanSend(gmmail, mapTemp)) { - if(mailType == GM_MAIL_TYPE.SINGLE) { - await f.createSingleMails(code, receivers.map(cur => cur.roleId)); - } else if (mailType == GM_MAIL_TYPE.GROUP) { - await f.createGroupMails(code, receivers.map(cur => cur.roleId)); - } else if (mailType == GM_MAIL_TYPE.SERVER) { - await f.createServerMails(code, receivers.map(cur => cur.serverId)); - } - } - } - await f.pushToUsers(); -} - -function checkCanSend(gmmail: GMMailType, mapTemp: MailTemp ) { - let { circleStart, circleEnd, timeType } = gmmail; - if(timeType == MAIL_TIME_TYPE.CIRCLE) { - if(circleStart > mapTemp.sendTime || circleEnd < mapTemp.sendTime) return false; - } - return true; -} -class MailTemp { - public code: string; - public gmmail: GMMailTypeParam; - private contentId: MAIL_TYPE = MAIL_TYPE.SEND_MAIL; // 0-读GmMail,1以上读dicMail - private sendName: string = SEND_NAME; - private title: string = SEND_TITLE; - private content: string = ''; - private hasGoods: boolean = false; // 是否内含奖励 - private goods: RewardInter[] = []; // 发送的奖励 - public sendTime: number; - private endTime: number; - private isSp: boolean = false; - - // 从dicMail读取数据 - public setWithContentId(contentId: MAIL_TYPE, params: { sendName?: string, params?: string[], goods?: RewardInter[] }) { - this.code = genCode(8); - let dicMail = gameData.mail.get(contentId); - this.contentId = contentId; - this.sendTime = nowSeconds(); - this.endTime = this.sendTime + dicMail?.time||0; - this.content = this.getContent(dicMail.content, params.params); - if(dicMail.title) this.title = dicMail.title; - if(dicMail.sendName || params.sendName) this.sendName = params.sendName||dicMail.sendName; - - this.hasGoods = params.goods?.length > 0; - this.goods = params.goods||[]; - } - - public async setWithGmMail(gmmail: GMMailType) { - if(gmmail.timeType == MAIL_TIME_TYPE.IMMEDIATE) { - this.sendTime = nowSeconds(); - } else if (gmmail.timeType == MAIL_TIME_TYPE.DELAY) { - this.sendTime = gmmail.startTime; - } else if (gmmail.timeType == MAIL_TIME_TYPE.CIRCLE) { - let time = moment(moment().format('YYYY-MM-DD ' + gmmail.circleHour)).unix(); - if(time < nowSeconds()) { - if(gmmail.circleDay == 0) { - time += 86400; - } else { - let date = getCurDay(true); // 今天星期几 - if(date < gmmail.circleDay) { - time += (gmmail.circleDay - date) * 86400; - } else { - time += (7 + date - gmmail.circleDay) * 86400; - } - } - } - this.sendTime = time; - } - this.code = genCode(8); - this.gmmail = gmmail; - this.contentId = 0; - this.endTime = this.sendTime + gmmail.expire * 60 * 60; - this.sendName = gmmail.sendName; - this.title = gmmail.title; - this.content = gmmail.content; - this.hasGoods = gmmail.hasGoods; - this.goods = gmmail.goods; - this.isSp = gmmail.isSp; - return true; - } - - private getContent(content: string, params: string[] = []) { - if(!content) content = '%d'; - for(let p of params) { - content = content.replace(/%d/, p); - } - return content - } - - public getCreateMailParams() { - return { - contentId: this.contentId, - gmmailId: this.gmmail?._id, - sendTime: this.sendTime, - endTime: this.endTime, - goods: this.goods, - title: this.title, - sendName: this.sendName, - content: this.content, - hasGoods: this.hasGoods, - isSp: this.isSp, - } - } -} - -/** - * 发送邮件方法类 - */ -export class SendMailFun { - private mailTemps = new Map(); - private mails: MailType[] = []; - private groupMails: GroupMailType[] = []; - private serverMails: ServerMailType[] = []; - private hideMail = false; - - public getMailTemp(code: string) { - return this.mailTemps.get(code); - } - - public setMailHide() { - this.hideMail = true; - } - - // 从dicMail读取数据 - public setWithContentId(contentId: MAIL_TYPE, params: { sendName?: string, params?: string[], goods?: RewardInter[] }) { - let mailTemp = new MailTemp(); - mailTemp.setWithContentId(contentId, params); - this.mailTemps.set(mailTemp.code, mailTemp); - return mailTemp.code; - } - - // 从GMMail表读取数据 - public async setWithGmMail(gmmail: GMMailType) { - let mailTemp = new MailTemp(); - let canSet = mailTemp.setWithGmMail(gmmail); - if(!canSet) return false - this.mailTemps.set(mailTemp.code, mailTemp); - return mailTemp.code; - } - - // 生成单人邮件 - public async createSingleMails(code: string, roleIds: string[]) { - let mapTemp = this.mailTemps.get(code); - if(mapTemp) console.log('#### createSingleMails', mapTemp.getCreateMailParams()?.contentId, roleIds); - if(mapTemp.sendTime < nowSeconds()) return; - for(let roleId of roleIds) { - // console.log('#### createSingleMails this.hideMail', this.hideMail, this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE) - let originMail = await MailModel.addMail({ roleId, status: this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE, ...mapTemp.getCreateMailParams() }); - this.mails.push(originMail); - } - if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); - } - - // 生成多人邮件 - public async createGroupMails(code: string, roleIds: string[], guildCode?: string, leagueCode?: string) { - let mapTemp = this.mailTemps.get(code); - if(mapTemp.sendTime < nowSeconds()) return; - let roleStatus = roleIds.map(roleId => { - return { roleId, status: this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE } - }) - console.log('#### createGroupMails', this.hideMail, roleStatus) - let originMail = await GroupMailModel.addMail({ roleStatus, guildCode, leagueCode, ...mapTemp.getCreateMailParams() }); - if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); - this.groupMails.push(originMail); - } - - // 生成全服邮件 - public async createServerMails(code: string, serverIds: number[]) { - let mapTemp = this.mailTemps.get(code); - // console.log('###### createServerMails 1', code, this.mailTemps, mapTemp) - if(mapTemp.sendTime < nowSeconds()) return; - for(let serverId of serverIds) { - let originMail = await ServerMailModel.addMail({ serverId, ...mapTemp.getCreateMailParams() }); - this.serverMails.push(originMail); - } - if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); - } - - public async setMails(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { - this.mails.push(...mails); - this.groupMails.push(...groupMails); - this.serverMails.push(...serverMails); - } - - // 将存储的邮件发出 - public async pushToUsers(myRoleId?: string, mySid?: string) { - if(this.hideMail) return; - // 将可以发的邮件发出 - let pushByRoleId = new Map(); - let pushByGuildCode = new Map(); - let pushByServerId = new Map(); - - for(let mail of this.mails) { - if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { - let mailParam = new MailParam(GM_MAIL_TYPE.SINGLE, mail); - if(!pushByRoleId.has(mail.roleId)) pushByRoleId.set(mail.roleId, []); - pushByRoleId.get(mail.roleId).push(mailParam); - } - } - for(let mail of this.groupMails) { - if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { - let mailParam = new MailParam(GM_MAIL_TYPE.GROUP, mail); - if(!!mail.guildCode) { - if(!pushByGuildCode.has(mail.guildCode)) pushByGuildCode.set(mail.guildCode, []); - pushByGuildCode.get(mail.guildCode).push(mailParam); - } else { - for(let { roleId } of mail.roleStatus) { - if(!pushByRoleId.has(roleId)) pushByRoleId.set(roleId, []); - pushByRoleId.get(roleId).push(mailParam); - } - } - } - } - for(let mail of this.serverMails) { - if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { - let mailParam = new MailParam(GM_MAIL_TYPE.SERVER, mail); - if(!pushByServerId.has(mail.serverId)) pushByServerId.set(mail.serverId, []); - pushByServerId.get(mail.serverId).push(mailParam); - } - } - - for(let [roleId, mails ] of pushByRoleId) { - let uids = await this.getUids(roleId, myRoleId, mySid); - if(uids.length > 0 && mails.length > 0) { - sendMessageToUsersWithSuc(PUSH_ROUTE.MAILS_ADD, { mails }, uids); - } - } - - for(let [guildCode, mails] of pushByGuildCode) { - if(mails.length > 0) { - await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.MAILS_ADD, { mails }); - } - } - - for(let [serverId, mails] of pushByServerId) { - if( mails.length > 0) { - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.MAILS_ADD, { mails }, true); - } - } - - // 延时邮件,设置定时器 - pinus.app.rpc.systimer.systimerRemote.addMailsToSchedule.broadcast(this.mails, this.groupMails, this.serverMails); - } - - private async getUids(roleId: string, myRoleId?: string, mySid?: string) { - let uids: { uid: string, sid: string }[] = []; - let sid = ''; - if(roleId == myRoleId) { - sid = mySid; - } else { - let hisOnlineInfo = await getRoleOnlineInfo(roleId); - if(hisOnlineInfo.isOnline) { - sid = hisOnlineInfo.sid; - } - } - if(!!sid) { - uids.push({ uid: roleId, sid }); - } - return uids; - } - - public async saveRecord(createUid: number) { - for(let mail of this.mails) { - await GMMailRecordModel.createRecord(GM_MAIL_TYPE.SINGLE, mail, createUid); - } - for(let mail of this.groupMails) { - await GMMailRecordModel.createRecord(GM_MAIL_TYPE.GROUP, mail, createUid); - } - for(let mail of this.serverMails) { - await GMMailRecordModel.createRecord(GM_MAIL_TYPE.SERVER, mail, createUid); - } - } -} - -export function checkMailGoods(mail: MailType | GroupMailType | ServerMailType, jewelCount: number) { - let isEquipOver = false; - for (let good of mail.goods) { - let dicGoods = gameData.goods.get(good.id); - let dicItid = ITID.get(dicGoods.itid); - if (dicItid.table == 'jewel') { // 装备 - if (++jewelCount > BAG.BAG_EQUIP_UPLIMITED) { - isEquipOver = true; - break; - } - } - } - - return { - isEquipOver, jewelCount - } -} \ No newline at end of file +import { RewardInter, pushMail, mailData } from "@pubUtils/interface"; +import { MailModel, MailType } from "@db/Mail"; +import { GroupMailModel, GroupMailType } from "@db/GroupMail"; +import { ServerMailModel, ServerMailType } from '@db/ServerMail'; +import { getRoleOnlineInfo } from "./redisService"; +import { pinus } from "pinus"; +import { gameData } from "@pubUtils/data"; +import { getCurDay, nowSeconds } from '@pubUtils/timeUtil'; +import { STATUS } from '@consts/statusCode'; +import { genCode, resResult } from '@pubUtils/util'; +import { GM_MAIL_TYPE, ITID, MAIL_STATUS, MAIL_TIME_TYPE, MAIL_TYPE, PUSH_ROUTE, SEND_NAME, SEND_TITLE } from "@consts"; +import { MailParam } from '@domain/roleField/mail'; +import { GMMailType, GMMailModel, GMMailTypeParam } from "@db/GMMail"; +import { getGuildChannelSid, getWorldChannelSid } from "./chatChannelService"; +import { GMMailRecordModel } from "@db/GMMailRecord"; +import { BAG } from "@pubUtils/dicParam"; +import { GuildModel, GuildType } from "@db/Guild"; +import moment = require("moment"); +import { sendMessageToGuildWithSuc, sendMessageToServerWithSuc, sendMessageToUsersWithSuc } from "./pushService"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; + +/** + * 获取邮件信息 + * @param {String} roleId 玩家id + * @param {Number} serverId 服务器id + */ +export async function getMails(roleId: string, serverId: number) { + let mails = await MailModel.findByRoleId(roleId)||[]; + let groupMails = await GroupMailModel.findByRoleId(roleId)||[]; + let serverMails = await ServerMailModel.findByRoleId(roleId, serverId)||[]; + + let list = getMailInfos(roleId, mails, groupMails, serverMails); + list.sort((a, b) => a.sendTime - b.sendTime); + return list; +} + +/** + * 根据数据库数据,生成返回数据 + * @param {String} roleId 玩家id + * @param {MailType[]} mails 单人邮件 + * @param {GroupMailType[]} groupMails 多人邮件 + * @param {ServerMailType[]} serverMails 全服邮件 + */ +function getMailInfos(roleId: string, mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { + let list: MailParam[] = []; // 结果 + for(let mail of mails) { + list.push(new MailParam( GM_MAIL_TYPE.SINGLE, mail, roleId)); + } + for(let mail of groupMails) { + list.push(new MailParam(GM_MAIL_TYPE.GROUP, mail, roleId)); + } + for(let mail of serverMails) { + list.push(new MailParam(GM_MAIL_TYPE.SERVER, mail, roleId)); + } + return list; +} + +export async function sendMailByContent(contentId: MAIL_TYPE, hisRoleId: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, dontSendReward?: boolean) { + + let f = new SendMailFun(); + let code = f.setWithContentId(contentId, params); + if(dontSendReward) f.setMailHide(); + await f.createSingleMails(code, [hisRoleId]); + await f.pushToUsers(); +} + +export async function sendMailToGuildByContent(contentId: MAIL_TYPE, guildCode: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, guild?: GuildType) { + if(!guild) guild = await GuildModel.findByCode(guildCode, null, '+members'); + if(!guild) return false; + let f = new SendMailFun(); + let code = f.setWithContentId(contentId, params); + await f.createGroupMails(code, guild.members, guildCode); + await f.pushToUsers(); + return true; +} + +export async function sendMailToLeagueByContent(contentId: MAIL_TYPE, leagueCode: string, params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }, league?: GVGLeagueType, dontSendReward?: boolean) { + console.log('###### sendMailToLeagueByContent', dontSendReward) + if(!league) league = await GVGLeagueModel.findByCodeWithoutPopulate(leagueCode); + if(!league) return false; + let f = new SendMailFun(); + let code = f.setWithContentId(contentId, params); + if(dontSendReward) f.setMailHide(); + await f.createGroupMails(code, league.members.map(cur => cur.roleId), null, leagueCode); + await f.pushToUsers(); + return true; +} + +export async function sendMailToManyPlayerByContent(contentId: MAIL_TYPE, roleIds: string[], params: { sendName?: string, endTime?: number, params?: string[], goods?: RewardInter[] }) { + let f = new SendMailFun(); + let code = f.setWithContentId(contentId, params); + await f.createGroupMails(code, roleIds); + await f.pushToUsers(); + return true; +} + +export async function sendMailsByGmMail(gmmails: GMMailType[]) { + let f = new SendMailFun(); + for(let gmmail of gmmails) { + let { receivers, mailType, sendTimes } = gmmail; + let code = await f.setWithGmMail(gmmail); + if(!code) continue; + let mapTemp = f.getMailTemp(code); + + if(sendTimes.indexOf(mapTemp.sendTime) == -1 && checkCanSend(gmmail, mapTemp)) { + if(mailType == GM_MAIL_TYPE.SINGLE) { + await f.createSingleMails(code, receivers.map(cur => cur.roleId)); + } else if (mailType == GM_MAIL_TYPE.GROUP) { + await f.createGroupMails(code, receivers.map(cur => cur.roleId)); + } else if (mailType == GM_MAIL_TYPE.SERVER) { + await f.createServerMails(code, receivers.map(cur => cur.serverId)); + } + } + } + await f.pushToUsers(); +} + +function checkCanSend(gmmail: GMMailType, mapTemp: MailTemp ) { + let { circleStart, circleEnd, timeType } = gmmail; + if(timeType == MAIL_TIME_TYPE.CIRCLE) { + if(circleStart > mapTemp.sendTime || circleEnd < mapTemp.sendTime) return false; + } + return true; +} +class MailTemp { + public code: string; + public gmmail: GMMailTypeParam; + private contentId: MAIL_TYPE = MAIL_TYPE.SEND_MAIL; // 0-读GmMail,1以上读dicMail + private sendName: string = SEND_NAME; + private title: string = SEND_TITLE; + private content: string = ''; + private hasGoods: boolean = false; // 是否内含奖励 + private goods: RewardInter[] = []; // 发送的奖励 + public sendTime: number; + private endTime: number; + private isSp: boolean = false; + + // 从dicMail读取数据 + public setWithContentId(contentId: MAIL_TYPE, params: { sendName?: string, params?: string[], goods?: RewardInter[] }) { + this.code = genCode(8); + let dicMail = gameData.mail.get(contentId); + this.contentId = contentId; + this.sendTime = nowSeconds(); + this.endTime = this.sendTime + dicMail?.time||0; + this.content = this.getContent(dicMail.content, params.params); + if(dicMail.title) this.title = dicMail.title; + if(dicMail.sendName || params.sendName) this.sendName = params.sendName||dicMail.sendName; + + this.hasGoods = params.goods?.length > 0; + this.goods = params.goods||[]; + } + + public async setWithGmMail(gmmail: GMMailType) { + if(gmmail.timeType == MAIL_TIME_TYPE.IMMEDIATE) { + this.sendTime = nowSeconds(); + } else if (gmmail.timeType == MAIL_TIME_TYPE.DELAY) { + this.sendTime = gmmail.startTime; + } else if (gmmail.timeType == MAIL_TIME_TYPE.CIRCLE) { + let time = moment(moment().format('YYYY-MM-DD ' + gmmail.circleHour)).unix(); + if(time < nowSeconds()) { + if(gmmail.circleDay == 0) { + time += 86400; + } else { + let date = getCurDay(true); // 今天星期几 + if(date < gmmail.circleDay) { + time += (gmmail.circleDay - date) * 86400; + } else { + time += (7 + date - gmmail.circleDay) * 86400; + } + } + } + this.sendTime = time; + } + this.code = genCode(8); + this.gmmail = gmmail; + this.contentId = 0; + this.endTime = this.sendTime + gmmail.expire * 60 * 60; + this.sendName = gmmail.sendName; + this.title = gmmail.title; + this.content = gmmail.content; + this.hasGoods = gmmail.hasGoods; + this.goods = gmmail.goods; + this.isSp = gmmail.isSp; + return true; + } + + private getContent(content: string, params: string[] = []) { + if(!content) content = '%d'; + for(let p of params) { + content = content.replace(/%d/, p); + } + return content + } + + public getCreateMailParams() { + return { + contentId: this.contentId, + gmmailId: this.gmmail?._id, + sendTime: this.sendTime, + endTime: this.endTime, + goods: this.goods, + title: this.title, + sendName: this.sendName, + content: this.content, + hasGoods: this.hasGoods, + isSp: this.isSp, + } + } +} + +/** + * 发送邮件方法类 + */ +export class SendMailFun { + private mailTemps = new Map(); + private mails: MailType[] = []; + private groupMails: GroupMailType[] = []; + private serverMails: ServerMailType[] = []; + private hideMail = false; + + public getMailTemp(code: string) { + return this.mailTemps.get(code); + } + + public setMailHide() { + this.hideMail = true; + } + + // 从dicMail读取数据 + public setWithContentId(contentId: MAIL_TYPE, params: { sendName?: string, params?: string[], goods?: RewardInter[] }) { + let mailTemp = new MailTemp(); + mailTemp.setWithContentId(contentId, params); + this.mailTemps.set(mailTemp.code, mailTemp); + return mailTemp.code; + } + + // 从GMMail表读取数据 + public async setWithGmMail(gmmail: GMMailType) { + let mailTemp = new MailTemp(); + let canSet = mailTemp.setWithGmMail(gmmail); + if(!canSet) return false + this.mailTemps.set(mailTemp.code, mailTemp); + return mailTemp.code; + } + + // 生成单人邮件 + public async createSingleMails(code: string, roleIds: string[]) { + let mapTemp = this.mailTemps.get(code); + if(mapTemp) console.log('#### createSingleMails', mapTemp.getCreateMailParams()?.contentId, roleIds); + if(mapTemp.sendTime < nowSeconds()) return; + for(let roleId of roleIds) { + // console.log('#### createSingleMails this.hideMail', this.hideMail, this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE) + let originMail = await MailModel.addMail({ roleId, status: this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE, ...mapTemp.getCreateMailParams() }); + this.mails.push(originMail); + } + if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); + } + + // 生成多人邮件 + public async createGroupMails(code: string, roleIds: string[], guildCode?: string, leagueCode?: string) { + let mapTemp = this.mailTemps.get(code); + if(mapTemp.sendTime < nowSeconds()) return; + let roleStatus = roleIds.map(roleId => { + return { roleId, status: this.hideMail? MAIL_STATUS.HIDE: MAIL_STATUS.CREATE } + }) + console.log('#### createGroupMails', this.hideMail, roleStatus) + let originMail = await GroupMailModel.addMail({ roleStatus, guildCode, leagueCode, ...mapTemp.getCreateMailParams() }); + if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); + this.groupMails.push(originMail); + } + + // 生成全服邮件 + public async createServerMails(code: string, serverIds: number[]) { + let mapTemp = this.mailTemps.get(code); + // console.log('###### createServerMails 1', code, this.mailTemps, mapTemp) + if(mapTemp.sendTime < nowSeconds()) return; + for(let serverId of serverIds) { + let originMail = await ServerMailModel.addMail({ serverId, ...mapTemp.getCreateMailParams() }); + this.serverMails.push(originMail); + } + if(mapTemp.gmmail) await GMMailModel.sendMail(mapTemp.gmmail._id, mapTemp.sendTime); + } + + public async setMails(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { + this.mails.push(...mails); + this.groupMails.push(...groupMails); + this.serverMails.push(...serverMails); + } + + // 将存储的邮件发出 + public async pushToUsers(myRoleId?: string, mySid?: string) { + if(this.hideMail) return; + // 将可以发的邮件发出 + let pushByRoleId = new Map(); + let pushByGuildCode = new Map(); + let pushByServerId = new Map(); + + for(let mail of this.mails) { + if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { + let mailParam = new MailParam(GM_MAIL_TYPE.SINGLE, mail); + if(!pushByRoleId.has(mail.roleId)) pushByRoleId.set(mail.roleId, []); + pushByRoleId.get(mail.roleId).push(mailParam); + } + } + for(let mail of this.groupMails) { + if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { + let mailParam = new MailParam(GM_MAIL_TYPE.GROUP, mail); + if(!!mail.guildCode) { + if(!pushByGuildCode.has(mail.guildCode)) pushByGuildCode.set(mail.guildCode, []); + pushByGuildCode.get(mail.guildCode).push(mailParam); + } else { + for(let { roleId } of mail.roleStatus) { + if(!pushByRoleId.has(roleId)) pushByRoleId.set(roleId, []); + pushByRoleId.get(roleId).push(mailParam); + } + } + } + } + for(let mail of this.serverMails) { + if(mail.sendTime <= nowSeconds() && mail.endTime > nowSeconds()) { + let mailParam = new MailParam(GM_MAIL_TYPE.SERVER, mail); + if(!pushByServerId.has(mail.serverId)) pushByServerId.set(mail.serverId, []); + pushByServerId.get(mail.serverId).push(mailParam); + } + } + + for(let [roleId, mails ] of pushByRoleId) { + let uids = await this.getUids(roleId, myRoleId, mySid); + if(uids.length > 0 && mails.length > 0) { + sendMessageToUsersWithSuc(PUSH_ROUTE.MAILS_ADD, { mails }, uids); + } + } + + for(let [guildCode, mails] of pushByGuildCode) { + if(mails.length > 0) { + await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.MAILS_ADD, { mails }); + } + } + + for(let [serverId, mails] of pushByServerId) { + if( mails.length > 0) { + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.MAILS_ADD, { mails }, true); + } + } + + // 延时邮件,设置定时器 + pinus.app.rpc.systimer.systimerRemote.addMailsToSchedule.broadcast(this.mails, this.groupMails, this.serverMails); + } + + private async getUids(roleId: string, myRoleId?: string, mySid?: string) { + let uids: { uid: string, sid: string }[] = []; + let sid = ''; + if(roleId == myRoleId) { + sid = mySid; + } else { + let hisOnlineInfo = await getRoleOnlineInfo(roleId); + if(hisOnlineInfo.isOnline) { + sid = hisOnlineInfo.sid; + } + } + if(!!sid) { + uids.push({ uid: roleId, sid }); + } + return uids; + } + + public async saveRecord(createUid: number) { + for(let mail of this.mails) { + await GMMailRecordModel.createRecord(GM_MAIL_TYPE.SINGLE, mail, createUid); + } + for(let mail of this.groupMails) { + await GMMailRecordModel.createRecord(GM_MAIL_TYPE.GROUP, mail, createUid); + } + for(let mail of this.serverMails) { + await GMMailRecordModel.createRecord(GM_MAIL_TYPE.SERVER, mail, createUid); + } + } +} + +export function checkMailGoods(mail: MailType | GroupMailType | ServerMailType, jewelCount: number) { + let isEquipOver = false; + for (let good of mail.goods) { + let dicGoods = gameData.goods.get(good.id); + let dicItid = ITID.get(dicGoods.itid); + if (dicItid.table == 'jewel') { // 装备 + if (++jewelCount > BAG.BAG_EQUIP_UPLIMITED) { + isEquipOver = true; + break; + } + } + } + + return { + isEquipOver, jewelCount + } +} diff --git a/game-server/app/services/memoryCache/activityData.ts b/game-server/app/services/memoryCache/activityData.ts index 3d7458c86..d151b787a 100644 --- a/game-server/app/services/memoryCache/activityData.ts +++ b/game-server/app/services/memoryCache/activityData.ts @@ -1,178 +1,178 @@ -import { pinus, } from 'pinus'; -import { ActivityModel } from '../../db/Activity'; -import { ActivityInRemote } from '../../domain/activityField/activityField'; -import { ActivityGroupModel } from '../../db/ActivityGroup'; - -const activityByServer: Map = new Map(); // serverId => activityId[]; -const activities: Map = new Map(); // activityId => activity -const activityByType: Map> = new Map(); // serverId => type => activityId[]; -const groupToServer: Map = new Map(); // group => serverId[]; - -export function clearData() { - activityByServer.clear(); - activities.clear(); - activityByType.clear(); - groupToServer.clear(); -} - -function updateActivityByType(_activityByType: Map>) { - activityByType.clear(); - for(let [serverId, map] of _activityByType) { - activityByType.set(serverId, map); - } - pinus.app.set('activityByType', activityByType); -} - -function updateActivityByServer(_activityByServer: Map) { - activityByServer.clear(); - for(let [serverId, arr] of _activityByServer) { - activityByServer.set(serverId, arr); - } - pinus.app.set('activityByServer', activityByServer); -} - -export async function loadActivities() { - clearData(); - let activityGroup = await ActivityGroupModel.findAllActivityGroup(); - for(let { groupId, serverIds } of activityGroup) { - for(let serverId of serverIds) { - if(!groupToServer.has(groupId)) { - groupToServer.set(groupId, []); - } - groupToServer.get(groupId).push(serverId); - } - } - - let activityDb = await ActivityModel.findOpenAndComingActivityes(); - let activityIds: number[] = []; - for(let activity of activityDb) { - activities.set(activity.activityId, new ActivityInRemote(activity)); - activityIds.push(activity.activityId); - } - setActivityTypeAndServer(); - - pinus.app.set('activityByServer', activityByServer); - pinus.app.set('activityByType', activityByType); - pinus.app.set('activities', activities); - pinus.app.set('groupToServer', groupToServer); -} - -export async function setActivityTypeAndServer() { - let _activityByServer: Map = new Map(); // serverId => activityId[]; - let _activityByType: Map> = new Map(); - - for(let [_, activity] of activities) { - let servers = groupToServer.get(activity.groupId)||[]; - for(let serverId of servers) { - if(!_activityByServer.has(serverId)) { - _activityByServer.set(serverId, []); - } - _activityByServer.get(serverId).push(activity.activityId); - - if(!_activityByType.has(serverId)) { - _activityByType.set(serverId, new Map()); - } - if(!_activityByType.get(serverId).has(activity.type)) { - _activityByType.get(serverId).set(activity.type, []); - } - _activityByType.get(serverId).get(activity.type).push(activity.activityId); - } - } - updateActivityByServer(_activityByServer); - updateActivityByType(_activityByType); - - -} - -export function updateActivities(activityDb: ActivityInRemote[]) { - // console.log('******* activities', activities) - let activityIds: number[] = []; - for(let activity of activityDb) { - activities.set(activity.activityId, activity); - activityIds.push(activity.activityId); - } - setActivityTypeAndServer(); -} - -export function deleteActivities(activityIds: number[]) { - - for(let activityId of activityIds) { - activities.delete(activityId); - } - setActivityTypeAndServer(); -} - -export function saveGroupToServer(groupIds: number[], serverIds: number[]) { - for(let groupId of groupIds) { - groupToServer.set(groupId, serverIds); - } - setActivityTypeAndServer(); -} - -export function addServerToGroup(groupIds: number[], serverIds: number[]) { - for(let groupId of groupIds) { - - if(!groupToServer.has(groupId)) { - groupToServer.set(groupId, []); - } - for(let serverId of serverIds) { - let arr = groupToServer.get(groupId)||[]; - if(arr.indexOf(serverId) == -1) { - groupToServer.get(groupId).push(serverId); - } - } - } - setActivityTypeAndServer(); -} - -export function saveActivitiesToGroup(groupId: number, activityDb: number[]) { - for(let activityId of activityDb) { - if(activities.get(activityId)) { - activities.get(activityId).groupId = groupId; - } - } - setActivityTypeAndServer(); -} - -export function _getActivityById(activityId: number) { - return activities?.get(activityId); -} - -export function _getActivitiesByType(serverId: number, type: number) { - let activityByTypeData = activityByType?.get(serverId)?.get(type)??[]; - let activities: Map = pinus.app.get('activities'); - let result: ActivityInRemote[] = []; - for(let activityId of activityByTypeData) { - let activity = activities.get(activityId); - if(activity && activity.isEnable) { - result.push(activity); - } - } - return result; -} - -export function _getActivitiesByServerId(serverId: number) { - let activityByServerId = activityByServer?.get(serverId)||[] - let activities: Map = pinus.app.get('activities'); - let result: ActivityInRemote[] = []; - for(let activityId of activityByServerId) { - let activity = activities.get(activityId); - if(activity && activity.isEnable) { - result.push(activity); - } - } - return result; -} - -export function _getActivities() { - try { - // console.log('***** activities', activities); - let result: ActivityInRemote[] = []; - for(let [_, activity] of activities) { - result.push(activity); - } - return result; - } catch(e) { - console.log('******** activity e', e) - } -} +import { pinus, } from 'pinus'; +import { ActivityModel } from '@db/Activity'; +import { ActivityInRemote } from '@domain/activityField/activityField'; +import { ActivityGroupModel } from '@db/ActivityGroup'; + +const activityByServer: Map = new Map(); // serverId => activityId[]; +const activities: Map = new Map(); // activityId => activity +const activityByType: Map> = new Map(); // serverId => type => activityId[]; +const groupToServer: Map = new Map(); // group => serverId[]; + +export function clearData() { + activityByServer.clear(); + activities.clear(); + activityByType.clear(); + groupToServer.clear(); +} + +function updateActivityByType(_activityByType: Map>) { + activityByType.clear(); + for(let [serverId, map] of _activityByType) { + activityByType.set(serverId, map); + } + pinus.app.set('activityByType', activityByType); +} + +function updateActivityByServer(_activityByServer: Map) { + activityByServer.clear(); + for(let [serverId, arr] of _activityByServer) { + activityByServer.set(serverId, arr); + } + pinus.app.set('activityByServer', activityByServer); +} + +export async function loadActivities() { + clearData(); + let activityGroup = await ActivityGroupModel.findAllActivityGroup(); + for(let { groupId, serverIds } of activityGroup) { + for(let serverId of serverIds) { + if(!groupToServer.has(groupId)) { + groupToServer.set(groupId, []); + } + groupToServer.get(groupId).push(serverId); + } + } + + let activityDb = await ActivityModel.findOpenAndComingActivityes(); + let activityIds: number[] = []; + for(let activity of activityDb) { + activities.set(activity.activityId, new ActivityInRemote(activity)); + activityIds.push(activity.activityId); + } + setActivityTypeAndServer(); + + pinus.app.set('activityByServer', activityByServer); + pinus.app.set('activityByType', activityByType); + pinus.app.set('activities', activities); + pinus.app.set('groupToServer', groupToServer); +} + +export async function setActivityTypeAndServer() { + let _activityByServer: Map = new Map(); // serverId => activityId[]; + let _activityByType: Map> = new Map(); + + for(let [_, activity] of activities) { + let servers = groupToServer.get(activity.groupId)||[]; + for(let serverId of servers) { + if(!_activityByServer.has(serverId)) { + _activityByServer.set(serverId, []); + } + _activityByServer.get(serverId).push(activity.activityId); + + if(!_activityByType.has(serverId)) { + _activityByType.set(serverId, new Map()); + } + if(!_activityByType.get(serverId).has(activity.type)) { + _activityByType.get(serverId).set(activity.type, []); + } + _activityByType.get(serverId).get(activity.type).push(activity.activityId); + } + } + updateActivityByServer(_activityByServer); + updateActivityByType(_activityByType); + + +} + +export function updateActivities(activityDb: ActivityInRemote[]) { + // console.log('******* activities', activities) + let activityIds: number[] = []; + for(let activity of activityDb) { + activities.set(activity.activityId, activity); + activityIds.push(activity.activityId); + } + setActivityTypeAndServer(); +} + +export function deleteActivities(activityIds: number[]) { + + for(let activityId of activityIds) { + activities.delete(activityId); + } + setActivityTypeAndServer(); +} + +export function saveGroupToServer(groupIds: number[], serverIds: number[]) { + for(let groupId of groupIds) { + groupToServer.set(groupId, serverIds); + } + setActivityTypeAndServer(); +} + +export function addServerToGroup(groupIds: number[], serverIds: number[]) { + for(let groupId of groupIds) { + + if(!groupToServer.has(groupId)) { + groupToServer.set(groupId, []); + } + for(let serverId of serverIds) { + let arr = groupToServer.get(groupId)||[]; + if(arr.indexOf(serverId) == -1) { + groupToServer.get(groupId).push(serverId); + } + } + } + setActivityTypeAndServer(); +} + +export function saveActivitiesToGroup(groupId: number, activityDb: number[]) { + for(let activityId of activityDb) { + if(activities.get(activityId)) { + activities.get(activityId).groupId = groupId; + } + } + setActivityTypeAndServer(); +} + +export function _getActivityById(activityId: number) { + return activities?.get(activityId); +} + +export function _getActivitiesByType(serverId: number, type: number) { + let activityByTypeData = activityByType?.get(serverId)?.get(type)??[]; + let activities: Map = pinus.app.get('activities'); + let result: ActivityInRemote[] = []; + for(let activityId of activityByTypeData) { + let activity = activities.get(activityId); + if(activity && activity.isEnable) { + result.push(activity); + } + } + return result; +} + +export function _getActivitiesByServerId(serverId: number) { + let activityByServerId = activityByServer?.get(serverId)||[] + let activities: Map = pinus.app.get('activities'); + let result: ActivityInRemote[] = []; + for(let activityId of activityByServerId) { + let activity = activities.get(activityId); + if(activity && activity.isEnable) { + result.push(activity); + } + } + return result; +} + +export function _getActivities() { + try { + // console.log('***** activities', activities); + let result: ActivityInRemote[] = []; + for(let [_, activity] of activities) { + result.push(activity); + } + return result; + } catch(e) { + console.log('******** activity e', e) + } +} diff --git a/game-server/app/services/memoryCache/auctionData.ts b/game-server/app/services/memoryCache/auctionData.ts index adc85f025..831843bbd 100644 --- a/game-server/app/services/memoryCache/auctionData.ts +++ b/game-server/app/services/memoryCache/auctionData.ts @@ -1,21 +1,21 @@ -let auctionTimer = new Map(); - -export function getLotTimer(code: string) { - return auctionTimer.get(code) -} - -export function setLotTimer(code: string, timer: NodeJS.Timer) { - if(auctionTimer.has(code)) { - let originTimer = auctionTimer.get(code); - if(originTimer) clearTimeout(originTimer); - } - auctionTimer.set(code, timer); -} - -export function clearLotTimer(code: string) { - let timer = getLotTimer(code); - if (timer) { - clearTimeout(timer); - auctionTimer.delete(code) - } -} \ No newline at end of file +let auctionTimer = new Map(); + +export function getLotTimer(code: string) { + return auctionTimer.get(code) +} + +export function setLotTimer(code: string, timer: any) { + if(auctionTimer.has(code)) { + let originTimer = auctionTimer.get(code); + if(originTimer) clearTimeout(originTimer); + } + auctionTimer.set(code, timer); +} + +export function clearLotTimer(code: string) { + let timer = getLotTimer(code); + if (timer) { + clearTimeout(timer); + auctionTimer.delete(code) + } +} diff --git a/game-server/app/services/memoryCache/comBattleData.ts b/game-server/app/services/memoryCache/comBattleData.ts index 9d43f6070..b5c2640df 100644 --- a/game-server/app/services/memoryCache/comBattleData.ts +++ b/game-server/app/services/memoryCache/comBattleData.ts @@ -1,57 +1,57 @@ -import { pinus } from "pinus"; -import { MemComBtlTeam } from "../../domain/battleField/ComBattleTeamField"; - -let teamMap = new Map(); -let teamDisTimer = new Map(); -let robotHurtTimer = new Map(); - - -export function addComTeam(teamCode: string, team: MemComBtlTeam) { - teamMap.set(teamCode, team); - pinus.app.set('teamMap', teamMap); - return teamMap -} - -export function getTeamMap() { - return teamMap; -} - -export function getComTeamByCode(teamCode: string) { - return teamMap.get(teamCode); -} - -export function deleteComBattle(teamCode: string) { - let rmSt = teamMap.delete(teamCode); - return rmSt -} - -export function getComTeamTimerByCode(teamCode: string) { - return teamDisTimer.get(teamCode) -} - -export function setComTeamTimer(teamCode: string, timer: NodeJS.Timer) { - teamDisTimer.set(teamCode, timer); - pinus.app.set('teamDisTimer', teamDisTimer); -} - -export function clearComBtlTimer(teamCode: string) { - let timer = getComTeamTimerByCode(teamCode); - if (timer) { - clearTimeout(timer); - teamDisTimer.delete(teamCode) - } - pinus.app.set('teamDisTimer', teamDisTimer); -} - -export function getRobotHurtTimer(teamCode: string, roleId: string) { - const timerKey = `${teamCode}_${roleId}`; - return robotHurtTimer.get(timerKey); -} - -export function setRobotHurtTimerIfNotExist(teamCode: string, roleId: string, robotTimer: NodeJS.Timer) { - const timerKey = `${teamCode}_${roleId}`; - if(!robotHurtTimer.has(timerKey)) { - robotHurtTimer.set(timerKey, robotTimer); - pinus.app.set('robotHurtTimer', robotHurtTimer); - } -} \ No newline at end of file +import { pinus } from "pinus"; +import { MemComBtlTeam } from "@domain/battleField/ComBattleTeamField"; + +let teamMap = new Map(); +let teamDisTimer = new Map(); +let robotHurtTimer = new Map(); + + +export function addComTeam(teamCode: string, team: MemComBtlTeam) { + teamMap.set(teamCode, team); + pinus.app.set('teamMap', teamMap); + return teamMap +} + +export function getTeamMap() { + return teamMap; +} + +export function getComTeamByCode(teamCode: string) { + return teamMap.get(teamCode); +} + +export function deleteComBattle(teamCode: string) { + let rmSt = teamMap.delete(teamCode); + return rmSt +} + +export function getComTeamTimerByCode(teamCode: string) { + return teamDisTimer.get(teamCode) +} + +export function setComTeamTimer(teamCode: string, timer: any) { + teamDisTimer.set(teamCode, timer); + pinus.app.set('teamDisTimer', teamDisTimer); +} + +export function clearComBtlTimer(teamCode: string) { + let timer = getComTeamTimerByCode(teamCode); + if (timer) { + clearTimeout(timer); + teamDisTimer.delete(teamCode) + } + pinus.app.set('teamDisTimer', teamDisTimer); +} + +export function getRobotHurtTimer(teamCode: string, roleId: string) { + const timerKey = `${teamCode}_${roleId}`; + return robotHurtTimer.get(timerKey); +} + +export function setRobotHurtTimerIfNotExist(teamCode: string, roleId: string, robotTimer: any) { + const timerKey = `${teamCode}_${roleId}`; + if(!robotHurtTimer.has(timerKey)) { + robotHurtTimer.set(timerKey, robotTimer); + pinus.app.set('robotHurtTimer', robotHurtTimer); + } +} diff --git a/game-server/app/services/memoryCache/guildActivityData.ts b/game-server/app/services/memoryCache/guildActivityData.ts index 7ce0e8f9a..7822a7bb3 100644 --- a/game-server/app/services/memoryCache/guildActivityData.ts +++ b/game-server/app/services/memoryCache/guildActivityData.ts @@ -1,38 +1,38 @@ -import { pinus } from "pinus"; -import { CityActivityObject } from "../guildActivity/cityActivityObj"; -import { GateActivityObject } from "../guildActivity/gateActivityObj"; -import { RaceActivityObject } from "../guildActivity/raceActivityObj"; - -let gateActivityObj: GateActivityObject = null; -let cityActivityObj: CityActivityObject = null; -let raceActivityObj: RaceActivityObject = null; - -export function getGateActivityObj() { - if (!gateActivityObj) { - gateActivityObj = new GateActivityObject(); - pinus.app.set('gateActivityObj', gateActivityObj); - } - return gateActivityObj; -} - -export function getCityActivityObj() { - if (!cityActivityObj) { - cityActivityObj = new CityActivityObject(); - pinus.app.set('cityActivityObj', cityActivityObj); - } - return cityActivityObj; -} - -export function getRaceActivityObj() { - if (!raceActivityObj) { - raceActivityObj = new RaceActivityObject(); - pinus.app.set('raceActivityObj', raceActivityObj); - } - return raceActivityObj; -} - -export function clearActivityObj() { - gateActivityObj = undefined; - cityActivityObj = undefined; - raceActivityObj = undefined; -} \ No newline at end of file +import { pinus } from "pinus"; +import { CityActivityObject } from "../guildActivity/cityActivityObj"; +import { GateActivityObject } from "../guildActivity/gateActivityObj"; +import { RaceActivityObject } from "../guildActivity/raceActivityObj"; + +let gateActivityObj: GateActivityObject = null; +let cityActivityObj: CityActivityObject = null; +let raceActivityObj: RaceActivityObject = null; + +export function getGateActivityObj() { + if (!gateActivityObj) { + gateActivityObj = new GateActivityObject(); + pinus.app.set('gateActivityObj', gateActivityObj); + } + return gateActivityObj; +} + +export function getCityActivityObj() { + if (!cityActivityObj) { + cityActivityObj = new CityActivityObject(); + pinus.app.set('cityActivityObj', cityActivityObj); + } + return cityActivityObj; +} + +export function getRaceActivityObj() { + if (!raceActivityObj) { + raceActivityObj = new RaceActivityObject(); + pinus.app.set('raceActivityObj', raceActivityObj); + } + return raceActivityObj; +} + +export function clearActivityObj() { + gateActivityObj = undefined; + cityActivityObj = undefined; + raceActivityObj = undefined; +} diff --git a/game-server/app/services/memoryCache/gvgBattleData.ts b/game-server/app/services/memoryCache/gvgBattleData.ts index d6a8ae35e..a5dc2f7f3 100644 --- a/game-server/app/services/memoryCache/gvgBattleData.ts +++ b/game-server/app/services/memoryCache/gvgBattleData.ts @@ -1,21 +1,21 @@ -import { pinus } from "pinus"; -import { GVGBattleData } from "../gvg/gvgBattleMemory"; - -// 积分点占领情况,groupId_serverType_cityId -> GVGBattleData -const gvgBattleMap: Map = new Map(); - -export function getGVGBattleData(groupKey: string) { - if(!gvgBattleMap.has(groupKey)) { - gvgBattleMap.set(groupKey, new GVGBattleData(groupKey)); - pinus.app.set('gvgBattleMap', gvgBattleMap); - } - return gvgBattleMap.get(groupKey); -} - -export function getGVGBattleMap() { - return gvgBattleMap; -} - -export function clearBattleMemory() { - gvgBattleMap.clear(); -} +import { pinus } from "pinus"; +import { GVGBattleData } from "../gvg/gvgBattleMemory"; + +// 积分点占领情况,groupId_serverType_cityId -> GVGBattleData +const gvgBattleMap: Map = new Map(); + +export function getGVGBattleData(groupKey: string) { + if(!gvgBattleMap.has(groupKey)) { + gvgBattleMap.set(groupKey, new GVGBattleData(groupKey)); + pinus.app.set('gvgBattleMap', gvgBattleMap); + } + return gvgBattleMap.get(groupKey); +} + +export function getGVGBattleMap() { + return gvgBattleMap; +} + +export function clearBattleMemory() { + gvgBattleMap.clear(); +} diff --git a/game-server/app/services/memoryCache/hiddenData.ts b/game-server/app/services/memoryCache/hiddenData.ts index b343d04e4..f8c6d1623 100644 --- a/game-server/app/services/memoryCache/hiddenData.ts +++ b/game-server/app/services/memoryCache/hiddenData.ts @@ -1,17 +1,17 @@ -import { pinus } from "pinus"; - - -export function setHiddenData(heroes: number[], goods: number[], refTime: number) { - pinus.app.set('hiddenHeroees', heroes||[]); - pinus.app.set('hiddenGoods', goods||[]); - pinus.app.set('hiddenRefTime', refTime||0); -} - -export function getHiddenData() { - let heroes: number[] = pinus.app.get('hiddenHeroees')||[]; - let goods: number[] = pinus.app.get('hiddenGoods')||[]; - let refTime = pinus.app.get('hiddenRefTime')||0; - return { - refTime, heroes, items: goods - } -} \ No newline at end of file +import { pinus } from "pinus"; + + +export function setHiddenData(heroes: number[], goods: number[], refTime: number) { + pinus.app.set('hiddenHeroees', heroes||[]); + pinus.app.set('hiddenGoods', goods||[]); + pinus.app.set('hiddenRefTime', refTime||0); +} + +export function getHiddenData() { + let heroes: number[] = pinus.app.get('hiddenHeroees')||[]; + let goods: number[] = pinus.app.get('hiddenGoods')||[]; + let refTime = pinus.app.get('hiddenRefTime')||0; + return { + refTime, heroes, items: goods + } +} diff --git a/game-server/app/services/normalBattleService.ts b/game-server/app/services/normalBattleService.ts index a0495270a..1609109f0 100644 --- a/game-server/app/services/normalBattleService.ts +++ b/game-server/app/services/normalBattleService.ts @@ -1,281 +1,281 @@ - -import { HeroModel, HeroType } from '../db/Hero'; -import Role, { RoleModel, RoleType, WarCount } from '../db/Role' -import { getLvByExp, getExpByLv, gameData, getDicApByLv } from '../pubUtils/data'; -import { updateRoleOnlineInfo, updateUserInfo } from './redisService'; -// import { switchOnFunc } from './funcSwitchService'; -import { FUNC_OPT_TYPE, TASK_TYPE, WAR_TYPE, STATUS, KING_EXP_RATIO_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, HERO_SYSTEM_TYPE, PUSH_ROUTE } from '../consts'; -import { BackendSession, pinus } from 'pinus'; -import { REDIS_KEY } from '../consts'; -import { Rank } from './rankService'; -import { checkTask } from './task/taskService'; -import { RScriptRecordModel } from '../db/RScriptRecord'; -import { setAp } from './actionPointService'; -import { resResult, shouldRefresh } from '../pubUtils/util'; -import { GuildLeader, LineupParam } from '../domain/rank'; -import { WarStar } from '../domain/dbGeneral'; -import { isArray, isNumber, uniq } from 'underscore'; -import { checkPopUpCondition } from './activity/popUpShopService'; -import { calculateCeWithRole } from './playerCeService'; -import { sendMessageToUserWithSuc } from './pushService'; -import { ActionPointModel } from '../db/ActionPoint'; -import { GK_MAIN, GK_MAINELITE, RECHARGE } from '../pubUtils/dicParam'; -import { updateGVGBattleRoleInfo } from './gvg/gvgTeamService'; -import { pvpEndParamInter } from '../pubUtils/interface'; - -export async function roleLevelup(type: KING_EXP_RATIO_TYPE, roleId: string, kingExp: number = 0, session: BackendSession) { - const serverId = session.get('serverId'); - const sid = session.get('sid'); - const ip = session.get('ip'); - - let role = await RoleModel.findByRoleId(roleId); - let { lv = 1, exp = 0 } = role; - let canGetExp = lv < gameData.maxPlayerLv.max; // 当主公超过最大级后,挑战结算不再获得经验值 - let ratio = gameData.kingExpRaio.get(lv)?.get(type)||0; - let newExp = canGetExp ? exp + Math.floor(kingExp * ratio) : exp; - let newLv = getLvByExp(newExp); - - role = await RoleModel.levelup(roleId, newLv, newExp); - if (newLv > lv) { // 升级 - // await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session); - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'lv', value: newLv }]); - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, role.guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - } - - let r = new Rank(REDIS_KEY.USER_LV, { serverId: role.serverId }); - await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role); - - // 任务 - await checkTask(serverId, roleId, session.get('sid'), TASK_TYPE.ROLE_LV, { oldLv: lv, lv: newLv }); - // 弹出礼包 - await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.LV_TO, { oldLv: lv, newLv }) - // await calculateCeWithRole(HERO_SYSTEM_TYPE.ROLE_LV, roleId, serverId, sid, { lv: newLv }); - - await updateRoleOnlineInfo(roleId, { lv: newLv }); - - await updateGVGBattleRoleInfo(serverId, roleId, { lv }); - } - let actordata: { lv: number, exp: number, getExp: number, mostExp: number }[] = []; - for (let i = lv; i <= newLv; i++) { - let lvObj = getExpByLv(i); - - if (!lvObj) break; - let { sum, cur } = lvObj; - let lastSum = sum - cur; - // console.log(sum, cur, lastSum, exp, newExp); - - let startExp = exp > lastSum ? exp - lastSum : 0; - let getExp = newExp > sum ? cur - startExp : newExp - lastSum - startExp; - actordata.push({ - lv: i, - exp: startExp, // 升级前经验 - getExp: getExp > 0 ? getExp : 0, // 获得的经验 - mostExp: cur - }); - if(i != lv) { // 升级加体力 - let dicAp = getDicApByLv(i); - let { ap, apBefore } = await setAp(serverId, roleId, ip, i, dicAp.restoreAp, sid, ITEM_CHANGE_REASON.LV_UP); - await ActionPointModel.setLvRecord(roleId, i, ap, apBefore); - } - } - // 推送 - if(canGetExp && kingExp >= 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_EXP_CHANGE, { isLvUp: newLv > lv, lv: newLv, exp: newExp }, sid); - } - - return { actordata, lv: newLv, exp: newExp, kingExp: newExp - exp }; -} - - -export async function checkBattleHeroes(roleId: string, seqIds: Array = []) { - let hids: number[] = [], lineup: LineupParam[] = [], heroes: HeroType[] = []; - let flag = true; - // if (seqIds.length <= 0) flag = false; - - const findHeroes = await HeroModel.findBySeqIdRange(seqIds, roleId); - if (findHeroes.length != seqIds.length) flag = false; - for (let seqId of seqIds) { - let hero = findHeroes.find(cur => cur.seqId == seqId); - if (!hero) { - flag = false; break; - } - hids.push(hero.hid); - lineup.push(new LineupParam(hero)); - heroes.push(hero); - } - return { isOK: flag, hids, heroes, seqIds, lineup }; -} - -export async function checkBattleHeroesByHid(roleId: string, heroes: Array = []) { - let flag = true; - // if (heroes.length <= 0) flag = false; - - const findHeroes = await HeroModel.findByHidRange(heroes, roleId); - if (findHeroes.length != heroes.length) flag = false; - for (let hid of heroes) { - let hero = findHeroes.find(cur => cur.hid == hid); - if (!hero) flag = false; - } - return { isOK: flag, heroes: findHeroes }; -} - -export function calculateWarStar(warStar: WarStar[] = [], battleId: number, stars: number[] = []) { - let newWarStars: WarStar[] = []; - let newStars: number[] = [], newStar = 0; - let hasFound = false; - for(let curWarStar of warStar) { - if(curWarStar.id == battleId) { - let oldStars = curWarStar.stars||[]; - newStars = uniq([...stars, ...oldStars]); - newStar = newStars.filter(cur => cur > 0).length; - newWarStars.push({...curWarStar, star: newStar, stars: newStars}); - hasFound = true; - } else { - newWarStars.push(curWarStar); - } - } - if(!hasFound) { - newStar = stars.filter(cur => cur > 0).length; - newStars = stars; - let dicWar = gameData.war.get(battleId); - if(dicWar) newWarStars.push({ id: battleId, warType: dicWar.warType, star: newStar, stars: newStars}); - } - return { newWarStars, newStars, newStar }; -} - -export async function getBattleListOfMain(role: RoleType) { - let types = [ WAR_TYPE.NORMAL, WAR_TYPE.VESTIGE, WAR_TYPE.MAIN_ELITE, WAR_TYPE.TOWER, WAR_TYPE.MYSTERY, WAR_TYPE.BRANCH_ELITE ]; - return await getBattleListOfTypes(role, types); -} - -export async function getBattleListOfTypes(role: RoleType, types: number[]) { - let result = []; - for(let type of types) { - let list = await getBattleList(role, type); - result.push({ type, list }); - } - return result -} - -export async function getBattleList(role: RoleType, type: number) { - let { roleId, warStar, warCount = [], refWarCount } = role; - if(shouldRefresh(refWarCount, new Date())) { - warCount = []; - } - - let scripts = await RScriptRecordModel.findbyRole(roleId, type); - - let result = []; // 去重 - for (let { battleId, scriptBefore = '', scriptAfter = '' } of scripts) { - - result.push({ - battleId, - status: 0, - star: 0, - stars: [], - scriptBefore, - scriptAfter - }); - } - for (let { id, star, stars = [], warType } of warStar) { - if (warType == type) { - let curResult = result.find(cur => cur.battleId == id); - if (curResult) { - curResult.status = 1; - curResult.star = star; - curResult.stars = stars; - } else { - result.push({ - battleId: id, - status: 1, - star, - stars, - scriptBefore: '', - scriptAfter: '' - }); - } - } - } - if(type == WAR_TYPE.NORMAL || type == WAR_TYPE.MAIN_ELITE) { - for(let data of result) { - let curWarCount = warCount.find(cur => cur.warId == data.battleId); - data.count = curWarCount? curWarCount.count: 0; - } - } - result = result.sort((a, b) => { return a.battleId - b.battleId }); - return result; -} - -export async function checkWarCountAndInc(warId: number, inc: number, role: RoleType, needRefresh: boolean) { - let { roleId, warCount, refWarCount } = role; - let dicWar = gameData.war.get(warId); - let max = dicWar.warType == WAR_TYPE.NORMAL? GK_MAIN.GK_MAIN_SWEEP_TIMES: GK_MAINELITE.GK_MAINELITE_SWEEP_TIMES; - if(needRefresh && shouldRefresh(refWarCount, new Date())) { - let role = await RoleModel.updateRoleInfo(roleId, { refWarCount: new Date(), warCount: [] }); - warCount = role.warCount; - } - let curWarCount = warCount.find(cur => cur.warId == warId); - let count = curWarCount? curWarCount.count: 0; - if(inc <= 0) { // checkBattle - if(count >= max) return resResult(STATUS.BATTLE_OR_SWEEP_CNT_NOT_ENOUGH); - } else { // battleEnd & battleSweep - if(count + inc > max) return resResult(STATUS.BATTLE_OR_SWEEP_CNT_NOT_ENOUGH); - } - if(inc > 0) { - if(curWarCount) { - curWarCount.count += inc; - } else { - warCount.push({ warId, count: inc }); - } - await RoleModel.updateRoleInfo(roleId, { warCount }); - } - return resResult(STATUS.SUCCESS); -} - -export function getStarOfChapter(warStar: WarStar[], warTye: number, chapter: number) { - let starOfChapter = 0 - for(let { id, star } of warStar ) { - let dicWar = gameData.war.get(id); - if(dicWar.warType == warTye && star > 0) { - starOfChapter += star; - } - } - return starOfChapter; -} - -export function getMainChapter(role: RoleType) { - let chapterArr: { chapter: number, star: number, warType: number }[] = []; - for(let { id, star } of role.warStar ) { - let dicWar = gameData.war.get(id); - if((dicWar && (dicWar.warType == WAR_TYPE.NORMAL || dicWar.warType == WAR_TYPE.MAIN_ELITE)) && star > 0) { - let curChapter = chapterArr.find(cur => cur.warType == dicWar.warType && cur.chapter == dicWar.chapter); - if(!curChapter) { - chapterArr.push({ chapter: dicWar.chapter, star, warType: dicWar.warType }); - } else { - curChapter.star += star; - } - } - } - - return { - star: chapterArr, - receivedBox: role.receivedBox||[], - receivedWarIds: role.receivedWarIds||[], - } -} - -export function getBattleRecordParam(damageRecord: pvpEndParamInter[], round: number, heroes?: number[]) { - let record = { 'record.heroes': [], 'record.damageRecord': [], 'record.round': 0 }; - if(heroes && isArray(heroes)) record['record.heroes'] = heroes; - if(damageRecord && isArray(damageRecord)) { - for(let { hid, damage, heal, underDamage, subHid } of damageRecord) { - if (subHid && (!isNumber(subHid))) continue; - if(isNumber(hid) && isNumber(damage) && isNumber(heal) && isNumber(underDamage)) { - record['record.damageRecord'].push({ hid, damage, heal, underDamage, subHid }); - } - } - } - if(isNumber(round)) record['record.round'] = round; - return record; -} \ No newline at end of file + +import { HeroModel, HeroType } from '@db/Hero'; +import Role, { RoleModel, RoleType, WarCount } from '@db/Role' +import { getLvByExp, getExpByLv, gameData, getDicApByLv } from '@pubUtils/data'; +import { updateRoleOnlineInfo, updateUserInfo } from './redisService'; +// import { switchOnFunc } from './funcSwitchService'; +import { FUNC_OPT_TYPE, TASK_TYPE, WAR_TYPE, STATUS, KING_EXP_RATIO_TYPE, ITEM_CHANGE_REASON, POP_UP_SHOP_CONDITION_TYPE, HERO_SYSTEM_TYPE, PUSH_ROUTE } from '@consts'; +import { BackendSession, pinus } from 'pinus'; +import { REDIS_KEY } from '@consts'; +import { Rank } from './rankService'; +import { checkTask } from './task/taskService'; +import { RScriptRecordModel } from '@db/RScriptRecord'; +import { setAp } from './actionPointService'; +import { resResult, shouldRefresh } from '@pubUtils/util'; +import { GuildLeader, LineupParam } from '@domain/rank'; +import { WarStar } from '@domain/dbGeneral'; +import { isArray, isNumber, uniq } from 'underscore'; +import { checkPopUpCondition } from './activity/popUpShopService'; +import { calculateCeWithRole } from './playerCeService'; +import { sendMessageToUserWithSuc } from './pushService'; +import { ActionPointModel } from '@db/ActionPoint'; +import { GK_MAIN, GK_MAINELITE, RECHARGE } from '@pubUtils/dicParam'; +import { updateGVGBattleRoleInfo } from './gvg/gvgTeamService'; +import { pvpEndParamInter } from '@pubUtils/interface'; + +export async function roleLevelup(type: KING_EXP_RATIO_TYPE, roleId: string, kingExp: number = 0, session: BackendSession) { + const serverId = session.get('serverId'); + const sid = session.get('sid'); + const ip = session.get('ip'); + + let role = await RoleModel.findByRoleId(roleId); + let { lv = 1, exp = 0 } = role; + let canGetExp = lv < gameData.maxPlayerLv.max; // 当主公超过最大级后,挑战结算不再获得经验值 + let ratio = gameData.kingExpRaio.get(lv)?.get(type)||0; + let newExp = canGetExp ? exp + Math.floor(kingExp * ratio) : exp; + let newLv = getLvByExp(newExp); + + role = await RoleModel.levelup(roleId, newLv, newExp); + if (newLv > lv) { // 升级 + // await switchOnFunc(roleId, FUNC_OPT_TYPE.LEVEL_UP, newLv, session); + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'lv', value: newLv }]); + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, role.guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + } + + let r = new Rank(REDIS_KEY.USER_LV, { serverId: role.serverId }); + await r.setRankWithRoleInfo(roleId, newLv, Date.now(), role); + + // 任务 + await checkTask(serverId, roleId, session.get('sid'), TASK_TYPE.ROLE_LV, { oldLv: lv, lv: newLv }); + // 弹出礼包 + await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.LV_TO, { oldLv: lv, newLv }) + // await calculateCeWithRole(HERO_SYSTEM_TYPE.ROLE_LV, roleId, serverId, sid, { lv: newLv }); + + await updateRoleOnlineInfo(roleId, { lv: newLv }); + + await updateGVGBattleRoleInfo(serverId, roleId, { lv }); + } + let actordata: { lv: number, exp: number, getExp: number, mostExp: number }[] = []; + for (let i = lv; i <= newLv; i++) { + let lvObj = getExpByLv(i); + + if (!lvObj) break; + let { sum, cur } = lvObj; + let lastSum = sum - cur; + // console.log(sum, cur, lastSum, exp, newExp); + + let startExp = exp > lastSum ? exp - lastSum : 0; + let getExp = newExp > sum ? cur - startExp : newExp - lastSum - startExp; + actordata.push({ + lv: i, + exp: startExp, // 升级前经验 + getExp: getExp > 0 ? getExp : 0, // 获得的经验 + mostExp: cur + }); + if(i != lv) { // 升级加体力 + let dicAp = getDicApByLv(i); + let { ap, apBefore } = await setAp(serverId, roleId, ip, i, dicAp.restoreAp, sid, ITEM_CHANGE_REASON.LV_UP); + await ActionPointModel.setLvRecord(roleId, i, ap, apBefore); + } + } + // 推送 + if(canGetExp && kingExp >= 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_EXP_CHANGE, { isLvUp: newLv > lv, lv: newLv, exp: newExp }, sid); + } + + return { actordata, lv: newLv, exp: newExp, kingExp: newExp - exp }; +} + + +export async function checkBattleHeroes(roleId: string, seqIds: Array = []) { + let hids: number[] = [], lineup: LineupParam[] = [], heroes: HeroType[] = []; + let flag = true; + // if (seqIds.length <= 0) flag = false; + + const findHeroes = await HeroModel.findBySeqIdRange(seqIds, roleId); + if (findHeroes.length != seqIds.length) flag = false; + for (let seqId of seqIds) { + let hero = findHeroes.find(cur => cur.seqId == seqId); + if (!hero) { + flag = false; break; + } + hids.push(hero.hid); + lineup.push(new LineupParam(hero)); + heroes.push(hero); + } + return { isOK: flag, hids, heroes, seqIds, lineup }; +} + +export async function checkBattleHeroesByHid(roleId: string, heroes: Array = []) { + let flag = true; + // if (heroes.length <= 0) flag = false; + + const findHeroes = await HeroModel.findByHidRange(heroes, roleId); + if (findHeroes.length != heroes.length) flag = false; + for (let hid of heroes) { + let hero = findHeroes.find(cur => cur.hid == hid); + if (!hero) flag = false; + } + return { isOK: flag, heroes: findHeroes }; +} + +export function calculateWarStar(warStar: WarStar[] = [], battleId: number, stars: number[] = []) { + let newWarStars: WarStar[] = []; + let newStars: number[] = [], newStar = 0; + let hasFound = false; + for(let curWarStar of warStar) { + if(curWarStar.id == battleId) { + let oldStars = curWarStar.stars||[]; + newStars = uniq([...stars, ...oldStars]); + newStar = newStars.filter(cur => cur > 0).length; + newWarStars.push({...curWarStar, star: newStar, stars: newStars}); + hasFound = true; + } else { + newWarStars.push(curWarStar); + } + } + if(!hasFound) { + newStar = stars.filter(cur => cur > 0).length; + newStars = stars; + let dicWar = gameData.war.get(battleId); + if(dicWar) newWarStars.push({ id: battleId, warType: dicWar.warType, star: newStar, stars: newStars}); + } + return { newWarStars, newStars, newStar }; +} + +export async function getBattleListOfMain(role: RoleType) { + let types = [ WAR_TYPE.NORMAL, WAR_TYPE.VESTIGE, WAR_TYPE.MAIN_ELITE, WAR_TYPE.TOWER, WAR_TYPE.MYSTERY, WAR_TYPE.BRANCH_ELITE ]; + return await getBattleListOfTypes(role, types); +} + +export async function getBattleListOfTypes(role: RoleType, types: number[]) { + let result = []; + for(let type of types) { + let list = await getBattleList(role, type); + result.push({ type, list }); + } + return result +} + +export async function getBattleList(role: RoleType, type: number) { + let { roleId, warStar, warCount = [], refWarCount } = role; + if(shouldRefresh(refWarCount, new Date())) { + warCount = []; + } + + let scripts = await RScriptRecordModel.findbyRole(roleId, type); + + let result = []; // 去重 + for (let { battleId, scriptBefore = '', scriptAfter = '' } of scripts) { + + result.push({ + battleId, + status: 0, + star: 0, + stars: [], + scriptBefore, + scriptAfter + }); + } + for (let { id, star, stars = [], warType } of warStar) { + if (warType == type) { + let curResult = result.find(cur => cur.battleId == id); + if (curResult) { + curResult.status = 1; + curResult.star = star; + curResult.stars = stars; + } else { + result.push({ + battleId: id, + status: 1, + star, + stars, + scriptBefore: '', + scriptAfter: '' + }); + } + } + } + if(type == WAR_TYPE.NORMAL || type == WAR_TYPE.MAIN_ELITE) { + for(let data of result) { + let curWarCount = warCount.find(cur => cur.warId == data.battleId); + data.count = curWarCount? curWarCount.count: 0; + } + } + result = result.sort((a, b) => { return a.battleId - b.battleId }); + return result; +} + +export async function checkWarCountAndInc(warId: number, inc: number, role: RoleType, needRefresh: boolean) { + let { roleId, warCount, refWarCount } = role; + let dicWar = gameData.war.get(warId); + let max = dicWar.warType == WAR_TYPE.NORMAL? GK_MAIN.GK_MAIN_SWEEP_TIMES: GK_MAINELITE.GK_MAINELITE_SWEEP_TIMES; + if(needRefresh && shouldRefresh(refWarCount, new Date())) { + let role = await RoleModel.updateRoleInfo(roleId, { refWarCount: new Date(), warCount: [] }); + warCount = role.warCount; + } + let curWarCount = warCount.find(cur => cur.warId == warId); + let count = curWarCount? curWarCount.count: 0; + if(inc <= 0) { // checkBattle + if(count >= max) return resResult(STATUS.BATTLE_OR_SWEEP_CNT_NOT_ENOUGH); + } else { // battleEnd & battleSweep + if(count + inc > max) return resResult(STATUS.BATTLE_OR_SWEEP_CNT_NOT_ENOUGH); + } + if(inc > 0) { + if(curWarCount) { + curWarCount.count += inc; + } else { + warCount.push({ warId, count: inc }); + } + await RoleModel.updateRoleInfo(roleId, { warCount }); + } + return resResult(STATUS.SUCCESS); +} + +export function getStarOfChapter(warStar: WarStar[], warTye: number, chapter: number) { + let starOfChapter = 0 + for(let { id, star } of warStar ) { + let dicWar = gameData.war.get(id); + if(dicWar.warType == warTye && star > 0) { + starOfChapter += star; + } + } + return starOfChapter; +} + +export function getMainChapter(role: RoleType) { + let chapterArr: { chapter: number, star: number, warType: number }[] = []; + for(let { id, star } of role.warStar ) { + let dicWar = gameData.war.get(id); + if((dicWar && (dicWar.warType == WAR_TYPE.NORMAL || dicWar.warType == WAR_TYPE.MAIN_ELITE)) && star > 0) { + let curChapter = chapterArr.find(cur => cur.warType == dicWar.warType && cur.chapter == dicWar.chapter); + if(!curChapter) { + chapterArr.push({ chapter: dicWar.chapter, star, warType: dicWar.warType }); + } else { + curChapter.star += star; + } + } + } + + return { + star: chapterArr, + receivedBox: role.receivedBox||[], + receivedWarIds: role.receivedWarIds||[], + } +} + +export function getBattleRecordParam(damageRecord: pvpEndParamInter[], round: number, heroes?: number[]) { + let record = { 'record.heroes': [], 'record.damageRecord': [], 'record.round': 0 }; + if(heroes && isArray(heroes)) record['record.heroes'] = heroes; + if(damageRecord && isArray(damageRecord)) { + for(let { hid, damage, heal, underDamage, subHid } of damageRecord) { + if (subHid && (!isNumber(subHid))) continue; + if(isNumber(hid) && isNumber(damage) && isNumber(heal) && isNumber(underDamage)) { + record['record.damageRecord'].push({ hid, damage, heal, underDamage, subHid }); + } + } + } + if(isNumber(round)) record['record.round'] = round; + return record; +} diff --git a/game-server/app/services/orderService.ts b/game-server/app/services/orderService.ts index dd13311ed..ef95cb61a 100644 --- a/game-server/app/services/orderService.ts +++ b/game-server/app/services/orderService.ts @@ -1,443 +1,443 @@ -import { UserOrderModel, UserOrderModelType } from '../db/UserOrder'; -import { ACTIVITY_TYPE, DEBUG_PRICE, MAIL_TYPE, ORDER_STATE, PAY_TYPE, PUSH_ROUTE, REFUND_PRICE_TO_GOLD, STATUS, TASK_TYPE, TA_EVENT, TA_USERSET_TYPE } from '../consts'; -import { dicRMB } from '../pubUtils/dictionary/DicRMB'; -import { makeYuanbaoShopReward } from './activity/yuanbaoService'; -import { RoleModel } from '../db/Role'; -import { checkMonthlyTicket, makeMonthlyTicketReward } from './activity/monthlyTicketService'; -import { checkSignInCanBuy, makeSignInVIP } from './activity/signInService'; -import { checkDailyRMBGifts, makeDailyRMBGiftsReward } from './activity/dailyRMBGiftsService'; -import { checkPopUpShopCanBuy, makePopUpShopReward } from './activity/popUpShopService'; -import { ActivityModel, ActivityModelType } from '../db/Activity'; -import { checkGrowthFund, makeGrowthFund } from './activity/growthFundService'; -import { checkLimitPackageCanBuy, makeLimitPackageReward } from './activity/limitPackageService'; -import { checkTreasureHuntShop, makeShop } from './activity/treasureHuntService'; -import { checkSelfServiceShop, makeSelfServerShop } from './activity/selfServiceShopActivityService'; -import { checkRefreshShop, makeRefreshShopReward } from './activity/refreshShopService'; -import { ActivityMonopolyModel, ActivityMonopolyModelType } from '../db/ActivityMonopoly'; -import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '../db/ActivityMonopolyLand'; -import { parseGoodStr, resResult } from '../pubUtils/util'; -import { checkOrderWX } from './pay/weixinPay'; -import { addRechargeMoney } from './activity/rechargeMoneyService'; -import { addVipRechargeMoney } from './activity/vipRechargeMoneyService'; -import { checkTask } from './task/taskService'; -import { checkOrderALI } from './pay/aliPay'; -import { getRoleOnlineInfo } from './redisService'; -import { PayCallback37Data } from '../domain/sdk'; -import { reportTAEvent, reportTAUserSet } from './sdkService'; -import { savePayLog } from '../pubUtils/logUtil'; -import { recordFirstGift } from './activity/firstGiftService'; -import { checkTaskPass, makeTaskPass } from './activity/taskPassService'; -import { addGuildPay } from './activity/guildPayService'; -import { sendMessageToUserWithSuc } from './pushService'; -import { checkParamPrice, needRebate } from '../pubUtils/sdkUtil'; -import { checkShopCanBuyInOrder, makeShopOrder } from './shopService'; -import { checkWeeklyFund, makeWeeklyFund } from './activity/weeklyFundService'; -import { checkMonthlyFund, makeMonthlyFund } from './activity/monthlyFundService'; -import { gameData } from '../pubUtils/data'; - -export async function checkOrderCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, paramStr: string) { - let activityId = activityData.activityId; - - switch(activityData.type) { - case ACTIVITY_TYPE.SIGN_IN_VIP: - case ACTIVITY_TYPE.COMMON_SIGN_IN: - { - return await checkSignInCanBuy(roleId, serverId, activityId, productID) - } - case ACTIVITY_TYPE.POP_UP_SHOP: - { - return await checkPopUpShopCanBuy(roleId, serverId, activityId, productID, paramStr) - } - case ACTIVITY_TYPE.SHOP: - { - return await checkShopCanBuyInOrder(roleId, serverId, activityData, productID) - } - case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: - { - return await checkLimitPackageCanBuy(roleId, serverId, activityData, productID) - } - case ACTIVITY_TYPE.WEEKLY_FUND: - { - return await checkWeeklyFund(roleId, serverId, activityData); - } - case ACTIVITY_TYPE.MONTHLY_FUND: - { - return await checkMonthlyFund(roleId, serverId, activityData, productID); - } - case ACTIVITY_TYPE.DAILY_RMB_GIFTS: - { - return await checkDailyRMBGifts(roleId, serverId, activityData, productID); - } - case ACTIVITY_TYPE.MONTHLY_TICKET_1: - case ACTIVITY_TYPE.MONTHLY_TICKET_2: - { - return await checkMonthlyTicket(roleId, serverId, activityData); - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) - { - return await checkGrowthFund(roleId, serverId, activityData, productID); - } - case ACTIVITY_TYPE.SELF_SERVICE_SHOP: - { - return await checkSelfServiceShop(roleId, serverId, activityData, productID); - } - case ACTIVITY_TYPE.TASK_PASS: - { - return await checkTaskPass(roleId, serverId, activityData, productID); - } - case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) - { - if (paramStr) {//大富翁商店结算 - let paramObj = JSON.parse(paramStr); - let activityId = paramObj.activityId;//大富翁活动id; orderInfo.activityId是大富翁中的商店活动id - if (activityId) { - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityId, roleId); - let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(serverId, activityId, roleId, playerMonopolyData.curPosition); - let roundIndex = playerLandData.stopCount; - return await checkRefreshShop(roleId, serverId, activityData, productID, roundIndex); - } - } - //正常商店结算 - return await checkRefreshShop(roleId, serverId, activityData, productID, 0); - } - case ACTIVITY_TYPE.TREASURE_HUNT://寻宝奇兵活动-每日物资商店 - { - return await checkTreasureHuntShop(roleId, serverId, activityData, productID); - } - } - return true -} - -/** - * 结算账单 - * @param localOrderID 本地订单号 - */ -export async function makeOrder(orderInfo: UserOrderModelType, sid: string) { - - //商品价格信息 - let productInfo = dicRMB.get(orderInfo.productID) - - - let productType = productInfo.type;//类型 - let price = orderInfo.price;//下单时的价格 - let payType = orderInfo.payType;//支付类型 - let roleId = orderInfo.roleId;//角色 - - const roleInfo = await RoleModel.increaseTotalPay(roleId, price); - - let rewardResult: any = { code: 0, data: null }; - - switch (productType) { - case ACTIVITY_TYPE.SIGN_IN_VIP: - case ACTIVITY_TYPE.COMMON_SIGN_IN: - { - rewardResult = await makeSignInVIP(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: - { - rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: - case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: - { - rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.YUAN_BAO_SHOP: - { - rewardResult = await makeYuanbaoShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - - case ACTIVITY_TYPE.MONTHLY_TICKET_1: - case ACTIVITY_TYPE.MONTHLY_TICKET_2: - { - rewardResult = await makeMonthlyTicketReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.DAILY_RMB_GIFTS: - { - rewardResult = await makeDailyRMBGiftsReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.POP_UP_SHOP://弹出礼包 - { - rewardResult = await makePopUpShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, orderInfo.paramStr, roleInfo) - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) - { - rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) - { - rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) - { - rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP://学宫密卷(高阶) - { - rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP://列传密卷(高阶) - { - rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.TREASURE_HUNT://寻宝奇兵活动-每日物资商店 - { - rewardResult = await makeShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.SELF_SERVICE_SHOP://自选商店-购买礼包(糜家商队) - { - rewardResult = await makeSelfServerShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) - { - if (orderInfo.paramStr) {//大富翁商店结算 - let paramObj = JSON.parse(orderInfo.paramStr); - let activityId = paramObj.activityId;//大富翁活动id; orderInfo.activityId是大富翁中的商店活动id - if (activityId) { - let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(orderInfo.serverId, activityId, roleId); - let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(orderInfo.serverId, activityId, roleId, playerMonopolyData.curPosition); - let roundIndex = playerLandData.stopCount; - rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, roundIndex) - break; - } - } - //正常商店结算 - rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, 0) - break; - } - case ACTIVITY_TYPE.TASK_PASS: // 战令-高级卡 - { - rewardResult = await makeTaskPass(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - - } - case ACTIVITY_TYPE.SHOP: // 商店 - { - rewardResult = await makeShopOrder(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - - } - case ACTIVITY_TYPE.WEEKLY_FUND: // 周基金 - { - rewardResult = await makeWeeklyFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - case ACTIVITY_TYPE.MONTHLY_FUND: // 月基金 - { - rewardResult = await makeMonthlyFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) - break; - } - default: - rewardResult = STATUS.ERROR_TYPE; - break; - } - - if(rewardResult.code == 0) { - await recordFirstGift(roleInfo, orderInfo.serverId); - } - - await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { totalPay: roleInfo.totalPay }, sid); - - return {...rewardResult, roleInfo} -} - -export async function settleOrder(order: UserOrderModelType, serverId: number, sid?: string) { - if(!sid) { - let onlineUser = await getRoleOnlineInfo(order.roleId); - sid = onlineUser.sid; - } - //结算奖励 - let result = await makeOrder(order, sid); - if (result.code !== 0) {//结算失败 - console.log(`支付失败..... ${JSON.stringify(result)}`) - reportTAEvent(order.roleId, TA_EVENT.RECHARGE_FAIL, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" }) - savePayLog(order); - return resResult(result); - } - //推送 - console.log('***** settleOrder', order.roleId, sid) - //活动统计 - await addRechargeMoney(order.roleId, serverId, order.price); - await addVipRechargeMoney(order.roleId, serverId, order.price); - await addGuildPay(result.roleInfo, order.price) - //成长任务 - checkTask(serverId, order.roleId, null, TASK_TYPE.ACTIVITY_RMB, { count: order.price }); - if(order.payType != PAY_TYPE.TEST) { - reportTAEvent(order.roleId, TA_EVENT.RECHARGE_SUCCESS, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: getVoucherType(order.useVoucher, order.voucherId) }) - reportTAUserSet(TA_USERSET_TYPE.SET_ONCE, order.roleId, { first_pay_time: new Date() }); - reportTAUserSet(TA_USERSET_TYPE.SET, order.roleId, { last_pay_time: new Date() }); - reportTAUserSet(TA_USERSET_TYPE.ADD, order.roleId, { total_revenue: order.price }); - } - savePayLog(order); - if(!!sid) { - sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.ORDER, { - ...result.data, - price: order.price, - state: order.state, - localOrderID: order.localOrderID}, sid); - } - return result.data; -} - -function getVoucherType(useVoucher: boolean, voucherId: number) { - if(useVoucher) { - let dicGood = gameData.goods.get(voucherId); - if(!dicGood) return '未知'; - return dicGood.name; - } - return '现金' -} - -export async function settleOrderWx(order: UserOrderModelType, serverId: number, sid: string) { - - if (order.state == ORDER_STATE.RESULT_SUCCESS) { - return STATUS.DUPLICATE_ORDER; - } - order = await UserOrderModel.check(order.roleId, order.localOrderID); - if (!order) { - return STATUS.DUPLICATE_ORDER; - } - - let weixinResult = await checkOrderWX(order.localOrderID); - if (weixinResult.code == 0) { - console.log('微信订单查询失败') - return STATUS.ORDER_ERROR; - } - if (parseInt(weixinResult.data.total_fee) / 100 != order.price) { - console.log('订单价格错误') - return STATUS.PRICE_ERROR; - } - if (weixinResult.data.trade_state != "SUCCESS" || - weixinResult.data.result_code != "SUCCESS" || - weixinResult.data.return_code != "SUCCESS") { - return STATUS.NO_PAY; - } - - let result = await settleOrder(order, serverId, sid); - order = await UserOrderModel.success(order.roleId, order.localOrderID, result); - - return STATUS.SUCCESS -} - -export async function settleOrderAli(order: UserOrderModelType, serverId: number, sid: string) { - if (order.state == ORDER_STATE.RESULT_SUCCESS) { - return STATUS.DUPLICATE_ORDER; - } - let aliResult = await checkOrderALI(order.localOrderID); - if (aliResult.code == 0) { - console.log('支付宝订单查询失败') - return STATUS.ORDER_ERROR; - } - if (parseInt(aliResult.data.total_amount) != order.price) { - console.log('订单价格错误') - return STATUS.PRICE_ERROR; - } - if (aliResult.data.trade_status != "TRADE_SUCCESS") { - return STATUS.NO_PAY; - } - let aliOrderID = aliResult.data.trade_no; - let result = await settleOrder(order, serverId, sid); - await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, result); - - return STATUS.SUCCESS -} - -export async function settleOrderFromRedisPub(message: string) { - console.log('**********settleOrderFromRedisPub*******') - console.log('message: ', message); - - let params: PayCallback37Data; - try { - params = JSON.parse(message); - } catch(e) { - return false; - } - - let order = await UserOrderModel.findOrder(params.order_no); - if(!order || order.state != ORDER_STATE.CHECK_ORDER) { - console.log('订单状态错误'); - return false; - } - if(order.roleId != params.actor_id) { - console.log('订单玩家错误'); - return false; - } - if((!checkParamPrice(order.price, params.money))) { - console.log('订单金额错误'); - return false; - } - - let aliOrderID = params.order_id; - - let result = await settleOrder(order, parseInt(`${params.sid}`)); - await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, JSON.stringify(result)); - - return true -} - -export async function settleOrderFromHandler(localOrderID: string, roleId: string, serverId: number, sid: string ) { - - let order = await UserOrderModel.findOrder(localOrderID); - if(!order || order.state != ORDER_STATE.APPLY) { - return STATUS.DUPLICATE_ORDER; - } - if(order.roleId != roleId) { - console.log('订单玩家错误'); - return STATUS.ORDER_STATUS_ERROR; - } - - let result = await settleOrder(order, serverId, sid); - await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result)); - - return STATUS.SUCCESS -} - -export async function refundOrderFromRedisPub(message: string) { - console.log('**********refundOrderFromRedisPub*******') - console.log('message: ', message); - - let params: PayCallback37Data; - try { - params = JSON.parse(message); - } catch(e) { - return false; - } - - let order = await UserOrderModel.findOrder(params.order_no); - if(!order || order.state != ORDER_STATE.CHECK_TO_REFUND) { - console.log('订单状态错误'); - return false; - } - if(order.roleId != params.actor_id) { - console.log('订单玩家错误'); - return false; - } - - let price = order.price; - let refundGold = price * REFUND_PRICE_TO_GOLD; - let role = await RoleModel.incRoleInfo(order.roleId, { gold: -refundGold }, {}); - let onlineUser = await getRoleOnlineInfo(order.roleId); - let sid = onlineUser.sid; - sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold }, sid); - await UserOrderModel.refund(order.roleId, order.localOrderID, message); - - return true -} \ No newline at end of file +import { UserOrderModel, UserOrderModelType } from '@db/UserOrder'; +import { ACTIVITY_TYPE, DEBUG_PRICE, MAIL_TYPE, ORDER_STATE, PAY_TYPE, PUSH_ROUTE, REFUND_PRICE_TO_GOLD, STATUS, TASK_TYPE, TA_EVENT, TA_USERSET_TYPE } from '@consts'; +import { dicRMB } from '@pubUtils/dictionary/DicRMB'; +import { makeYuanbaoShopReward } from './activity/yuanbaoService'; +import { RoleModel } from '@db/Role'; +import { checkMonthlyTicket, makeMonthlyTicketReward } from './activity/monthlyTicketService'; +import { checkSignInCanBuy, makeSignInVIP } from './activity/signInService'; +import { checkDailyRMBGifts, makeDailyRMBGiftsReward } from './activity/dailyRMBGiftsService'; +import { checkPopUpShopCanBuy, makePopUpShopReward } from './activity/popUpShopService'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { checkGrowthFund, makeGrowthFund } from './activity/growthFundService'; +import { checkLimitPackageCanBuy, makeLimitPackageReward } from './activity/limitPackageService'; +import { checkTreasureHuntShop, makeShop } from './activity/treasureHuntService'; +import { checkSelfServiceShop, makeSelfServerShop } from './activity/selfServiceShopActivityService'; +import { checkRefreshShop, makeRefreshShopReward } from './activity/refreshShopService'; +import { ActivityMonopolyModel, ActivityMonopolyModelType } from '@db/ActivityMonopoly'; +import { ActivityMonopolyLandModel, ActivityMonopolyLandModelType } from '@db/ActivityMonopolyLand'; +import { parseGoodStr, resResult } from '@pubUtils/util'; +import { checkOrderWX } from './pay/weixinPay'; +import { addRechargeMoney } from './activity/rechargeMoneyService'; +import { addVipRechargeMoney } from './activity/vipRechargeMoneyService'; +import { checkTask } from './task/taskService'; +import { checkOrderALI } from './pay/aliPay'; +import { getRoleOnlineInfo } from './redisService'; +import { PayCallback37Data } from '@domain/sdk'; +import { reportTAEvent, reportTAUserSet } from './sdkService'; +import { savePayLog } from '@pubUtils/logUtil'; +import { recordFirstGift } from './activity/firstGiftService'; +import { checkTaskPass, makeTaskPass } from './activity/taskPassService'; +import { addGuildPay } from './activity/guildPayService'; +import { sendMessageToUserWithSuc } from './pushService'; +import { checkParamPrice, needRebate } from '@pubUtils/sdkUtil'; +import { checkShopCanBuyInOrder, makeShopOrder } from './shopService'; +import { checkWeeklyFund, makeWeeklyFund } from './activity/weeklyFundService'; +import { checkMonthlyFund, makeMonthlyFund } from './activity/monthlyFundService'; +import { gameData } from '@pubUtils/data'; + +export async function checkOrderCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, paramStr: string) { + let activityId = activityData.activityId; + + switch(activityData.type) { + case ACTIVITY_TYPE.SIGN_IN_VIP: + case ACTIVITY_TYPE.COMMON_SIGN_IN: + { + return await checkSignInCanBuy(roleId, serverId, activityId, productID) + } + case ACTIVITY_TYPE.POP_UP_SHOP: + { + return await checkPopUpShopCanBuy(roleId, serverId, activityId, productID, paramStr) + } + case ACTIVITY_TYPE.SHOP: + { + return await checkShopCanBuyInOrder(roleId, serverId, activityData, productID) + } + case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: + { + return await checkLimitPackageCanBuy(roleId, serverId, activityData, productID) + } + case ACTIVITY_TYPE.WEEKLY_FUND: + { + return await checkWeeklyFund(roleId, serverId, activityData); + } + case ACTIVITY_TYPE.MONTHLY_FUND: + { + return await checkMonthlyFund(roleId, serverId, activityData, productID); + } + case ACTIVITY_TYPE.DAILY_RMB_GIFTS: + { + return await checkDailyRMBGifts(roleId, serverId, activityData, productID); + } + case ACTIVITY_TYPE.MONTHLY_TICKET_1: + case ACTIVITY_TYPE.MONTHLY_TICKET_2: + { + return await checkMonthlyTicket(roleId, serverId, activityData); + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) + { + return await checkGrowthFund(roleId, serverId, activityData, productID); + } + case ACTIVITY_TYPE.SELF_SERVICE_SHOP: + { + return await checkSelfServiceShop(roleId, serverId, activityData, productID); + } + case ACTIVITY_TYPE.TASK_PASS: + { + return await checkTaskPass(roleId, serverId, activityData, productID); + } + case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) + { + if (paramStr) {//大富翁商店结算 + let paramObj = JSON.parse(paramStr); + let activityId = paramObj.activityId;//大富翁活动id; orderInfo.activityId是大富翁中的商店活动id + if (activityId) { + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(serverId, activityId, roleId); + let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(serverId, activityId, roleId, playerMonopolyData.curPosition); + let roundIndex = playerLandData.stopCount; + return await checkRefreshShop(roleId, serverId, activityData, productID, roundIndex); + } + } + //正常商店结算 + return await checkRefreshShop(roleId, serverId, activityData, productID, 0); + } + case ACTIVITY_TYPE.TREASURE_HUNT://寻宝奇兵活动-每日物资商店 + { + return await checkTreasureHuntShop(roleId, serverId, activityData, productID); + } + } + return true +} + +/** + * 结算账单 + * @param localOrderID 本地订单号 + */ +export async function makeOrder(orderInfo: UserOrderModelType, sid: string) { + + //商品价格信息 + let productInfo = dicRMB.get(orderInfo.productID) + + + let productType = productInfo.type;//类型 + let price = orderInfo.price;//下单时的价格 + let payType = orderInfo.payType;//支付类型 + let roleId = orderInfo.roleId;//角色 + + const roleInfo = await RoleModel.increaseTotalPay(roleId, price); + + let rewardResult: any = { code: 0, data: null }; + + switch (productType) { + case ACTIVITY_TYPE.SIGN_IN_VIP: + case ACTIVITY_TYPE.COMMON_SIGN_IN: + { + rewardResult = await makeSignInVIP(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.NEW_PLAYER_LIMIT_PACKAGE: + { + rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_DAILY: + case ACTIVITY_TYPE.LIMIT_PACKAGE_SHOP_WEEKLY: + { + rewardResult = await makeLimitPackageReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.YUAN_BAO_SHOP: + { + rewardResult = await makeYuanbaoShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + + case ACTIVITY_TYPE.MONTHLY_TICKET_1: + case ACTIVITY_TYPE.MONTHLY_TICKET_2: + { + rewardResult = await makeMonthlyTicketReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.DAILY_RMB_GIFTS: + { + rewardResult = await makeDailyRMBGiftsReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.POP_UP_SHOP://弹出礼包 + { + rewardResult = await makePopUpShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, orderInfo.paramStr, roleInfo) + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: //主线成长基金(高阶) + { + rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP://镇念塔成长基金(高阶) + { + rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP://精英成长基金(高阶) + { + rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP://学宫密卷(高阶) + { + rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP://列传密卷(高阶) + { + rewardResult = await makeGrowthFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.TREASURE_HUNT://寻宝奇兵活动-每日物资商店 + { + rewardResult = await makeShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.SELF_SERVICE_SHOP://自选商店-购买礼包(糜家商队) + { + rewardResult = await makeSelfServerShop(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.REFRESH_SHOP://通用的刷新商店(分页,可刷新,限制购买次数,支持rmb与资源兑换) + { + if (orderInfo.paramStr) {//大富翁商店结算 + let paramObj = JSON.parse(orderInfo.paramStr); + let activityId = paramObj.activityId;//大富翁活动id; orderInfo.activityId是大富翁中的商店活动id + if (activityId) { + let playerMonopolyData: ActivityMonopolyModelType = await ActivityMonopolyModel.findData(orderInfo.serverId, activityId, roleId); + let playerLandData: ActivityMonopolyLandModelType = await ActivityMonopolyLandModel.findDataByPosition(orderInfo.serverId, activityId, roleId, playerMonopolyData.curPosition); + let roundIndex = playerLandData.stopCount; + rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, roundIndex) + break; + } + } + //正常商店结算 + rewardResult = await makeRefreshShopReward(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID, 0) + break; + } + case ACTIVITY_TYPE.TASK_PASS: // 战令-高级卡 + { + rewardResult = await makeTaskPass(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + + } + case ACTIVITY_TYPE.SHOP: // 商店 + { + rewardResult = await makeShopOrder(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + + } + case ACTIVITY_TYPE.WEEKLY_FUND: // 周基金 + { + rewardResult = await makeWeeklyFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + case ACTIVITY_TYPE.MONTHLY_FUND: // 月基金 + { + rewardResult = await makeMonthlyFund(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } + default: + rewardResult = STATUS.ERROR_TYPE; + break; + } + + if(rewardResult.code == 0) { + await recordFirstGift(roleInfo, orderInfo.serverId); + } + + await sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { totalPay: roleInfo.totalPay }, sid); + + return {...rewardResult, roleInfo} +} + +export async function settleOrder(order: UserOrderModelType, serverId: number, sid?: string) { + if(!sid) { + let onlineUser = await getRoleOnlineInfo(order.roleId); + sid = onlineUser.sid; + } + //结算奖励 + let result = await makeOrder(order, sid); + if (result.code !== 0) {//结算失败 + console.log(`支付失败..... ${JSON.stringify(result)}`) + reportTAEvent(order.roleId, TA_EVENT.RECHARGE_FAIL, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: order.useVoucher? "现金": "代金券" }) + savePayLog(order); + return resResult(result); + } + //推送 + console.log('***** settleOrder', order.roleId, sid) + //活动统计 + await addRechargeMoney(order.roleId, serverId, order.price); + await addVipRechargeMoney(order.roleId, serverId, order.price); + await addGuildPay(result.roleInfo, order.price) + //成长任务 + checkTask(serverId, order.roleId, null, TASK_TYPE.ACTIVITY_RMB, { count: order.price }); + if(order.payType != PAY_TYPE.TEST) { + reportTAEvent(order.roleId, TA_EVENT.RECHARGE_SUCCESS, { pay_id: order.localOrderID, charge_id: order.productID, pay_name: order.message, pay_amount: order.price, pay_channel: order.payType, pay_type: getVoucherType(order.useVoucher, order.voucherId) }) + reportTAUserSet(TA_USERSET_TYPE.SET_ONCE, order.roleId, { first_pay_time: new Date() }); + reportTAUserSet(TA_USERSET_TYPE.SET, order.roleId, { last_pay_time: new Date() }); + reportTAUserSet(TA_USERSET_TYPE.ADD, order.roleId, { total_revenue: order.price }); + } + savePayLog(order); + if(!!sid) { + sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.ORDER, { + ...result.data, + price: order.price, + state: order.state, + localOrderID: order.localOrderID}, sid); + } + return result.data; +} + +function getVoucherType(useVoucher: boolean, voucherId: number) { + if(useVoucher) { + let dicGood = gameData.goods.get(voucherId); + if(!dicGood) return '未知'; + return dicGood.name; + } + return '现金' +} + +export async function settleOrderWx(order: UserOrderModelType, serverId: number, sid: string) { + + if (order.state == ORDER_STATE.RESULT_SUCCESS) { + return STATUS.DUPLICATE_ORDER; + } + order = await UserOrderModel.check(order.roleId, order.localOrderID); + if (!order) { + return STATUS.DUPLICATE_ORDER; + } + + let weixinResult = await checkOrderWX(order.localOrderID); + if (weixinResult.code == 0) { + console.log('微信订单查询失败') + return STATUS.ORDER_ERROR; + } + if (parseInt(weixinResult.data.total_fee) / 100 != order.price) { + console.log('订单价格错误') + return STATUS.PRICE_ERROR; + } + if (weixinResult.data.trade_state != "SUCCESS" || + weixinResult.data.result_code != "SUCCESS" || + weixinResult.data.return_code != "SUCCESS") { + return STATUS.NO_PAY; + } + + let result = await settleOrder(order, serverId, sid); + order = await UserOrderModel.success(order.roleId, order.localOrderID, result); + + return STATUS.SUCCESS +} + +export async function settleOrderAli(order: UserOrderModelType, serverId: number, sid: string) { + if (order.state == ORDER_STATE.RESULT_SUCCESS) { + return STATUS.DUPLICATE_ORDER; + } + let aliResult = await checkOrderALI(order.localOrderID); + if (aliResult.code == 0) { + console.log('支付宝订单查询失败') + return STATUS.ORDER_ERROR; + } + if (parseInt(aliResult.data.total_amount) != order.price) { + console.log('订单价格错误') + return STATUS.PRICE_ERROR; + } + if (aliResult.data.trade_status != "TRADE_SUCCESS") { + return STATUS.NO_PAY; + } + let aliOrderID = aliResult.data.trade_no; + let result = await settleOrder(order, serverId, sid); + await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, result); + + return STATUS.SUCCESS +} + +export async function settleOrderFromRedisPub(message: string) { + console.log('**********settleOrderFromRedisPub*******') + console.log('message: ', message); + + let params: PayCallback37Data; + try { + params = JSON.parse(message); + } catch(e) { + return false; + } + + let order = await UserOrderModel.findOrder(params.order_no); + if(!order || order.state != ORDER_STATE.CHECK_ORDER) { + console.log('订单状态错误'); + return false; + } + if(order.roleId != params.actor_id) { + console.log('订单玩家错误'); + return false; + } + if((!checkParamPrice(order.price, params.money))) { + console.log('订单金额错误'); + return false; + } + + let aliOrderID = params.order_id; + + let result = await settleOrder(order, parseInt(`${params.sid}`)); + await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, aliOrderID, JSON.stringify(result)); + + return true +} + +export async function settleOrderFromHandler(localOrderID: string, roleId: string, serverId: number, sid: string ) { + + let order = await UserOrderModel.findOrder(localOrderID); + if(!order || order.state != ORDER_STATE.APPLY) { + return STATUS.DUPLICATE_ORDER; + } + if(order.roleId != roleId) { + console.log('订单玩家错误'); + return STATUS.ORDER_STATUS_ERROR; + } + + let result = await settleOrder(order, serverId, sid); + await UserOrderModel.saveOrderID(order.roleId, order.localOrderID, '', JSON.stringify(result)); + + return STATUS.SUCCESS +} + +export async function refundOrderFromRedisPub(message: string) { + console.log('**********refundOrderFromRedisPub*******') + console.log('message: ', message); + + let params: PayCallback37Data; + try { + params = JSON.parse(message); + } catch(e) { + return false; + } + + let order = await UserOrderModel.findOrder(params.order_no); + if(!order || order.state != ORDER_STATE.CHECK_TO_REFUND) { + console.log('订单状态错误'); + return false; + } + if(order.roleId != params.actor_id) { + console.log('订单玩家错误'); + return false; + } + + let price = order.price; + let refundGold = price * REFUND_PRICE_TO_GOLD; + let role = await RoleModel.incRoleInfo(order.roleId, { gold: -refundGold }, {}); + let onlineUser = await getRoleOnlineInfo(order.roleId); + let sid = onlineUser.sid; + sendMessageToUserWithSuc(order.roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold }, sid); + await UserOrderModel.refund(order.roleId, order.localOrderID, message); + + return true +} diff --git a/game-server/app/services/pay/37Pay.ts b/game-server/app/services/pay/37Pay.ts index 837872668..881100fb3 100644 --- a/game-server/app/services/pay/37Pay.ts +++ b/game-server/app/services/pay/37Pay.ts @@ -1,55 +1,55 @@ -import { DEBUG_PRICE, SDK_37_CONST, STATUS } from "../../consts"; -import { RoleModel } from "../../db/Role"; -import { UserModel } from "../../db/User"; -import { LoginValidateData37 } from "../../domain/sdk"; -import { DicRMB } from "../../pubUtils/dictionary/DicRMB"; -import { nowSeconds } from "../../pubUtils/timeUtil"; -import { resResult } from "../../pubUtils/util"; -import { get37Md5SignA, isDebugPay } from "../../pubUtils/sdkUtil"; -import { pinus } from "pinus"; -import { gameData } from "../../pubUtils/data"; - -/** - * 37支付下单 - * - * @param {number} price 价格订单金额(分) - * @param {string} message 商品信息 - * @param {string} localOrderID 本地订单号 - * - */ -export async function applyOrder37(localOrderID: string, roleId: string, productInfo: DicRMB) { - let role = await RoleModel.findByRoleId(roleId); - let user = await UserModel.findUserByUid(role.userInfo.uid); - if(!user || !user.channelInfo || !(user.channelInfo).uid) - return { - code: -1, resData: resResult(STATUS.CHANNEL_INFO_NOT_FOUND) - } - let gameCoin = productInfo.gameCoin; - let ext = pinus.app.get('env'); - let body = { - game_id: SDK_37_CONST.GAME_ID, - uid: (user.channelInfo).uid, - sid: role.serverId, - actor_id: role.roleId, - order_no: localOrderID, - money: productInfo.price, - game_coin: gameCoin, - product_id: productInfo.channelProductID, - subject: productInfo.message, - time: nowSeconds(), - ext - } - if(isDebugPay()) { - body = {...body, money: DEBUG_PRICE} - } - - let sign = get37Md5SignA(body, SDK_37_CONST.PAY_KEY); - - - return { code: 0, data: { - gameCoin, - timestamp: nowSeconds(), - ext, - sign: sign - }}; -} +import { DEBUG_PRICE, SDK_37_CONST, STATUS } from "@consts"; +import { RoleModel } from "@db/Role"; +import { UserModel } from "@db/User"; +import { LoginValidateData37 } from "@domain/sdk"; +import { DicRMB } from "@pubUtils/dictionary/DicRMB"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { resResult } from "@pubUtils/util"; +import { get37Md5SignA, isDebugPay } from "@pubUtils/sdkUtil"; +import { pinus } from "pinus"; +import { gameData } from "@pubUtils/data"; + +/** + * 37支付下单 + * + * @param {number} price 价格订单金额(分) + * @param {string} message 商品信息 + * @param {string} localOrderID 本地订单号 + * + */ +export async function applyOrder37(localOrderID: string, roleId: string, productInfo: DicRMB) { + let role = await RoleModel.findByRoleId(roleId); + let user = await UserModel.findUserByUid(role.userInfo.uid); + if(!user || !user.channelInfo || !(user.channelInfo).uid) + return { + code: -1, resData: resResult(STATUS.CHANNEL_INFO_NOT_FOUND) + } + let gameCoin = productInfo.gameCoin; + let ext = pinus.app.get('env'); + let body = { + game_id: SDK_37_CONST.GAME_ID, + uid: (user.channelInfo).uid, + sid: role.serverId, + actor_id: role.roleId, + order_no: localOrderID, + money: productInfo.price, + game_coin: gameCoin, + product_id: productInfo.channelProductID, + subject: productInfo.message, + time: nowSeconds(), + ext + } + if(isDebugPay()) { + body = {...body, money: DEBUG_PRICE} + } + + let sign = get37Md5SignA(body, SDK_37_CONST.PAY_KEY); + + + return { code: 0, data: { + gameCoin, + timestamp: nowSeconds(), + ext, + sign: sign + }}; +} diff --git a/game-server/app/services/pay/aliPay.ts b/game-server/app/services/pay/aliPay.ts index ebf97ee38..330c89837 100644 --- a/game-server/app/services/pay/aliPay.ts +++ b/game-server/app/services/pay/aliPay.ts @@ -1,93 +1,93 @@ - -import path = require('path'); -import fs = require('fs'); -const Alipay = require('alipay-mobile').default -/* -包名:com.bantu.sgzzyz -APPID:2021002142639438 -*/ - -//notify_url: 异步通知url -//app_id: 开放平台 appid -//appPrivKeyFile: 你的应用私钥 -//alipayPubKeyFile: 蚂蚁金服公钥 -const config = { - app_id: '2021002142639438', - appPrivKeyFile: fs.readFileSync(path.resolve(__dirname, '../../../../../key/alipay/rsa_private_key.pem')), - alipayPubKeyFile: fs.readFileSync(path.resolve(__dirname, '../../../../../key/alipay/rsa_public_key.pem')) -} - - -const service = new Alipay(config) - -/** - * 支付宝下单 - * - * @param {number} price 订单总金额,单位为元,精确到小数点后两位 - * @param {string} message 商品信息 - * @param {string} localOrderID 本地订单号 - * - */ -export async function applyOrderALI(localOrderID: string, price: number, message: string) { - const data = { - subject: message, - out_trade_no: localOrderID, - total_amount: price.toFixed(2).toString() - } - console.log('applyOrderALI :', data) - let result = await service.createOrder(data) - - // { code: 0, - // message: '请求成功', - // data: - // 'app_id=2021002142639438&biz_content=%7B%22subject%22%3A%22%E8%B5%B5%E4%BA%91%E4%BC%A0%E8%B4%AD%E4%B9%B0%E5%85%83%E5%AE%9D60%22%2C%22out_trade_no%22%3A%22bwnNLGfdCylflxKf54bEpcwyEbq7xygp%22%2C%22total_amount%22%3A%226.00%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%7D&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2×tamp=2021-05-12%2018%3A40%3A25&version=1.0&sign=S4U6JzSUiCSMvAbXeiJ2m2AQ%2BfCSr4VE4VNN9QEZtplgWIO51HIGhL24BpR4aj7mMfWO%2BqaWQnU0Fe8Uki960smBdj0%2FDpuztA7%2BIBWHK1Qj69%2FLhDNLoHZgO41jQJjIOVI0gWt1KaDlG2%2B52ghswqcZN%2FkFLwfMZCMEph3eg3aofq1mmwRbqAh8Sepoy9nCd24CmMUIbNe%2FmcxVg3xvYcWXnneWWHu%2FFbnaeZtynoHVhXqqhjFZSrxdk8lo5qyTXkE1ZoUrhJz918E2rArwzZeUL09ncPshHHvX6AygXp5BtV4clwTY0OY5yzOEXboluR5YmSaVXn0VkTWJZCTWTQ%3D%3D' - // } - console.log('applyOrderALI result: ', result) - if (result.code == 0) { - return { code: 0, data: result.data }; - } - return { code: -1, data: JSON.stringify(result) }; -} - - - -/** - * 支付宝查询支付结果 - * - * @param {number} serverId 区Id - * @param {string} roleId 角色Id - * @param {string} localOrderID 本地订单号 - * - */ -export async function checkOrderALI(localOrderID: string) { - let data = { - out_trade_no: localOrderID, - } - console.log('checkOrderALI :', data) - - let result = await service.queryOrder(data) - console.log('checkOrderALI result: ', result) - // { - // 0|app | code: '0', - // 0|app | data: { - // 0|app | code: '10000', - // 0|app | msg: 'Success', - // 0|app | buyer_logon_id: '525***@qq.com', - // 0|app | buyer_pay_amount: '0.00', - // 0|app | buyer_user_id: '2088302819007765', - // 0|app | invoice_amount: '0.00', - // 0|app | out_trade_no: 'JbyWyR1SIVIw9ArxvHAgte6tmnIzSRea', - // 0|app | point_amount: '0.00', - // 0|app | receipt_amount: '0.00', - // 0|app | send_pay_date: '2019-09-29 18:32:13', - // 0|app | total_amount: '1.00', - // 0|app | trade_no: '2019092922001407760553648380', - // 0|app | trade_status: 'TRADE_SUCCESS' - // 0|app | }, - // 0|app | message: 'success' - // 0|app | } - if ((result.code == '0') && (result.message == "success")) { - return { code: 1, data: result.data }; - } - return { code: 0, data: JSON.stringify(result) }; -} \ No newline at end of file + +import path = require('path'); +import fs = require('fs'); +const Alipay = require('alipay-mobile').default +/* +包名:com.bantu.sgzzyz +APPID:2021002142639438 +*/ + +//notify_url: 异步通知url +//app_id: 开放平台 appid +//appPrivKeyFile: 你的应用私钥 +//alipayPubKeyFile: 蚂蚁金服公钥 +const config = { + app_id: '2021002142639438', + appPrivKeyFile: fs.readFileSync(path.resolve(__dirname, '../../../../../key/alipay/rsa_private_key.pem')), + alipayPubKeyFile: fs.readFileSync(path.resolve(__dirname, '../../../../../key/alipay/rsa_public_key.pem')) +} + + +const service = new Alipay(config) + +/** + * 支付宝下单 + * + * @param {number} price 订单总金额,单位为元,精确到小数点后两位 + * @param {string} message 商品信息 + * @param {string} localOrderID 本地订单号 + * + */ +export async function applyOrderALI(localOrderID: string, price: number, message: string) { + const data = { + subject: message, + out_trade_no: localOrderID, + total_amount: price.toFixed(2).toString() + } + console.log('applyOrderALI :', data) + let result = await service.createOrder(data) + + // { code: 0, + // message: '请求成功', + // data: + // 'app_id=2021002142639438&biz_content=%7B%22subject%22%3A%22%E8%B5%B5%E4%BA%91%E4%BC%A0%E8%B4%AD%E4%B9%B0%E5%85%83%E5%AE%9D60%22%2C%22out_trade_no%22%3A%22bwnNLGfdCylflxKf54bEpcwyEbq7xygp%22%2C%22total_amount%22%3A%226.00%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%7D&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2×tamp=2021-05-12%2018%3A40%3A25&version=1.0&sign=S4U6JzSUiCSMvAbXeiJ2m2AQ%2BfCSr4VE4VNN9QEZtplgWIO51HIGhL24BpR4aj7mMfWO%2BqaWQnU0Fe8Uki960smBdj0%2FDpuztA7%2BIBWHK1Qj69%2FLhDNLoHZgO41jQJjIOVI0gWt1KaDlG2%2B52ghswqcZN%2FkFLwfMZCMEph3eg3aofq1mmwRbqAh8Sepoy9nCd24CmMUIbNe%2FmcxVg3xvYcWXnneWWHu%2FFbnaeZtynoHVhXqqhjFZSrxdk8lo5qyTXkE1ZoUrhJz918E2rArwzZeUL09ncPshHHvX6AygXp5BtV4clwTY0OY5yzOEXboluR5YmSaVXn0VkTWJZCTWTQ%3D%3D' + // } + console.log('applyOrderALI result: ', result) + if (result.code == 0) { + return { code: 0, data: result.data }; + } + return { code: -1, data: JSON.stringify(result) }; +} + + + +/** + * 支付宝查询支付结果 + * + * @param {number} serverId 区Id + * @param {string} roleId 角色Id + * @param {string} localOrderID 本地订单号 + * + */ +export async function checkOrderALI(localOrderID: string) { + let data = { + out_trade_no: localOrderID, + } + console.log('checkOrderALI :', data) + + let result = await service.queryOrder(data) + console.log('checkOrderALI result: ', result) + // { + // 0|app | code: '0', + // 0|app | data: { + // 0|app | code: '10000', + // 0|app | msg: 'Success', + // 0|app | buyer_logon_id: '525***@qq.com', + // 0|app | buyer_pay_amount: '0.00', + // 0|app | buyer_user_id: '2088302819007765', + // 0|app | invoice_amount: '0.00', + // 0|app | out_trade_no: 'JbyWyR1SIVIw9ArxvHAgte6tmnIzSRea', + // 0|app | point_amount: '0.00', + // 0|app | receipt_amount: '0.00', + // 0|app | send_pay_date: '2019-09-29 18:32:13', + // 0|app | total_amount: '1.00', + // 0|app | trade_no: '2019092922001407760553648380', + // 0|app | trade_status: 'TRADE_SUCCESS' + // 0|app | }, + // 0|app | message: 'success' + // 0|app | } + if ((result.code == '0') && (result.message == "success")) { + return { code: 1, data: result.data }; + } + return { code: 0, data: JSON.stringify(result) }; +} diff --git a/game-server/app/services/pay/weixinPay.ts b/game-server/app/services/pay/weixinPay.ts index fb208dbc0..cc50789ef 100644 --- a/game-server/app/services/pay/weixinPay.ts +++ b/game-server/app/services/pay/weixinPay.ts @@ -1,94 +1,94 @@ - -import tenpay = require('tenpay'); -import path = require('path'); - -/* -包名:com.bantu.sgzzyz -APPID:wx1d3cd5cd2f065358 -AppSecret:ebf099c41da57edf8693b5bb234d9b31 -商户号:1272966801 -APISECRET:ABCabc328BantuPKU726BANTUMPRCghb -*/ - -const config = { - appid: 'wx1d3cd5cd2f065358', - mchid: '1272966801', - partnerKey: 'ABCabc328BantuPKU726BANTUMPRCghb', - pfx: require('fs').readFileSync(path.resolve(__dirname, '../../../../../key/weixinpay/apiclient_cert.p12')), - notify_url: "https://" + "10.29.176.166" + "/order/weixinpaycallback",//支付回调网址 - spbill_create_ip: '127.0.0.1' -}; -// 方式一 -const api = new tenpay(config); -// 调试模式 -// const api = new tenpay(config, true); -// 沙盒模式(用于微信支付验收) -// const sandboxAPI = await tenpay.sandbox(config); - - - - -/** - * 微信下单 - * - * @param {number} price 价格订单金额(分) - * @param {string} message 商品信息 - * @param {string} localOrderID 本地订单号 - * - */ -export async function applyOrderWX(localOrderID: string, price: number, message: string) { - let data = { - out_trade_no: localOrderID, - body: message,//'商品简单描述', - total_fee: price,//'订单金额(分)', - } - console.log('applyOrderWX :', data) - let result = await api.getAppParams(data) - // { appid: 'wx1d3cd5cd2f065358', - // partnerid: '1272966801', - // prepayid: 'wx12171213153829021f7cfe9413f0a20000',//微信订单号 - // package: 'Sign=WXPay', - // noncestr: 'OohMyaHNK0iP77uh', - // timestamp: '1620810734', - // sign: '7A1B41C577E78602344D03DE4A2F7B0A' } - console.log('applyOrderWX result: ', result) - if (result.appid == config.appid && result.partnerid == config.mchid) { - return { code: 0, data: result }; - } - return { code: -1, data: JSON.stringify(result) }; -} - - - -/** - * 微信查询支付结果 - * - * @param {number} serverId 区Id - * @param {string} roleId 角色Id - * @param {string} localOrderID 本地订单号 - * - */ -export async function checkOrderWX(localOrderID: string) { - let data = { - out_trade_no: localOrderID, - } - console.log('checkOrderWX :', data) - let result = await api.orderQuery(data) - // { return_code: 'SUCCESS', - // return_msg: 'OK', - // result_code: 'SUCCESS', - // mch_id: '1272966801', - // appid: 'wx1d3cd5cd2f065358', - // device_info: '', - // trade_state: 'NOTPAY', - // total_fee: '6', - // out_trade_no: 'nMeyvwjJSmNXPmfGcr6kzalTR3jlp7jW', - // trade_state_desc: '订单未支付', - // nonce_str: 'aJevQOtSDgvNDbtQ', - // sign: '955CE5F8AA2F046DA66E0A5DA56B338A' } - console.log('checkOrderWX result: ', result) - if (result.appid == config.appid && result.mch_id == config.mchid) { - return { code: 1, data: result }; - } - return { code: 0, data: JSON.stringify(result) }; -} \ No newline at end of file + +import tenpay = require('tenpay'); +import path = require('path'); + +/* +包名:com.bantu.sgzzyz +APPID:wx1d3cd5cd2f065358 +AppSecret:ebf099c41da57edf8693b5bb234d9b31 +商户号:1272966801 +APISECRET:ABCabc328BantuPKU726BANTUMPRCghb +*/ + +const config = { + appid: 'wx1d3cd5cd2f065358', + mchid: '1272966801', + partnerKey: 'ABCabc328BantuPKU726BANTUMPRCghb', + pfx: require('fs').readFileSync(path.resolve(__dirname, '../../../../../key/weixinpay/apiclient_cert.p12')), + notify_url: "https://" + "10.29.176.166" + "/order/weixinpaycallback",//支付回调网址 + spbill_create_ip: '127.0.0.1' +}; +// 方式一 +const api = new tenpay(config); +// 调试模式 +// const api = new tenpay(config, true); +// 沙盒模式(用于微信支付验收) +// const sandboxAPI = await tenpay.sandbox(config); + + + + +/** + * 微信下单 + * + * @param {number} price 价格订单金额(分) + * @param {string} message 商品信息 + * @param {string} localOrderID 本地订单号 + * + */ +export async function applyOrderWX(localOrderID: string, price: number, message: string) { + let data = { + out_trade_no: localOrderID, + body: message,//'商品简单描述', + total_fee: price,//'订单金额(分)', + } + console.log('applyOrderWX :', data) + let result = await api.getAppParams(data) + // { appid: 'wx1d3cd5cd2f065358', + // partnerid: '1272966801', + // prepayid: 'wx12171213153829021f7cfe9413f0a20000',//微信订单号 + // package: 'Sign=WXPay', + // noncestr: 'OohMyaHNK0iP77uh', + // timestamp: '1620810734', + // sign: '7A1B41C577E78602344D03DE4A2F7B0A' } + console.log('applyOrderWX result: ', result) + if (result.appid == config.appid && result.partnerid == config.mchid) { + return { code: 0, data: result }; + } + return { code: -1, data: JSON.stringify(result) }; +} + + + +/** + * 微信查询支付结果 + * + * @param {number} serverId 区Id + * @param {string} roleId 角色Id + * @param {string} localOrderID 本地订单号 + * + */ +export async function checkOrderWX(localOrderID: string) { + let data = { + out_trade_no: localOrderID, + } + console.log('checkOrderWX :', data) + let result = await api.orderQuery(data) + // { return_code: 'SUCCESS', + // return_msg: 'OK', + // result_code: 'SUCCESS', + // mch_id: '1272966801', + // appid: 'wx1d3cd5cd2f065358', + // device_info: '', + // trade_state: 'NOTPAY', + // total_fee: '6', + // out_trade_no: 'nMeyvwjJSmNXPmfGcr6kzalTR3jlp7jW', + // trade_state_desc: '订单未支付', + // nonce_str: 'aJevQOtSDgvNDbtQ', + // sign: '955CE5F8AA2F046DA66E0A5DA56B338A' } + console.log('checkOrderWX result: ', result) + if (result.appid == config.appid && result.mch_id == config.mchid) { + return { code: 1, data: result }; + } + return { code: 0, data: JSON.stringify(result) }; +} diff --git a/game-server/app/services/playerCeService.ts b/game-server/app/services/playerCeService.ts index e5a8ec1a0..e75974945 100644 --- a/game-server/app/services/playerCeService.ts +++ b/game-server/app/services/playerCeService.ts @@ -1,639 +1,639 @@ -/** - * 体力系统 - */ - -import { EPlace, HeroModel, HeroType, HeroUpdate } from '../db/Hero'; - -import { RoleUpdate, RoleType, RoleModel } from '../db/Role'; -import { Rank } from './rankService'; -import { HERO_SYSTEM_TYPE, PUSH_ROUTE, REDIS_KEY } from '../consts'; -import { saveLadderDefCe, saveLadderDefCeByData, updateRoleOnlineInfo, updateUserInfo } from './redisService'; -import { GuildModel, GuildType } from '../db/Guild'; -import { CalCe } from './role/calCe'; -import { RoleCeModel, RoleCeUpdate } from '../db/RoleCe'; -import { PvpDefenseModel } from '../db/PvpDefense'; -import { saveCeChangeLog } from '../pubUtils/logUtil'; -import { JewelType } from '../db/Jewel'; -import { SchoolModel, SchoolType } from '../db/School'; -import { AttributeCal } from '../domain/roleField/attribute'; -import { sendMessageToUserWithSuc } from './pushService'; -import { SkinType } from '../db/Skin'; -import { LadderMatchModel } from '../db/LadderMatch'; -import { ArtifactModelType } from '../db/Artifact'; -import { GVGVestigeRankModel } from '../db/GVGVestigeRank'; -import { AuthorBookType } from '../db/AuthorBook'; -import { getResonanceDataMap } from './role/resonanceService'; - -interface Param { - isInitRole?: boolean, - hid?: number, - hero?: HeroType, - isUpStar?: boolean, - shipId?: number, - isFavourLvUp?: boolean, - ePlaceId?: number, - ePlaceIds?: number[], - jewels?: JewelType[], - jewel?: JewelType, - teraphId?: number, - schoolId?: number, - schoolHid?: number, - preSchoolHid?: number, - skinId?: number, - roleUpdate?: RoleUpdate, - role?: RoleType, - roleIncUpdate?: RoleUpdate; - heroes?: HeroType[], - schools?: SchoolType[]; - skins?: SkinType[], - stonesId?: number, - talentId?: number, - artifact?: ArtifactModelType, - artifacts?: ArtifactModelType[], - job?: number, - authorBooks?: AuthorBookType[], - bookId?: number, - subId?: number, -} - -export async function calculateCeWithHero(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, hid: number, heroUpdate: HeroUpdate, param: Param = {}) { - let heroUpdates = new Map(); - heroUpdates.set(hid, heroUpdate); - let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, param.roleUpdate||{}, param.roleIncUpdate||{}, param); - let curHero = heroes.find(cur => cur.hid == hid); - return { heroes, curHero, curRole } -} - -export async function calculateCeWithHeroes(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, heroUpdate: HeroUpdate[], param: Param = {}) { - let heroUpdates = new Map(); - for(let val of heroUpdate){ - heroUpdates.set(val.hid, val); - } - let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, param.roleUpdate||{}, param.roleIncUpdate||{}, param); - return { heroes, curRole } -} - -export async function calculateCeWithRole(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, roleUpdate: RoleUpdate, param: Param = {}) { - let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, new Map(), roleUpdate, {}, param); - return { heroes, curRole }; -} - -export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, heroUpdates: Map, roleUpdate: RoleUpdate, roleIncUpdate: RoleUpdate, param: Param = {}) { - const ceChangeTxt: string[] = []; - let calCe = new CalCe(roleId); - let roleCe = await RoleCeModel.findByRoleId(roleId); - calCe.setRoleCe(roleCe); - switch (type) { - case HERO_SYSTEM_TYPE.INIT: - { - for(let [hid, { skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, skins }] of heroUpdates) { - ceChangeTxt.push(`获得武将 ${hid}`); - calCe.setHeroBase(hid, skinId); - calCe.setHeroLv(hid, lv); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - calCe.setTalent(hid, skins) - } - // console.log('####### roleUpdate', param.isInitRole, roleUpdate) - if(param.isInitRole) { - let { title, teraphs, lv } = roleUpdate; - calCe.setRoleLv(lv) - calCe.setTitle(title); - calCe.setTeraph(teraphs); - } - break; - } - case HERO_SYSTEM_TYPE.LVUP: // 1. 升级 - { - for(let [hid, { lv }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 升级到 ${lv}`); - calCe.setHeroLv(hid, lv); - } - break; - } - case HERO_SYSTEM_TYPE.STAR: // 2. 升星 - { - for(let [hid, { star, starStage }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 升星到 ${star} 星 ${starStage} 阶`); - let { hero: { quality, job, colorStar, colorStarStage }, isUpStar } = param; - await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, isUpStar); - } - break; - } - case HERO_SYSTEM_TYPE.QUALITY: // 3. 升品 - { - for(let [hid, { quality }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 升品到 ${quality} 品`); - let { hero: { star, starStage, colorStar, colorStarStage, job } } = param; - await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, true); - } - break; - } - case HERO_SYSTEM_TYPE.COLORSTAR: // 4. 觉醒 - { - for(let [hid, { quality, colorStar, colorStarStage }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 升彩星到 ${quality} 星`); - let { hero: { star, starStage, job }, isUpStar } = param; - await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, isUpStar); - } - break; - } - case HERO_SYSTEM_TYPE.TRAIN: // 5. 训练 - case HERO_SYSTEM_TYPE.STAGEUP: // 6. 职业进阶 - { - for(let [hid, { job, jobStage }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 的职业升到 ${job} ${jobStage} 阶`); - calCe.setJob(hid, job, jobStage); - } - break; - } - case HERO_SYSTEM_TYPE.SKIN: // 7. 穿皮肤 - { - let { hero: { quality, star, starStage, colorStar, colorStarStage, jobStage }, artifact } = param; - for(let [hid, { skinId, job, ePlace, skins }] of heroUpdates) { - ceChangeTxt.push(`武将 ${hid} 穿上了皮肤 ${skinId}`); - calCe.setHeroBase(hid, skinId); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - for(let { id, equipId, quality, qualityStage, lv, star, starStage } of ePlace) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - calCe.setEquipStrength(hid, id, equipId, lv); - calCe.setEquipStar(hid, id, equipId, star, starStage); - } - calCe.setEquipSuit(hid, skinId, ePlace); - calCe.setTalent(hid, skins); - if(artifact) calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); - } - break; - } - case HERO_SYSTEM_TYPE.CONNECT: // 9. 羁绊 - { - let { shipId } = param; - for(let [ hid, { connections } ] of heroUpdates) { - let curConnect = connections?.find(cur => cur.shipId); - ceChangeTxt.push(`武将 ${hid} 的羁绊 ${shipId} 升级到 ${curConnect?.level} 级`); - calCe.setConnection(hid, connections); - } - break; - } - case HERO_SYSTEM_TYPE.ADD_SKIN: // 15. 第一次获得皮肤 - { - let { skinId } = param; - calCe.setAddSkin(skinId); - ceChangeTxt.push(`获得皮肤 ${skinId}`); - break; - } - case HERO_SYSTEM_TYPE.SCHOOL: // 16. 放百家学宫 - { - let { schoolId, schoolHid, preSchoolHid, hero } = param; - if(preSchoolHid) { - calCe.setSchool(false, preSchoolHid, schoolId, 0, 0, 0); - ceChangeTxt.push(`将武将 ${preSchoolHid} 从百家学宫移除`); - } - if(schoolHid) { - let { star, colorStar, quality } = hero; - calCe.setSchool(true, schoolHid, schoolId, star, colorStar, quality); - ceChangeTxt.push(`将武将 ${schoolHid} 放置到百家学宫`); - } - break; - } - case HERO_SYSTEM_TYPE.SCROLL: // 17. 名将谱 - { - for(let [hid, { scrollStar, scrollQuality, scrollColorStar }] of heroUpdates) { - calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); - ceChangeTxt.push(`将武将 ${hid} 的名将谱激活至 ${scrollStar}星 ${scrollQuality}品 ${scrollColorStar}彩星`); - } - break; - } - case HERO_SYSTEM_TYPE.TITLE: // 18. 爵位 - { - let { title } = roleUpdate; - calCe.setTitle(title); - ceChangeTxt.push(`爵位升级至 ${title}`); - break; - } - case HERO_SYSTEM_TYPE.TERAPH: // 19. 神像 - case HERO_SYSTEM_TYPE.TERAPH_UP: // 20. 神像进阶 - { - let { teraphId } = param; - let { teraphs } = roleUpdate; - calCe.setTeraph(teraphs); - ceChangeTxt.push(`神像 ${teraphId} 升级或进阶`); - break; - } - case HERO_SYSTEM_TYPE.COMPOSE_EQUIP: // 21. 合成装备 - { - let { ePlaceId, skinId } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, equipId, quality, qualityStage, lv, star, starStage } of ePlace) { - if(ePlaceId == id) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - calCe.setEquipStrength(hid, id, equipId, lv); - calCe.setEquipStar(hid, id, equipId, star, starStage); - ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备合成装备`); - } - } - calCe.setEquipSuit(hid, skinId, ePlace); - } - break; - } - case HERO_SYSTEM_TYPE.EQUIP_STRENGTH: // 22. 装备强化 - { - let { ePlaceIds } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, equipId, lv } of ePlace) { - if(ePlaceIds.indexOf(id) != -1) { - calCe.setEquipStrength(hid, id, equipId, lv); - ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备升级到 ${lv} 级`); - } - } - } - break; - } - case HERO_SYSTEM_TYPE.EQUIP_QUALITY: // 23. 装备升品 - { - let { ePlaceId } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, equipId, quality, qualityStage } of ePlace) { - if(ePlaceId == id) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备升级到 ${quality} 品 ${qualityStage} 阶`); - } - } - } - break; - } - case HERO_SYSTEM_TYPE.EQUIP_STAR: // 24. 装备升星 - { - let { ePlaceId, skinId } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, equipId, star, starStage } of ePlace) { - if(ePlaceId == id) { - calCe.setEquipStar(hid, id, equipId, star, starStage); - ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备精炼到 ${star} 星 ${starStage} 阶`); - } - } - calCe.setEquipSuit(hid, skinId, ePlace); - } - break; - } - case HERO_SYSTEM_TYPE.EQUIP_JEWEL: // 25. 装备天晶 - case HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE: // 27. 洗练 - case HERO_SYSTEM_TYPE.JEWEL_QUENCH: // 28. 淬炼 - { - let { ePlaceId, jewel: curJewel, skinId } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, stones } of ePlace) { - if(ePlaceId == id) { - calCe.setJewel(hid, id, stones, curJewel); - ceChangeTxt.push(`武将 ${hid} 的 ${ePlaceId} 装备栏的天晶 ${curJewel?.id} 装备或洗练或淬炼`); - } - } - calCe.setEquipSuit(hid, skinId, ePlace); - } - break; - } - case HERO_SYSTEM_TYPE.EQUIP_STONE: // 26. 装备地玉 - { - let { ePlaceId, jewel: curJewel, skinId, stonesId } = param; - for(let [hid, { ePlace = [] }] of heroUpdates) { - for(let { id, stones } of ePlace) { - if(ePlaceId == id) { - calCe.setStone(hid, ePlaceId, stones); - calCe.setJewel(hid, id, stones, curJewel); - - ceChangeTxt.push(`武将 ${hid} 的 ${ePlaceId} 装备栏装备地玉 ${stonesId}`); - } - } - calCe.setEquipSuit(hid, skinId, ePlace); - } - break; - } - case HERO_SYSTEM_TYPE.REBIRTH: // 29. 重生 - { - let { schoolId } = param; - for(let [hid, { skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, skins, scrollStar, scrollQuality, scrollColorStar, connections }] of heroUpdates) { - calCe.setHeroBase(hid, skinId); - calCe.setHeroLv(hid, lv); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - calCe.clearEquip(hid); - calCe.setTalent(hid, skins); - calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); - calCe.setConnection(hid, connections); - if(schoolId) calCe.setSchool(true, hid, schoolId, star, colorStar, quality); - - ceChangeTxt.push(`武将 ${hid} 重生`); - } - break; - } - case HERO_SYSTEM_TYPE.TALENT_UNLOCK: // 30. 天赋解锁 - case HERO_SYSTEM_TYPE.TALENT_LV: // 32. 天赋升级 - case HERO_SYSTEM_TYPE.TALENT_RESET: // 33. 天赋洗点 - { - let { talentId } = param; - for(let [hid, { skins }] of heroUpdates) { - calCe.setTalent(hid, skins); - ceChangeTxt.push(`武将 ${hid} 天赋 ${talentId} 解锁、升级、洗点`); - } - break; - } - case HERO_SYSTEM_TYPE.RE_CAL: // 31. 重新计算 - { - let { role, schools, jewels, heroes, skins, artifacts } = param; - calCe.clearRoleCe(); - for(let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, scrollStar, scrollQuality, scrollColorStar, ePlace } of heroes) { - calCe.setHeroBase(hid, skinId); - calCe.setHeroLv(hid, lv); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - calCe.setConnection(hid, connections); - calCe.setTalent(hid, skins); - for(let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - calCe.setEquipStrength(hid, id, equipId, equipLv); - calCe.setEquipStar(hid, id, equipId, star, starStage); - let curJewel = jewels.find(cur => cur.seqId == jewel); - calCe.setJewel(hid, id, stones, curJewel); - calCe.setStone(hid, id, stones); - } - let artifact = artifacts.find(cur => cur.hid == hid); - if(artifact) calCe.setPutArtifact(hid, skinId, job, artifact); - calCe.setEquipSuit(hid, skinId, ePlace); - calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); - } - - - calCe.setTitle(role.title); - calCe.setTeraph(role.teraphs); - - for(let { schoolId, hid, } of schools) { - let curHero = heroes.find(cur => cur.hid == hid); - if(curHero) calCe.setSchool(true, hid, schoolId, curHero.star, curHero.colorStar, curHero.quality); - } - - for(let { id } of skins) { - calCe.setAddSkin(id); - } - ceChangeTxt.push(`后台重新计算`); - break; - } - case HERO_SYSTEM_TYPE.PUT_ARTIFACT: // 34. 装备宝物 - { - let { artifact, job, skinId } = param; - if(!artifact) break; - for(let [hid ] of heroUpdates) { - calCe.setPutArtifact(hid, skinId, job, artifact); - // calCe.setArtifactQuality(hid, artifact.artifactId); - // calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); - ceChangeTxt.push(`武将 ${hid} 装备宝物 ${artifact.artifactId}`); - } - break; - } - case HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT: // 35. 卸下 - { - for(let [hid ] of heroUpdates) { - calCe.setPutOffArtifact(hid); - ceChangeTxt.push(`武将 ${hid} 卸下宝物`); - } - break; - } - case HERO_SYSTEM_TYPE.ARTIFACT_LV: // 36.宝物升级 - { - let { artifact } = param; - if(!artifact) break; - for(let [hid ] of heroUpdates) { - calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); - ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} ${artifact.artifactId} 升至 ${artifact.lv} 级`); - } - break; - } - case HERO_SYSTEM_TYPE.ARTIFACT_QUALITY: // 37. 宝物升品 - { - let { artifact, job, skinId } = param; - if(!artifact) break; - for(let [hid ] of heroUpdates) { - calCe.setArtifactQuality(hid, artifact.artifactId); - calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); - ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 升至 ${artifact.artifactId}`); - } - break; - } - case HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER: // 38. 宝物转换 - { - let { artifact, job, skinId } = param; - if(!artifact) break; - for(let [hid ] of heroUpdates) { - calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); - calCe.setArtifactQuality(hid, artifact.artifactId); - calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); - ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 转换至 ${artifact.artifactId}`); - } - break; - } - case HERO_SYSTEM_TYPE.ARTIFACT_REBUILD: // 39. 宝物重铸 - { - let { artifact, job, skinId } = param; - if(!artifact) break; - for(let [hid ] of heroUpdates) { - calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); - calCe.setArtifactQuality(hid, artifact.artifactId); - calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); - ceChangeTxt.push(`武将 ${hid} 装备的宝物重铸`); - } - break; - } - case HERO_SYSTEM_TYPE.AUTHOR_BOOK_STAR: // 40. 诸子百家升星 - { - let { authorBooks = [], bookId, subId } = param; - calCe.setAuthorBooks(authorBooks); - ceChangeTxt.push(`诸子列传 ${bookId} 的 ${subId} 升星`); - - break; - } - case HERO_SYSTEM_TYPE.AUTHOR_BOOK_SUB_RESET: // 41. 诸子百家重置 - { - let { authorBooks = [], bookId, subId } = param; - calCe.setAuthorBooks(authorBooks); - ceChangeTxt.push(`诸子列传 ${bookId} 的 ${subId} 重置星级`); - - break; - } - case HERO_SYSTEM_TYPE.REBORN_CAL: // 42. 重生 - { - let hids = []; - let { jewels, heroes, artifacts } = param; - for (let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, scrollStar, scrollQuality, scrollColorStar, ePlace } of heroes) { - calCe.setHeroBase(hid, skinId); - calCe.setHeroLv(hid, lv); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - calCe.setConnection(hid, connections); - calCe.setTalent(hid, skins); - calCe.clearEquip(hid); - for (let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - calCe.setEquipStrength(hid, id, equipId, equipLv); - calCe.setEquipStar(hid, id, equipId, star, starStage); - let curJewel = jewels.find(cur => cur.seqId == jewel); - calCe.setJewel(hid, id, stones, curJewel); - calCe.setStone(hid, id, stones); - } - let artifact = artifacts.find(cur => cur.hid == hid); - if (artifact) calCe.setPutArtifact(hid, skinId, job, artifact); - calCe.setEquipSuit(hid, skinId, ePlace); - hids.push(hid); - } - ceChangeTxt.push(`重生武将重新计算, 重生武将hids:${hids}`); - break; - } - case HERO_SYSTEM_TYPE.RESONANCE_CAL: // 43. 共鸣 - { - let hids = []; - let { jewels, heroes, artifacts } = param; - for (let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, ePlace } of heroes) { - calCe.setHeroBase(hid, skinId); - calCe.setHeroLv(hid, lv); - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - calCe.setJob(hid, job, jobStage); - calCe.setConnection(hid, connections); - calCe.setTalent(hid, skins); - calCe.clearEquip(hid); - for (let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { - calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); - calCe.setEquipStrength(hid, id, equipId, equipLv); - calCe.setEquipStar(hid, id, equipId, star, starStage); - let curJewel = jewels.find(cur => cur.seqId == jewel); - calCe.setJewel(hid, id, stones, curJewel); - calCe.setStone(hid, id, stones); - } - let artifact = artifacts.find(cur => cur.hid == hid); - if (artifact) calCe.setPutArtifact(hid, skinId, job, artifact); - calCe.setEquipSuit(hid, skinId, ePlace); - hids.push(hid); - } - ceChangeTxt.push(`共鸣系统武将重新计算, 重生武将hids:${hids}`); - break; - } - } - let { heroCe, roleInc } = calCe.getCeInc(); // 计算战力,获得有变化的武将战力 - let changeHids: number[] = []; - let pushHeros = new Array<{ hid: number, ce: number, incHeroCe: number, isResonance:boolean }>(); - let heroes: HeroType[] = []; - - const { dbResonanceMap } = await getResonanceDataMap(roleId); - let isResonance = false - - for(let [hid, heroUpdate] of heroUpdates) { - if(heroCe.has(hid)) { - let { ce, inc } = heroCe.get(hid); - let heroUpdate = heroUpdates.get(hid)||{}; - let hero = await HeroModel.updateHeroInfo(roleId, hid, { ...heroUpdate, ce }); - calCe.setResultHero(hero); - heroes.push(hero); - await PvpDefenseModel.updateCe(roleId, hid, ce); // 更新pvp防守阵战力 - await LadderMatchModel.updateCe(roleId, hid, ce); - await GVGVestigeRankModel.updateCe(roleId, hid, ce); - if(dbResonanceMap.has(hid)) isResonance = true; - pushHeros.push({ hid, ce, incHeroCe: inc, isResonance }); - } else { - let hero = await HeroModel.updateHeroInfo(roleId, hid, heroUpdate); - heroes.push(hero); - } - } - for(let [hid, { ce, inc }] of heroCe) { - if(changeHids.indexOf(hid) == -1) { - let hero = await HeroModel.updateHeroInfo(roleId, hid, { ce }); - await PvpDefenseModel.updateCe(roleId, hid, ce); // 更新pvp防守阵战力 - await LadderMatchModel.updateCe(roleId, hid, ce); - await GVGVestigeRankModel.updateCe(roleId, hid, ce); - if(dbResonanceMap.has(hid)) isResonance = true; - pushHeros.push({ hid, ce: hero.ce, incHeroCe: inc, isResonance }); - } - } - - let { topLineup, topLineupCe, hasTopCeChange } = calCe.getTopLineupNew(dbResonanceMap); - let roleCeUpdate: RoleCeUpdate = calCe.getRoleCeTable(); - if(topLineupCe > (roleCe?.historyLineupCe||0)) { - roleCeUpdate = { ...roleCeUpdate, historyLineupCe: topLineupCe }; - } - - roleCe = await RoleCeModel.updateRoleCe(roleId, roleCeUpdate); - let role = await RoleModel.incRoleInfo(roleId, { ...roleIncUpdate, ce: roleInc }, { ...roleUpdate, topLineup, topLineupCe }); - let guild = await GuildModel.updateCe(roleId, roleInc); // 公会更新战力 - - saveCeChangeLog(role, roleInc, role.ce, type, ceChangeTxt); - updateRank(roleId, serverId, topLineupCe, role, pushHeros, guild); - - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_CE_UPDATE, { ce: role.ce, heros: pushHeros, topLineupCe, topLineup }, sid); - if(hasTopCeChange) await updateRoleOnlineInfo(roleId, { topLineupCe }); - if(guild) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]); - } - return { heroes, curRole: role } -} - -async function treatHeroStar(calCe: CalCe, roleId: string, hid: number, star: number, starStage: number, quality: number, colorStar: number, colorStarStage: number, job: number, isUpStar: boolean) { - calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); - if(isUpStar) { - let school = await SchoolModel.findByHid(roleId, hid); - if(school) calCe.setSchool(true, hid, school.schoolId, star, colorStar, quality); - } -} - -// 更新排行榜数据 -async function updateRank(roleId: string, serverId: number, topLineupCe: number, role: RoleType, pushHeros: {hid: number, ce: number}[], guild?: GuildType) { - - // 最强阵容 - let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId }); - await r.setRankWithRoleInfo(roleId, topLineupCe, 0, role); - - // 最强武将 - for(let { hid, ce } of pushHeros) { - let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }); - await r2.setRankWithHeroInfo(roleId, hid, ce, 0); - - let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }); - await r4.setRankWithHeroInfo(roleId, hid, ce, 0); - } - - // 总战力 - let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }); - await r3.setRankWithRoleInfo(roleId, role.ce, 0, role); - - // 更新最强五人阵容信息 - let r5 = new Rank(REDIS_KEY.TOP_LINEUP_INFO, { serverId }); - await r5.generParamAndSet(REDIS_KEY.TOP_LINEUP_INFO, { roleId }, { role }); - - if(guild) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]); - } - - // 武将数量 - let r6 = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId }); - await r6.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role); - - await saveLadderDefCeByData(roleId); -} - -export async function getSumCe(roleId: string) { - let roleCe = await RoleCeModel.findByRoleId(roleId); - if(roleCe && roleCe.historyLineupCe) return roleCe.historyLineupCe; - - let role = await RoleModel.findByRoleId(roleId); - return role.topLineupCe||0; -} - -export async function getHeroesAttributes(roleId: string) { - let roleCe = await RoleCeModel.findByRoleId(roleId); - let attrByHid = new Map(); - let heroAttrs = roleCe?.heroAttrs??[]; - for(let { hid, attrs } of roleCe?.attributes??[]) { - let cal = new AttributeCal(); - let heroAttr = heroAttrs.find(cur => cur.hid == hid); - if(heroAttr) cal.setLv(heroAttr.lv); - cal.setByCeArr(attrs); - attrByHid.set(hid, cal); - } - return attrByHid; -} \ No newline at end of file +/** + * 体力系统 + */ + +import { EPlace, HeroModel, HeroType, HeroUpdate } from '@db/Hero'; + +import { RoleUpdate, RoleType, RoleModel } from '@db/Role'; +import { Rank } from './rankService'; +import { HERO_SYSTEM_TYPE, PUSH_ROUTE, REDIS_KEY } from '@consts'; +import { saveLadderDefCe, saveLadderDefCeByData, updateRoleOnlineInfo, updateUserInfo } from './redisService'; +import { GuildModel, GuildType } from '@db/Guild'; +import { CalCe } from './role/calCe'; +import { RoleCeModel, RoleCeUpdate } from '@db/RoleCe'; +import { PvpDefenseModel } from '@db/PvpDefense'; +import { saveCeChangeLog } from '@pubUtils/logUtil'; +import { JewelType } from '@db/Jewel'; +import { SchoolModel, SchoolType } from '@db/School'; +import { AttributeCal } from '@domain/roleField/attribute'; +import { sendMessageToUserWithSuc } from './pushService'; +import { SkinType } from '@db/Skin'; +import { LadderMatchModel } from '@db/LadderMatch'; +import { ArtifactModelType } from '@db/Artifact'; +import { GVGVestigeRankModel } from '@db/GVGVestigeRank'; +import { AuthorBookType } from '@db/AuthorBook'; +import { getResonanceDataMap } from './role/resonanceService'; + +interface Param { + isInitRole?: boolean, + hid?: number, + hero?: HeroType, + isUpStar?: boolean, + shipId?: number, + isFavourLvUp?: boolean, + ePlaceId?: number, + ePlaceIds?: number[], + jewels?: JewelType[], + jewel?: JewelType, + teraphId?: number, + schoolId?: number, + schoolHid?: number, + preSchoolHid?: number, + skinId?: number, + roleUpdate?: RoleUpdate, + role?: RoleType, + roleIncUpdate?: RoleUpdate; + heroes?: HeroType[], + schools?: SchoolType[]; + skins?: SkinType[], + stonesId?: number, + talentId?: number, + artifact?: ArtifactModelType, + artifacts?: ArtifactModelType[], + job?: number, + authorBooks?: AuthorBookType[], + bookId?: number, + subId?: number, +} + +export async function calculateCeWithHero(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, hid: number, heroUpdate: HeroUpdate, param: Param = {}) { + let heroUpdates = new Map(); + heroUpdates.set(hid, heroUpdate); + let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, param.roleUpdate||{}, param.roleIncUpdate||{}, param); + let curHero = heroes.find(cur => cur.hid == hid); + return { heroes, curHero, curRole } +} + +export async function calculateCeWithHeroes(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, heroUpdate: HeroUpdate[], param: Param = {}) { + let heroUpdates = new Map(); + for(let val of heroUpdate){ + heroUpdates.set(val.hid, val); + } + let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, heroUpdates, param.roleUpdate||{}, param.roleIncUpdate||{}, param); + return { heroes, curRole } +} + +export async function calculateCeWithRole(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, roleUpdate: RoleUpdate, param: Param = {}) { + let { heroes, curRole } = await calculateCes(type, roleId, serverId, sid, new Map(), roleUpdate, {}, param); + return { heroes, curRole }; +} + +export async function calculateCes(type: HERO_SYSTEM_TYPE, roleId: string, serverId: number, sid: string, heroUpdates: Map, roleUpdate: RoleUpdate, roleIncUpdate: RoleUpdate, param: Param = {}) { + const ceChangeTxt: string[] = []; + let calCe = new CalCe(roleId); + let roleCe = await RoleCeModel.findByRoleId(roleId); + calCe.setRoleCe(roleCe); + switch (type) { + case HERO_SYSTEM_TYPE.INIT: + { + for(let [hid, { skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, skins }] of heroUpdates) { + ceChangeTxt.push(`获得武将 ${hid}`); + calCe.setHeroBase(hid, skinId); + calCe.setHeroLv(hid, lv); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + calCe.setTalent(hid, skins) + } + // console.log('####### roleUpdate', param.isInitRole, roleUpdate) + if(param.isInitRole) { + let { title, teraphs, lv } = roleUpdate; + calCe.setRoleLv(lv) + calCe.setTitle(title); + calCe.setTeraph(teraphs); + } + break; + } + case HERO_SYSTEM_TYPE.LVUP: // 1. 升级 + { + for(let [hid, { lv }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 升级到 ${lv}`); + calCe.setHeroLv(hid, lv); + } + break; + } + case HERO_SYSTEM_TYPE.STAR: // 2. 升星 + { + for(let [hid, { star, starStage }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 升星到 ${star} 星 ${starStage} 阶`); + let { hero: { quality, job, colorStar, colorStarStage }, isUpStar } = param; + await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, isUpStar); + } + break; + } + case HERO_SYSTEM_TYPE.QUALITY: // 3. 升品 + { + for(let [hid, { quality }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 升品到 ${quality} 品`); + let { hero: { star, starStage, colorStar, colorStarStage, job } } = param; + await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, true); + } + break; + } + case HERO_SYSTEM_TYPE.COLORSTAR: // 4. 觉醒 + { + for(let [hid, { quality, colorStar, colorStarStage }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 升彩星到 ${quality} 星`); + let { hero: { star, starStage, job }, isUpStar } = param; + await treatHeroStar(calCe, roleId, hid, star, starStage, quality, colorStar, colorStarStage, job, isUpStar); + } + break; + } + case HERO_SYSTEM_TYPE.TRAIN: // 5. 训练 + case HERO_SYSTEM_TYPE.STAGEUP: // 6. 职业进阶 + { + for(let [hid, { job, jobStage }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 的职业升到 ${job} ${jobStage} 阶`); + calCe.setJob(hid, job, jobStage); + } + break; + } + case HERO_SYSTEM_TYPE.SKIN: // 7. 穿皮肤 + { + let { hero: { quality, star, starStage, colorStar, colorStarStage, jobStage }, artifact } = param; + for(let [hid, { skinId, job, ePlace, skins }] of heroUpdates) { + ceChangeTxt.push(`武将 ${hid} 穿上了皮肤 ${skinId}`); + calCe.setHeroBase(hid, skinId); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + for(let { id, equipId, quality, qualityStage, lv, star, starStage } of ePlace) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + calCe.setEquipStrength(hid, id, equipId, lv); + calCe.setEquipStar(hid, id, equipId, star, starStage); + } + calCe.setEquipSuit(hid, skinId, ePlace); + calCe.setTalent(hid, skins); + if(artifact) calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); + } + break; + } + case HERO_SYSTEM_TYPE.CONNECT: // 9. 羁绊 + { + let { shipId } = param; + for(let [ hid, { connections } ] of heroUpdates) { + let curConnect = connections?.find(cur => cur.shipId); + ceChangeTxt.push(`武将 ${hid} 的羁绊 ${shipId} 升级到 ${curConnect?.level} 级`); + calCe.setConnection(hid, connections); + } + break; + } + case HERO_SYSTEM_TYPE.ADD_SKIN: // 15. 第一次获得皮肤 + { + let { skinId } = param; + calCe.setAddSkin(skinId); + ceChangeTxt.push(`获得皮肤 ${skinId}`); + break; + } + case HERO_SYSTEM_TYPE.SCHOOL: // 16. 放百家学宫 + { + let { schoolId, schoolHid, preSchoolHid, hero } = param; + if(preSchoolHid) { + calCe.setSchool(false, preSchoolHid, schoolId, 0, 0, 0); + ceChangeTxt.push(`将武将 ${preSchoolHid} 从百家学宫移除`); + } + if(schoolHid) { + let { star, colorStar, quality } = hero; + calCe.setSchool(true, schoolHid, schoolId, star, colorStar, quality); + ceChangeTxt.push(`将武将 ${schoolHid} 放置到百家学宫`); + } + break; + } + case HERO_SYSTEM_TYPE.SCROLL: // 17. 名将谱 + { + for(let [hid, { scrollStar, scrollQuality, scrollColorStar }] of heroUpdates) { + calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); + ceChangeTxt.push(`将武将 ${hid} 的名将谱激活至 ${scrollStar}星 ${scrollQuality}品 ${scrollColorStar}彩星`); + } + break; + } + case HERO_SYSTEM_TYPE.TITLE: // 18. 爵位 + { + let { title } = roleUpdate; + calCe.setTitle(title); + ceChangeTxt.push(`爵位升级至 ${title}`); + break; + } + case HERO_SYSTEM_TYPE.TERAPH: // 19. 神像 + case HERO_SYSTEM_TYPE.TERAPH_UP: // 20. 神像进阶 + { + let { teraphId } = param; + let { teraphs } = roleUpdate; + calCe.setTeraph(teraphs); + ceChangeTxt.push(`神像 ${teraphId} 升级或进阶`); + break; + } + case HERO_SYSTEM_TYPE.COMPOSE_EQUIP: // 21. 合成装备 + { + let { ePlaceId, skinId } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, equipId, quality, qualityStage, lv, star, starStage } of ePlace) { + if(ePlaceId == id) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + calCe.setEquipStrength(hid, id, equipId, lv); + calCe.setEquipStar(hid, id, equipId, star, starStage); + ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备合成装备`); + } + } + calCe.setEquipSuit(hid, skinId, ePlace); + } + break; + } + case HERO_SYSTEM_TYPE.EQUIP_STRENGTH: // 22. 装备强化 + { + let { ePlaceIds } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, equipId, lv } of ePlace) { + if(ePlaceIds.indexOf(id) != -1) { + calCe.setEquipStrength(hid, id, equipId, lv); + ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备升级到 ${lv} 级`); + } + } + } + break; + } + case HERO_SYSTEM_TYPE.EQUIP_QUALITY: // 23. 装备升品 + { + let { ePlaceId } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, equipId, quality, qualityStage } of ePlace) { + if(ePlaceId == id) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备升级到 ${quality} 品 ${qualityStage} 阶`); + } + } + } + break; + } + case HERO_SYSTEM_TYPE.EQUIP_STAR: // 24. 装备升星 + { + let { ePlaceId, skinId } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, equipId, star, starStage } of ePlace) { + if(ePlaceId == id) { + calCe.setEquipStar(hid, id, equipId, star, starStage); + ceChangeTxt.push(`武将 ${hid} 的 ${equipId} 装备精炼到 ${star} 星 ${starStage} 阶`); + } + } + calCe.setEquipSuit(hid, skinId, ePlace); + } + break; + } + case HERO_SYSTEM_TYPE.EQUIP_JEWEL: // 25. 装备天晶 + case HERO_SYSTEM_TYPE.JEWEL_RESET_RANDSE: // 27. 洗练 + case HERO_SYSTEM_TYPE.JEWEL_QUENCH: // 28. 淬炼 + { + let { ePlaceId, jewel: curJewel, skinId } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, stones } of ePlace) { + if(ePlaceId == id) { + calCe.setJewel(hid, id, stones, curJewel); + ceChangeTxt.push(`武将 ${hid} 的 ${ePlaceId} 装备栏的天晶 ${curJewel?.id} 装备或洗练或淬炼`); + } + } + calCe.setEquipSuit(hid, skinId, ePlace); + } + break; + } + case HERO_SYSTEM_TYPE.EQUIP_STONE: // 26. 装备地玉 + { + let { ePlaceId, jewel: curJewel, skinId, stonesId } = param; + for(let [hid, { ePlace = [] }] of heroUpdates) { + for(let { id, stones } of ePlace) { + if(ePlaceId == id) { + calCe.setStone(hid, ePlaceId, stones); + calCe.setJewel(hid, id, stones, curJewel); + + ceChangeTxt.push(`武将 ${hid} 的 ${ePlaceId} 装备栏装备地玉 ${stonesId}`); + } + } + calCe.setEquipSuit(hid, skinId, ePlace); + } + break; + } + case HERO_SYSTEM_TYPE.REBIRTH: // 29. 重生 + { + let { schoolId } = param; + for(let [hid, { skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, skins, scrollStar, scrollQuality, scrollColorStar, connections }] of heroUpdates) { + calCe.setHeroBase(hid, skinId); + calCe.setHeroLv(hid, lv); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + calCe.clearEquip(hid); + calCe.setTalent(hid, skins); + calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); + calCe.setConnection(hid, connections); + if(schoolId) calCe.setSchool(true, hid, schoolId, star, colorStar, quality); + + ceChangeTxt.push(`武将 ${hid} 重生`); + } + break; + } + case HERO_SYSTEM_TYPE.TALENT_UNLOCK: // 30. 天赋解锁 + case HERO_SYSTEM_TYPE.TALENT_LV: // 32. 天赋升级 + case HERO_SYSTEM_TYPE.TALENT_RESET: // 33. 天赋洗点 + { + let { talentId } = param; + for(let [hid, { skins }] of heroUpdates) { + calCe.setTalent(hid, skins); + ceChangeTxt.push(`武将 ${hid} 天赋 ${talentId} 解锁、升级、洗点`); + } + break; + } + case HERO_SYSTEM_TYPE.RE_CAL: // 31. 重新计算 + { + let { role, schools, jewels, heroes, skins, artifacts } = param; + calCe.clearRoleCe(); + for(let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, scrollStar, scrollQuality, scrollColorStar, ePlace } of heroes) { + calCe.setHeroBase(hid, skinId); + calCe.setHeroLv(hid, lv); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + calCe.setConnection(hid, connections); + calCe.setTalent(hid, skins); + for(let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + calCe.setEquipStrength(hid, id, equipId, equipLv); + calCe.setEquipStar(hid, id, equipId, star, starStage); + let curJewel = jewels.find(cur => cur.seqId == jewel); + calCe.setJewel(hid, id, stones, curJewel); + calCe.setStone(hid, id, stones); + } + let artifact = artifacts.find(cur => cur.hid == hid); + if(artifact) calCe.setPutArtifact(hid, skinId, job, artifact); + calCe.setEquipSuit(hid, skinId, ePlace); + calCe.setScroll(hid, scrollStar, scrollQuality, scrollColorStar); + } + + + calCe.setTitle(role.title); + calCe.setTeraph(role.teraphs); + + for(let { schoolId, hid, } of schools) { + let curHero = heroes.find(cur => cur.hid == hid); + if(curHero) calCe.setSchool(true, hid, schoolId, curHero.star, curHero.colorStar, curHero.quality); + } + + for(let { id } of skins) { + calCe.setAddSkin(id); + } + ceChangeTxt.push(`后台重新计算`); + break; + } + case HERO_SYSTEM_TYPE.PUT_ARTIFACT: // 34. 装备宝物 + { + let { artifact, job, skinId } = param; + if(!artifact) break; + for(let [hid ] of heroUpdates) { + calCe.setPutArtifact(hid, skinId, job, artifact); + // calCe.setArtifactQuality(hid, artifact.artifactId); + // calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); + ceChangeTxt.push(`武将 ${hid} 装备宝物 ${artifact.artifactId}`); + } + break; + } + case HERO_SYSTEM_TYPE.PUT_OFF_ARTIFACT: // 35. 卸下 + { + for(let [hid ] of heroUpdates) { + calCe.setPutOffArtifact(hid); + ceChangeTxt.push(`武将 ${hid} 卸下宝物`); + } + break; + } + case HERO_SYSTEM_TYPE.ARTIFACT_LV: // 36.宝物升级 + { + let { artifact } = param; + if(!artifact) break; + for(let [hid ] of heroUpdates) { + calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); + ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} ${artifact.artifactId} 升至 ${artifact.lv} 级`); + } + break; + } + case HERO_SYSTEM_TYPE.ARTIFACT_QUALITY: // 37. 宝物升品 + { + let { artifact, job, skinId } = param; + if(!artifact) break; + for(let [hid ] of heroUpdates) { + calCe.setArtifactQuality(hid, artifact.artifactId); + calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); + ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 升至 ${artifact.artifactId}`); + } + break; + } + case HERO_SYSTEM_TYPE.ARTIFACT_TRANSFER: // 38. 宝物转换 + { + let { artifact, job, skinId } = param; + if(!artifact) break; + for(let [hid ] of heroUpdates) { + calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); + calCe.setArtifactQuality(hid, artifact.artifactId); + calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); + ceChangeTxt.push(`武将 ${hid} 装备的宝物 ${artifact.seqId} 转换至 ${artifact.artifactId}`); + } + break; + } + case HERO_SYSTEM_TYPE.ARTIFACT_REBUILD: // 39. 宝物重铸 + { + let { artifact, job, skinId } = param; + if(!artifact) break; + for(let [hid ] of heroUpdates) { + calCe.setArtifactLv(hid, artifact.artifactId, artifact.lv); + calCe.setArtifactQuality(hid, artifact.artifactId); + calCe.setArtifactSeid(hid, skinId, job, artifact.artifactId); + ceChangeTxt.push(`武将 ${hid} 装备的宝物重铸`); + } + break; + } + case HERO_SYSTEM_TYPE.AUTHOR_BOOK_STAR: // 40. 诸子百家升星 + { + let { authorBooks = [], bookId, subId } = param; + calCe.setAuthorBooks(authorBooks); + ceChangeTxt.push(`诸子列传 ${bookId} 的 ${subId} 升星`); + + break; + } + case HERO_SYSTEM_TYPE.AUTHOR_BOOK_SUB_RESET: // 41. 诸子百家重置 + { + let { authorBooks = [], bookId, subId } = param; + calCe.setAuthorBooks(authorBooks); + ceChangeTxt.push(`诸子列传 ${bookId} 的 ${subId} 重置星级`); + + break; + } + case HERO_SYSTEM_TYPE.REBORN_CAL: // 42. 重生 + { + let hids = []; + let { jewels, heroes, artifacts } = param; + for (let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, scrollStar, scrollQuality, scrollColorStar, ePlace } of heroes) { + calCe.setHeroBase(hid, skinId); + calCe.setHeroLv(hid, lv); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + calCe.setConnection(hid, connections); + calCe.setTalent(hid, skins); + calCe.clearEquip(hid); + for (let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + calCe.setEquipStrength(hid, id, equipId, equipLv); + calCe.setEquipStar(hid, id, equipId, star, starStage); + let curJewel = jewels.find(cur => cur.seqId == jewel); + calCe.setJewel(hid, id, stones, curJewel); + calCe.setStone(hid, id, stones); + } + let artifact = artifacts.find(cur => cur.hid == hid); + if (artifact) calCe.setPutArtifact(hid, skinId, job, artifact); + calCe.setEquipSuit(hid, skinId, ePlace); + hids.push(hid); + } + ceChangeTxt.push(`重生武将重新计算, 重生武将hids:${hids}`); + break; + } + case HERO_SYSTEM_TYPE.RESONANCE_CAL: // 43. 共鸣 + { + let hids = []; + let { jewels, heroes, artifacts } = param; + for (let { hid, skinId, lv, quality, star, starStage, colorStar, colorStarStage, job, jobStage, connections, skins, ePlace } of heroes) { + calCe.setHeroBase(hid, skinId); + calCe.setHeroLv(hid, lv); + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + calCe.setJob(hid, job, jobStage); + calCe.setConnection(hid, connections); + calCe.setTalent(hid, skins); + calCe.clearEquip(hid); + for (let { id, equipId, star, starStage, quality, qualityStage, lv: equipLv, stones, jewel } of ePlace) { + calCe.setEquipQuality(hid, id, equipId, quality, qualityStage); + calCe.setEquipStrength(hid, id, equipId, equipLv); + calCe.setEquipStar(hid, id, equipId, star, starStage); + let curJewel = jewels.find(cur => cur.seqId == jewel); + calCe.setJewel(hid, id, stones, curJewel); + calCe.setStone(hid, id, stones); + } + let artifact = artifacts.find(cur => cur.hid == hid); + if (artifact) calCe.setPutArtifact(hid, skinId, job, artifact); + calCe.setEquipSuit(hid, skinId, ePlace); + hids.push(hid); + } + ceChangeTxt.push(`共鸣系统武将重新计算, 重生武将hids:${hids}`); + break; + } + } + let { heroCe, roleInc } = calCe.getCeInc(); // 计算战力,获得有变化的武将战力 + let changeHids: number[] = []; + let pushHeros = new Array<{ hid: number, ce: number, incHeroCe: number, isResonance:boolean }>(); + let heroes: HeroType[] = []; + + const { dbResonanceMap } = await getResonanceDataMap(roleId); + let isResonance = false + + for(let [hid, heroUpdate] of heroUpdates) { + if(heroCe.has(hid)) { + let { ce, inc } = heroCe.get(hid); + let heroUpdate = heroUpdates.get(hid)||{}; + let hero = await HeroModel.updateHeroInfo(roleId, hid, { ...heroUpdate, ce }); + calCe.setResultHero(hero); + heroes.push(hero); + await PvpDefenseModel.updateCe(roleId, hid, ce); // 更新pvp防守阵战力 + await LadderMatchModel.updateCe(roleId, hid, ce); + await GVGVestigeRankModel.updateCe(roleId, hid, ce); + if(dbResonanceMap.has(hid)) isResonance = true; + pushHeros.push({ hid, ce, incHeroCe: inc, isResonance }); + } else { + let hero = await HeroModel.updateHeroInfo(roleId, hid, heroUpdate); + heroes.push(hero); + } + } + for(let [hid, { ce, inc }] of heroCe) { + if(changeHids.indexOf(hid) == -1) { + let hero = await HeroModel.updateHeroInfo(roleId, hid, { ce }); + await PvpDefenseModel.updateCe(roleId, hid, ce); // 更新pvp防守阵战力 + await LadderMatchModel.updateCe(roleId, hid, ce); + await GVGVestigeRankModel.updateCe(roleId, hid, ce); + if(dbResonanceMap.has(hid)) isResonance = true; + pushHeros.push({ hid, ce: hero.ce, incHeroCe: inc, isResonance }); + } + } + + let { topLineup, topLineupCe, hasTopCeChange } = calCe.getTopLineupNew(dbResonanceMap); + let roleCeUpdate: RoleCeUpdate = calCe.getRoleCeTable(); + if(topLineupCe > (roleCe?.historyLineupCe||0)) { + roleCeUpdate = { ...roleCeUpdate, historyLineupCe: topLineupCe }; + } + + roleCe = await RoleCeModel.updateRoleCe(roleId, roleCeUpdate); + let role = await RoleModel.incRoleInfo(roleId, { ...roleIncUpdate, ce: roleInc }, { ...roleUpdate, topLineup, topLineupCe }); + let guild = await GuildModel.updateCe(roleId, roleInc); // 公会更新战力 + + saveCeChangeLog(role, roleInc, role.ce, type, ceChangeTxt); + updateRank(roleId, serverId, topLineupCe, role, pushHeros, guild); + + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_CE_UPDATE, { ce: role.ce, heros: pushHeros, topLineupCe, topLineup }, sid); + if(hasTopCeChange) await updateRoleOnlineInfo(roleId, { topLineupCe }); + if(guild) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]); + } + return { heroes, curRole: role } +} + +async function treatHeroStar(calCe: CalCe, roleId: string, hid: number, star: number, starStage: number, quality: number, colorStar: number, colorStarStage: number, job: number, isUpStar: boolean) { + calCe.setHeroStar(hid, job, quality, star, starStage, colorStar, colorStarStage); + if(isUpStar) { + let school = await SchoolModel.findByHid(roleId, hid); + if(school) calCe.setSchool(true, hid, school.schoolId, star, colorStar, quality); + } +} + +// 更新排行榜数据 +async function updateRank(roleId: string, serverId: number, topLineupCe: number, role: RoleType, pushHeros: {hid: number, ce: number}[], guild?: GuildType) { + + // 最强阵容 + let r = new Rank(REDIS_KEY.TOP_LINEUP_RANK, { serverId }); + await r.setRankWithRoleInfo(roleId, topLineupCe, 0, role); + + // 最强武将 + for(let { hid, ce } of pushHeros) { + let r2 = new Rank(REDIS_KEY.TOP_HERO_RANK, { serverId }); + await r2.setRankWithHeroInfo(roleId, hid, ce, 0); + + let r4 = new Rank(REDIS_KEY.HERO_RANK, { serverId, hid }); + await r4.setRankWithHeroInfo(roleId, hid, ce, 0); + } + + // 总战力 + let r3 = new Rank(REDIS_KEY.SUM_CE_RANK, { serverId }); + await r3.setRankWithRoleInfo(roleId, role.ce, 0, role); + + // 更新最强五人阵容信息 + let r5 = new Rank(REDIS_KEY.TOP_LINEUP_INFO, { serverId }); + await r5.generParamAndSet(REDIS_KEY.TOP_LINEUP_INFO, { roleId }, { role }); + + if(guild) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }]); + } + + // 武将数量 + let r6 = new Rank(REDIS_KEY.HERO_NUM_RANK, { serverId }); + await r6.setRankWithRoleInfo(roleId, role.heroNum, role.heroNumUpdatedAt, role); + + await saveLadderDefCeByData(roleId); +} + +export async function getSumCe(roleId: string) { + let roleCe = await RoleCeModel.findByRoleId(roleId); + if(roleCe && roleCe.historyLineupCe) return roleCe.historyLineupCe; + + let role = await RoleModel.findByRoleId(roleId); + return role.topLineupCe||0; +} + +export async function getHeroesAttributes(roleId: string) { + let roleCe = await RoleCeModel.findByRoleId(roleId); + let attrByHid = new Map(); + let heroAttrs = roleCe?.heroAttrs??[]; + for(let { hid, attrs } of roleCe?.attributes??[]) { + let cal = new AttributeCal(); + let heroAttr = heroAttrs.find(cur => cur.hid == hid); + if(heroAttr) cal.setLv(heroAttr.lv); + cal.setByCeArr(attrs); + attrByHid.set(hid, cal); + } + return attrByHid; +} diff --git a/game-server/app/services/pushService.ts b/game-server/app/services/pushService.ts index b685dff88..6007954e5 100644 --- a/game-server/app/services/pushService.ts +++ b/game-server/app/services/pushService.ts @@ -1,391 +1,391 @@ -import { Channel, pinus } from "pinus"; -import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, SDK_PUSH_MSG_PLAYER_TYPE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, STATUS } from "../consts"; -import { genCode, resResult } from "../pubUtils/util"; -import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId, getGroupShopSid, getGVGAreaChannelSid, getGVGAreaTeamChannelSid, getGVGCityTeamChannelSid } from "./chatService"; -import { getAllOnlineRoles, getAllServers, getRoleOnlineInfo } from "./redisService"; -import { errlogger, infologger } from '../util/logger'; -import { MsgEncrypt } from "../pubUtils/sysUtil"; -import { isSkipEncode, needPushMsg } from "../pubUtils/sdkUtil"; -import { isDevelopEnv } from "./utilService"; -import { gameData } from "../pubUtils/data"; -import { pushMsg37 } from "./sdkService"; -import { RoleModel, RoleType } from "../db/Role"; -import { GVGLeagueModel } from "../db/GVGLeague"; - -export async function sendMessageToAllWithSuc(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { - await sendMessageToAll(route, resResult(STATUS.SUCCESS, data), filterCb); -} - -export async function sendMessageToAll(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { - let allOnlineUsers = await getAllOnlineRoles(); - if(filterCb) { - allOnlineUsers = allOnlineUsers.filter(filterCb); - } - let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批 - let sendToUser = (i: number) => { - let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); - let uids = users.map(cur => ({ uid: cur.roleId, sid: cur.sid })); - sendMessageToUsers(route, data, uids); - } - let i = -1; - sendToUser(++i); - let interval = setInterval(() => { - if (++i < n) { - sendToUser(i); - } else { - clearInterval(interval); - } - }, PUSH_INTERVAL); -} - -export async function sendMessageToAllServersWithSuc(route: string, data: any) { - let servers = await getAllServers(); - for(let serverId of servers) { - await sendMessageToServerWithSuc(serverId, route, data); - } -} - -export async function sendMessageToServerWithSuc(serverId: number, route: string, data: any, isBatch = false) { - await sendMessageToServer(serverId, route, resResult(STATUS.SUCCESS, data), isBatch); -} - -export async function sendMessageToServer(serverId: number, route: string, data: any, isBatch = false) { - let channelSid = await getWorldChannelSid(serverId); - let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data, isBatch); -} - -export async function sendMessageToGuildWithSuc(guildCode: string, route: string, data: any) { - await sendMessageToGuild(guildCode, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToGuild(guildCode: string, route: string, data: any) { - let channelSid = await getGuildChannelSid(guildCode); - let roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); -} - -export async function sendMessageToGVGAreaWithSuc(groupKey: string, areaId: number, route: string, data: any) { - let channelSid = await getGVGAreaChannelSid(groupKey, areaId); - let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToGVGAreaByTeamWithSuc(groupKey: string, areaId: number, route: string, data: any) { - let channelSid = await getGVGAreaTeamChannelSid(groupKey, areaId); - let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToGVGCityWithSuc(groupKey: string, cityId: number, route: string, data: any) { - let channelSid = await getGVGCityTeamChannelSid(groupKey, cityId); - let roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToCityWithSuc(serverId: number, cityId: number, route: string, data: any) { - await sendMessageToCity(serverId, cityId, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToCity(serverId: number, cityId: number, route: string, data: any) { - let channelSid = await getCityChannelSid(serverId, cityId); - let roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); -} - -export async function sendMessageToGroupShopWithSuc(route: string, data: any) { - let channelSid = await getGroupShopSid(); - let roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); - await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); -} - -export async function sendMessageToUserWithSuc(roleId: string, route: string, data: any, sid?: string) { - await sendMessageToUser(roleId, route, resResult(STATUS.SUCCESS, data), sid); -} - -export async function sendMessageToUser(roleId: string, route: string, data: any, sid?: string) { - let uids = []; - if (!sid) { - let onlineUser = await getRoleOnlineInfo(roleId); - sid = onlineUser.sid; - } - if (!!sid) { - uids.push({ uid: roleId, sid }); - sendMessageToUsers(route, data, uids); - } -} - -export async function sendMessageToUsersWithSuc(route: string, data: any, uids: { uid: string, sid: string }[]) { - await sendMessageToUsers(route, resResult(STATUS.SUCCESS, data), uids); -} - -// 推送给个人的方法收束于这个函数 -export async function sendMessageToUsers(route: string, data: any, uids: { uid: string, sid: string }[]) { - if(uids.length > 0) { - pinus.app.get('channelService').pushMessageByUids(route, encryptMsg(route, data), uids); - infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${uids.map(obj => obj.uid).join()}`); - } -} - -export async function sendMessageToTeam(teamCode: string, route: string, data: any) { - const channel = pinus.app.get('channelService').getChannel(teamCode); - sendMessageToChannel(channel, route, resResult(STATUS.SUCCESS, data)); -} - -/** - * - * @param user - */ - export function addUserToTeamChannel(teamCode: string, isCreate: boolean, roleId: string, sid: string) { - let channel = pinus.app.get('channelService').getChannel(teamCode, isCreate); - if(channel) addUserToChannel(channel, roleId, sid); - return channel -} - -export function addUserToChannel(channel: Channel, roleId: string, sid: string) { - let member = channel.getMember(roleId); - if(member && member.sid != sid) channel.removeMember(roleId); - const users = channel.getMembers(); - if (users.indexOf(roleId) === -1) { - channel.add(roleId, sid); - } -} - -export function sendMessgeToChannelByBatch(channel: Channel, route: string, data: any) { - let members = channel.getMembers(); - if(members.length > PUSH_BATCH) { - let n = Math.ceil(members.length / PUSH_BATCH); // 一共多少批 - // console.log(n) - let i = -1; - let interval = setInterval(() => { - if (++i < n) { - let uidlist = members.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); - let uids: { uid: string, sid: string }[] = []; - for (let uid of uidlist) { - uids.push(channel.getMember(uid)); - } - sendMessageToUsers(route, data, uids); - } else { - clearInterval(interval); - } - }, PUSH_INTERVAL); - } else { - sendMessageToChannel(channel, route, data); - } -} - - // 抽下下来pushMessage收束 -export function sendMessageToChannel(channel: Channel, route: string, data: any) { - if(channel.getMembers().length <= 0) return; - channel.pushMessage(route, encryptMsg(route, data)); - infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${channel.getMembers().join()}`); -} - -export function delTeamChannel(teamCode: string) { - let channel = pinus.app.get('channelService').getChannel(teamCode); - if(!!channel) channel.destroy(); -} - -export function removeFromTeamChannel(teamCode: string, roleId: string) { - let channel = pinus.app.get('channelService').getChannel(teamCode); - if(!channel) return null; - - let users: string[] = channel.getMembers(); - if (users.indexOf(roleId) !== -1) { - channel.removeMember(roleId); - } -} - -function getKvFromMemory() { - let aesKey = pinus.app.get('aesKey'); - let aesIV = pinus.app.get('aesIV'); - let originK = pinus.app.get('originK'); - let originV = pinus.app.get('originV'); - let kvRefTime = pinus.app.get('kvRefTime'); - let now = new Date().setMinutes(0, 0, 0); - if(!kvRefTime || now - kvRefTime >= 60 * 60 * 1000) { - originK = genCode(24); - originV = genCode(16); - let msgEncrypt = new MsgEncrypt({ k: originK, v: originV }); - ({ aesKey, aesIV } = msgEncrypt.getEncodeKv()); - - setKvToRemote(originK, originV, aesKey, aesIV, now); - } - return { aesKey, aesIV, originK, originV, now } -} - -function setKvToRemote(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - pinus.app.rpc.activity.activityRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.battle.battleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.chat.chatRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.connector.connectorRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.guild.guildRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.order.orderRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.role.roleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.systimer.systimerRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); - pinus.app.rpc.comBattle.comBattleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); -} - -export function setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { - pinus.app.set('originK', originK); - pinus.app.set('originV', originV); - pinus.app.set('aesKey', aesKey); - pinus.app.set('aesIV', aesIV); - pinus.app.set('kvRefTime', now); -} - -function encryptMsg(event: string, json: any) { - if(checkNotEncryptRoute(event)) return json - let { aesKey, aesIV, originK, originV } = getKvFromMemory(); - let msgEncrypt = new MsgEncrypt({ originK, originV }); - let data = msgEncrypt.encryptMsg(json); - return { data, k: aesKey, v: aesIV } -} - -function checkNotEncryptRoute(event: string) { - return isSkipEncode(isDevelopEnv()) || [ - PUSH_ROUTE.PUSH_CURRENT_TIME, // onPushCurrentTime 推送时间 - PUSH_ROUTE.RACE_START, // onRaceStart 粮草先行开始 - PUSH_ROUTE.GUILD_ACTIVITY_END, // onGuildActivityEnd 军团活动结束 - PUSH_ROUTE.GUILD_RACE_UPDATE, // onRaceHorseUpdate 粮草先行状态 - PUSH_ROUTE.GUILD_RACE_EVENT, // onRaceEventUpdate 更新木马事件 - PUSH_ROUTE.TEAMMATE_ACT, // onTeammateAct 寻宝队友行动 - PUSH_ROUTE.CITY_ACT_RANK, // onGuildCityRankUpdate 诸侯混战排行榜 - PUSH_ROUTE.GUILD_CITY_ACT_HP, // onGuildCityGateHpUpdate 诸侯混战城门血条 - PUSH_ROUTE.GUILD_GATE_ACT_HP, // onGuildGateHpUpdate 蛮夷入侵城门血条 - PUSH_ROUTE.GATE_ACT_RANK, // onGuildGateRankUpdate 蛮夷入侵排行榜 - PUSH_ROUTE.BOSS_HP_UPDATE, // onBossHpUpdate 演武台更新 - PUSH_ROUTE.DIVIDEND_UPDATE, // onDividendsUpdate 拍卖行分红更新 - PUSH_ROUTE.AUCTION_OVER, // onAuctionOver 拍卖价格超过 - PUSH_ROUTE.GUILD_BOSS_ENCOURAGE, // onGuildBossEncourage 鼓舞 - PUSH_ROUTE.GVG_TEAM_ATTACKED, // onTeamAttacked 当队伍受到攻击 - PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, // onMyTeamAttacked 当队伍受到攻击 - // PUSH_ROUTE.GVG_AREA_SPINE_CHANGE, // onAreaSpinesChange 可见区域内spine的变动,每隔5秒会下发 - PUSH_ROUTE.GVG_AREA_POINT_CHANGE, // onMyAreaPointChange 积分点上的驻守人变更 - PUSH_ROUTE.GVG_PLAYER_AREA_ADD, // onPlayerAddToArea 积分点上的驻守人变更 - PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, // onPlayerLeaveArea 积分点上的驻守人变更 - PUSH_ROUTE.GVG_CITY_RANK_UPDATE, // onGVGCityRankUpdate 城池积分排名 - PUSH_ROUTE.GVG_SPINE_ATTACKED, // onSpinesAttacked 队伍在地图上受到攻击 - PUSH_ROUTE.GVG_SPINE_AREA_ADD, - PUSH_ROUTE.GVG_SPINE_AREA_LEAVE, - PUSH_ROUTE.GVG_SPINE_POINT_CHANGE, - ].indexOf(event) != -1 -} - -/** - * 推送客户端下拉消息 - * @param type SDK_PUSH_MSG_TYPE - * @returns - */ - -export async function pushClientMsg(type: SDK_PUSH_MSG_TYPE) { - let dicPushMessage = gameData.dicPushMessage.get(type); - if(!dicPushMessage) return; - let targetObj = await getPushTarget(dicPushMessage.playerType); - if(!targetObj) return; - if(!needPushMsg(pinus.app.get('env'))) return; - let { target, audiences } = targetObj; - let t = Date.now(); - for(let i = 0; i < audiences.length; i++) { - let audience = audiences[i]; - // console.log(target, audience) - if(audience || target == SDK_PUSH_TARGET_TYPE.ALL ) { - await timeoutAsync(i * 10) - await pushMsg37(t.toString(), dicPushMessage, target, audience); - } - } -} - -function timeoutAsync(time: number) { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, time); - }) -} - -// 只推送all -async function getPushTarget(playerType: number): Promise<{ target: SDK_PUSH_TARGET_TYPE, audiences: string[] }> { - return { target: SDK_PUSH_TARGET_TYPE.ALL, audiences: [''] } - - // let uids: number[] = []; - // switch(playerType) { - // case SDK_PUSH_MSG_PLAYER_TYPE.HAS_GUILD: - // { uids = await getHasGuildPlayers(); break; } - // case SDK_PUSH_MSG_PLAYER_TYPE.HAS_LEAGUE: - // { uids = await getHasLeaguePlayers(); break; } - // case SDK_PUSH_MSG_PLAYER_TYPE.AFK: - // { uids = await getAfkPlayers(); break; } - // case SDK_PUSH_MSG_PLAYER_TYPE.ACTIVE_PLAYER: - // { uids = await getActivePlayers(); break; } - // } - // let len = uids.length; - // if(len == 0) return null; - // if(len == 1) return { target: SDK_PUSH_TARGET_TYPE.SINGLE, audiences: [uids.join()] }; - // let audiences: string[] = []; - // for(let i = 0; i < Math.ceil(len/200); i++) { - // audiences.push(uids.slice(i * 200, i * 200 + 200).join()) - // } - // return { target: SDK_PUSH_TARGET_TYPE.LIST, audiences }; -} - -// 有军团且24小时内登录过但当前未在线的玩家 -async function getHasGuildPlayers() { - let uids: number[] = [], players: RoleType[] = []; - let createdAt: Date; - while(!createdAt || players.length > 0) { - players = await RoleModel.findHasGuildPlayers(createdAt); - if(players.length == 0) break; - createdAt = players[players.length -1].createdAt; - players.forEach(player => { - if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); - }); - } - return uids; -} - -// 有联军且48小时内登录过但当前未在线的玩家 -async function getHasLeaguePlayers() { - let leagues = await GVGLeagueModel.findActiveLeagueMembers(); - let uids: number[] = [], roleIds: string[] = []; - for(let { members } of leagues) roleIds.push(...members.map(member => member.roleId)); - let len = roleIds.length; - for(let i = 0; i < Math.ceil(len/1000); i++) { - let curRoleIds = roleIds.slice(i * 1000, i * 1000 + 1000); - let players = await RoleModel.findByRoleIds(curRoleIds, 'userInfo.channelInfo isClosePush'); - players.forEach(player => { - if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); - }); - } - return uids; -} - -// 至少48小时未上线且等级>=20级的玩家 -async function getAfkPlayers() { - let uids: number[] = [], players: RoleType[] = []; - let createdAt: Date; - while(!createdAt || players.length > 0) { - players = await RoleModel.findAfkPlayers(createdAt); - if(players.length == 0) break; - createdAt = players[players.length -1].createdAt; - players.forEach(player => { - if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); - }); - } - return uids; -} - -// 24小时内登录过但当前未在线的玩家 -async function getActivePlayers() { - let uids: number[] = [], players: RoleType[] = []; - let createdAt: Date; - while(!createdAt || players.length > 0) { - players = await RoleModel.findActivePlayers(createdAt); - if(players.length == 0) break; - createdAt = players[players.length -1].createdAt; - players.forEach(player => { - if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime) uids.push(player.userInfo.channelInfo.uid); - }); - } - return uids; -} \ No newline at end of file +import { Channel, pinus } from "pinus"; +import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, SDK_PUSH_MSG_PLAYER_TYPE, SDK_PUSH_MSG_TYPE, SDK_PUSH_TARGET_TYPE, STATUS } from "@consts"; +import { genCode, resResult } from "@pubUtils/util"; +import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId, getGroupShopSid, getGVGAreaChannelSid, getGVGAreaTeamChannelSid, getGVGCityTeamChannelSid } from "./chatService"; +import { getAllOnlineRoles, getAllServers, getRoleOnlineInfo } from "./redisService"; +import { errlogger, infologger } from '../util/logger'; +import { MsgEncrypt } from "@pubUtils/sysUtil"; +import { isSkipEncode, needPushMsg } from "@pubUtils/sdkUtil"; +import { isDevelopEnv } from "./utilService"; +import { gameData } from "@pubUtils/data"; +import { pushMsg37 } from "./sdkService"; +import { RoleModel, RoleType } from "@db/Role"; +import { GVGLeagueModel } from "@db/GVGLeague"; + +export async function sendMessageToAllWithSuc(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { + await sendMessageToAll(route, resResult(STATUS.SUCCESS, data), filterCb); +} + +export async function sendMessageToAll(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) { + let allOnlineUsers = await getAllOnlineRoles(); + if(filterCb) { + allOnlineUsers = allOnlineUsers.filter(filterCb); + } + let n = Math.ceil(allOnlineUsers.length / PUSH_BATCH); // 一共多少批 + let sendToUser = (i: number) => { + let users = allOnlineUsers.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); + let uids = users.map(cur => ({ uid: cur.roleId, sid: cur.sid })); + sendMessageToUsers(route, data, uids); + } + let i = -1; + sendToUser(++i); + let interval = setInterval(() => { + if (++i < n) { + sendToUser(i); + } else { + clearInterval(interval); + } + }, PUSH_INTERVAL); +} + +export async function sendMessageToAllServersWithSuc(route: string, data: any) { + let servers = await getAllServers(); + for(let serverId of servers) { + await sendMessageToServerWithSuc(serverId, route, data); + } +} + +export async function sendMessageToServerWithSuc(serverId: number, route: string, data: any, isBatch = false) { + await sendMessageToServer(serverId, route, resResult(STATUS.SUCCESS, data), isBatch); +} + +export async function sendMessageToServer(serverId: number, route: string, data: any, isBatch = false) { + let channelSid = await getWorldChannelSid(serverId); + let roomId = groupRoomId(CHANNEL_PREFIX.WORLD, serverId); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data, isBatch); +} + +export async function sendMessageToGuildWithSuc(guildCode: string, route: string, data: any) { + await sendMessageToGuild(guildCode, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToGuild(guildCode: string, route: string, data: any) { + let channelSid = await getGuildChannelSid(guildCode); + let roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); +} + +export async function sendMessageToGVGAreaWithSuc(groupKey: string, areaId: number, route: string, data: any) { + let channelSid = await getGVGAreaChannelSid(groupKey, areaId); + let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREAS, `${groupKey}_${areaId}`); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToGVGAreaByTeamWithSuc(groupKey: string, areaId: number, route: string, data: any) { + let channelSid = await getGVGAreaTeamChannelSid(groupKey, areaId); + let roomId = groupRoomId(CHANNEL_PREFIX.GVG_AREA_BY_TEAM, `${groupKey}_${areaId}`); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToGVGCityWithSuc(groupKey: string, cityId: number, route: string, data: any) { + let channelSid = await getGVGCityTeamChannelSid(groupKey, cityId); + let roomId = groupRoomId(CHANNEL_PREFIX.GVG_CITY, `${groupKey}_${cityId}`); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToCityWithSuc(serverId: number, cityId: number, route: string, data: any) { + await sendMessageToCity(serverId, cityId, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToCity(serverId: number, cityId: number, route: string, data: any) { + let channelSid = await getCityChannelSid(serverId, cityId); + let roomId = groupRoomId(CHANNEL_PREFIX.CITY, `${serverId}_${cityId}`); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data); +} + +export async function sendMessageToGroupShopWithSuc(route: string, data: any) { + let channelSid = await getGroupShopSid(); + let roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP); + await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data)); +} + +export async function sendMessageToUserWithSuc(roleId: string, route: string, data: any, sid?: string) { + await sendMessageToUser(roleId, route, resResult(STATUS.SUCCESS, data), sid); +} + +export async function sendMessageToUser(roleId: string, route: string, data: any, sid?: string) { + let uids = []; + if (!sid) { + let onlineUser = await getRoleOnlineInfo(roleId); + sid = onlineUser.sid; + } + if (!!sid) { + uids.push({ uid: roleId, sid }); + sendMessageToUsers(route, data, uids); + } +} + +export async function sendMessageToUsersWithSuc(route: string, data: any, uids: { uid: string, sid: string }[]) { + await sendMessageToUsers(route, resResult(STATUS.SUCCESS, data), uids); +} + +// 推送给个人的方法收束于这个函数 +export async function sendMessageToUsers(route: string, data: any, uids: { uid: string, sid: string }[]) { + if(uids.length > 0) { + pinus.app.get('channelService').pushMessageByUids(route, encryptMsg(route, data), uids); + infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${uids.map(obj => obj.uid).join()}`); + } +} + +export async function sendMessageToTeam(teamCode: string, route: string, data: any) { + const channel = pinus.app.get('channelService').getChannel(teamCode); + sendMessageToChannel(channel, route, resResult(STATUS.SUCCESS, data)); +} + +/** + * + * @param user + */ + export function addUserToTeamChannel(teamCode: string, isCreate: boolean, roleId: string, sid: string) { + let channel = pinus.app.get('channelService').getChannel(teamCode, isCreate); + if(channel) addUserToChannel(channel, roleId, sid); + return channel +} + +export function addUserToChannel(channel: Channel, roleId: string, sid: string) { + let member = channel.getMember(roleId); + if(member && member.sid != sid) channel.removeMember(roleId); + const users = channel.getMembers(); + if (users.indexOf(roleId) === -1) { + channel.add(roleId, sid); + } +} + +export function sendMessgeToChannelByBatch(channel: Channel, route: string, data: any) { + let members = channel.getMembers(); + if(members.length > PUSH_BATCH) { + let n = Math.ceil(members.length / PUSH_BATCH); // 一共多少批 + // console.log(n) + let i = -1; + let interval = setInterval(() => { + if (++i < n) { + let uidlist = members.slice(i * PUSH_BATCH, (i + 1) * PUSH_BATCH - 1); + let uids: { uid: string, sid: string }[] = []; + for (let uid of uidlist) { + uids.push(channel.getMember(uid)); + } + sendMessageToUsers(route, data, uids); + } else { + clearInterval(interval); + } + }, PUSH_INTERVAL); + } else { + sendMessageToChannel(channel, route, data); + } +} + + // 抽下下来pushMessage收束 +export function sendMessageToChannel(channel: Channel, route: string, data: any) { + if(channel.getMembers().length <= 0) return; + channel.pushMessage(route, encryptMsg(route, data)); + infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${channel.getMembers().join()}`); +} + +export function delTeamChannel(teamCode: string) { + let channel = pinus.app.get('channelService').getChannel(teamCode); + if(!!channel) channel.destroy(); +} + +export function removeFromTeamChannel(teamCode: string, roleId: string) { + let channel = pinus.app.get('channelService').getChannel(teamCode); + if(!channel) return null; + + let users: string[] = channel.getMembers(); + if (users.indexOf(roleId) !== -1) { + channel.removeMember(roleId); + } +} + +function getKvFromMemory() { + let aesKey = pinus.app.get('aesKey'); + let aesIV = pinus.app.get('aesIV'); + let originK = pinus.app.get('originK'); + let originV = pinus.app.get('originV'); + let kvRefTime = pinus.app.get('kvRefTime'); + let now = new Date().setMinutes(0, 0, 0); + if(!kvRefTime || now - kvRefTime >= 60 * 60 * 1000) { + originK = genCode(24); + originV = genCode(16); + let msgEncrypt = new MsgEncrypt({ k: originK, v: originV }); + ({ aesKey, aesIV } = msgEncrypt.getEncodeKv()); + + setKvToRemote(originK, originV, aesKey, aesIV, now); + } + return { aesKey, aesIV, originK, originV, now } +} + +function setKvToRemote(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + pinus.app.rpc.activity.activityRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.battle.battleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.chat.chatRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.connector.connectorRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.guild.guildRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.order.orderRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.role.roleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.systimer.systimerRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); + pinus.app.rpc.comBattle.comBattleRemote.setKvToMemory.broadcast(originK, originV, aesKey, aesIV, now); +} + +export function setKvToMemory(originK: string, originV: string, aesKey: string, aesIV: string, now: number) { + pinus.app.set('originK', originK); + pinus.app.set('originV', originV); + pinus.app.set('aesKey', aesKey); + pinus.app.set('aesIV', aesIV); + pinus.app.set('kvRefTime', now); +} + +function encryptMsg(event: string, json: any) { + if(checkNotEncryptRoute(event)) return json + let { aesKey, aesIV, originK, originV } = getKvFromMemory(); + let msgEncrypt = new MsgEncrypt({ originK, originV }); + let data = msgEncrypt.encryptMsg(json); + return { data, k: aesKey, v: aesIV } +} + +function checkNotEncryptRoute(event: string) { + return isSkipEncode(isDevelopEnv()) || [ + PUSH_ROUTE.PUSH_CURRENT_TIME, // onPushCurrentTime 推送时间 + PUSH_ROUTE.RACE_START, // onRaceStart 粮草先行开始 + PUSH_ROUTE.GUILD_ACTIVITY_END, // onGuildActivityEnd 军团活动结束 + PUSH_ROUTE.GUILD_RACE_UPDATE, // onRaceHorseUpdate 粮草先行状态 + PUSH_ROUTE.GUILD_RACE_EVENT, // onRaceEventUpdate 更新木马事件 + PUSH_ROUTE.TEAMMATE_ACT, // onTeammateAct 寻宝队友行动 + PUSH_ROUTE.CITY_ACT_RANK, // onGuildCityRankUpdate 诸侯混战排行榜 + PUSH_ROUTE.GUILD_CITY_ACT_HP, // onGuildCityGateHpUpdate 诸侯混战城门血条 + PUSH_ROUTE.GUILD_GATE_ACT_HP, // onGuildGateHpUpdate 蛮夷入侵城门血条 + PUSH_ROUTE.GATE_ACT_RANK, // onGuildGateRankUpdate 蛮夷入侵排行榜 + PUSH_ROUTE.BOSS_HP_UPDATE, // onBossHpUpdate 演武台更新 + PUSH_ROUTE.DIVIDEND_UPDATE, // onDividendsUpdate 拍卖行分红更新 + PUSH_ROUTE.AUCTION_OVER, // onAuctionOver 拍卖价格超过 + PUSH_ROUTE.GUILD_BOSS_ENCOURAGE, // onGuildBossEncourage 鼓舞 + PUSH_ROUTE.GVG_TEAM_ATTACKED, // onTeamAttacked 当队伍受到攻击 + PUSH_ROUTE.GVG_MY_TEAM_ATTACKED, // onMyTeamAttacked 当队伍受到攻击 + // PUSH_ROUTE.GVG_AREA_SPINE_CHANGE, // onAreaSpinesChange 可见区域内spine的变动,每隔5秒会下发 + PUSH_ROUTE.GVG_AREA_POINT_CHANGE, // onMyAreaPointChange 积分点上的驻守人变更 + PUSH_ROUTE.GVG_PLAYER_AREA_ADD, // onPlayerAddToArea 积分点上的驻守人变更 + PUSH_ROUTE.GVG_PLAYER_LEAVE_AREA, // onPlayerLeaveArea 积分点上的驻守人变更 + PUSH_ROUTE.GVG_CITY_RANK_UPDATE, // onGVGCityRankUpdate 城池积分排名 + PUSH_ROUTE.GVG_SPINE_ATTACKED, // onSpinesAttacked 队伍在地图上受到攻击 + PUSH_ROUTE.GVG_SPINE_AREA_ADD, + PUSH_ROUTE.GVG_SPINE_AREA_LEAVE, + PUSH_ROUTE.GVG_SPINE_POINT_CHANGE, + ].indexOf(event) != -1 +} + +/** + * 推送客户端下拉消息 + * @param type SDK_PUSH_MSG_TYPE + * @returns + */ + +export async function pushClientMsg(type: SDK_PUSH_MSG_TYPE) { + let dicPushMessage = gameData.dicPushMessage.get(type); + if(!dicPushMessage) return; + let targetObj = await getPushTarget(dicPushMessage.playerType); + if(!targetObj) return; + if(!needPushMsg(pinus.app.get('env'))) return; + let { target, audiences } = targetObj; + let t = Date.now(); + for(let i = 0; i < audiences.length; i++) { + let audience = audiences[i]; + // console.log(target, audience) + if(audience || target == SDK_PUSH_TARGET_TYPE.ALL ) { + await timeoutAsync(i * 10) + await pushMsg37(t.toString(), dicPushMessage, target, audience); + } + } +} + +function timeoutAsync(time: number) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, time); + }) +} + +// 只推送all +async function getPushTarget(playerType: number): Promise<{ target: SDK_PUSH_TARGET_TYPE, audiences: string[] }> { + return { target: SDK_PUSH_TARGET_TYPE.ALL, audiences: [''] } + + // let uids: number[] = []; + // switch(playerType) { + // case SDK_PUSH_MSG_PLAYER_TYPE.HAS_GUILD: + // { uids = await getHasGuildPlayers(); break; } + // case SDK_PUSH_MSG_PLAYER_TYPE.HAS_LEAGUE: + // { uids = await getHasLeaguePlayers(); break; } + // case SDK_PUSH_MSG_PLAYER_TYPE.AFK: + // { uids = await getAfkPlayers(); break; } + // case SDK_PUSH_MSG_PLAYER_TYPE.ACTIVE_PLAYER: + // { uids = await getActivePlayers(); break; } + // } + // let len = uids.length; + // if(len == 0) return null; + // if(len == 1) return { target: SDK_PUSH_TARGET_TYPE.SINGLE, audiences: [uids.join()] }; + // let audiences: string[] = []; + // for(let i = 0; i < Math.ceil(len/200); i++) { + // audiences.push(uids.slice(i * 200, i * 200 + 200).join()) + // } + // return { target: SDK_PUSH_TARGET_TYPE.LIST, audiences }; +} + +// 有军团且24小时内登录过但当前未在线的玩家 +async function getHasGuildPlayers() { + let uids: number[] = [], players: RoleType[] = []; + let createdAt: Date; + while(!createdAt || players.length > 0) { + players = await RoleModel.findHasGuildPlayers(createdAt); + if(players.length == 0) break; + createdAt = players[players.length -1].createdAt; + players.forEach(player => { + if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); + }); + } + return uids; +} + +// 有联军且48小时内登录过但当前未在线的玩家 +async function getHasLeaguePlayers() { + let leagues = await GVGLeagueModel.findActiveLeagueMembers(); + let uids: number[] = [], roleIds: string[] = []; + for(let { members } of leagues) roleIds.push(...members.map(member => member.roleId)); + let len = roleIds.length; + for(let i = 0; i < Math.ceil(len/1000); i++) { + let curRoleIds = roleIds.slice(i * 1000, i * 1000 + 1000); + let players = await RoleModel.findByRoleIds(curRoleIds, 'userInfo.channelInfo isClosePush'); + players.forEach(player => { + if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); + }); + } + return uids; +} + +// 至少48小时未上线且等级>=20级的玩家 +async function getAfkPlayers() { + let uids: number[] = [], players: RoleType[] = []; + let createdAt: Date; + while(!createdAt || players.length > 0) { + players = await RoleModel.findAfkPlayers(createdAt); + if(players.length == 0) break; + createdAt = players[players.length -1].createdAt; + players.forEach(player => { + if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime && !player.isClosePush) uids.push(player.userInfo.channelInfo.uid); + }); + } + return uids; +} + +// 24小时内登录过但当前未在线的玩家 +async function getActivePlayers() { + let uids: number[] = [], players: RoleType[] = []; + let createdAt: Date; + while(!createdAt || players.length > 0) { + players = await RoleModel.findActivePlayers(createdAt); + if(players.length == 0) break; + createdAt = players[players.length -1].createdAt; + players.forEach(player => { + if(player.userInfo && player.userInfo.channelInfo && player.quitTime != player.loginTime) uids.push(player.userInfo.channelInfo.uid); + }); + } + return uids; +} diff --git a/game-server/app/services/pvpService.ts b/game-server/app/services/pvpService.ts index 066969d9f..c6dd02439 100644 --- a/game-server/app/services/pvpService.ts +++ b/game-server/app/services/pvpService.ts @@ -1,807 +1,807 @@ - -import { PvpDefenseModel, PvpDefenseType, pvpUpdateInter } from '../db/PvpDefense'; -import { Defense, Attack, LineupCe, OppPlayer, HeroScore, HeroReward, OppPlayerReturn, AttackHero, DefenseHero } from '../domain/battleField/pvp'; -import { RoleType } from '../db/Role'; -import { REDIS_KEY, TASK_TYPE, MAIL_TYPE, TA_EVENT, ITID, getHeadItid, getFrameItid, getSpineItid, PVP_SEASON_STATUS, SHOP_REFRESH_TYPE } from '../consts'; -import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent"; -import { getRandSingleIndex, genCode, shouldRefresh, getChineseName, makeRobotId, robotIdComBack, getRandSingleEelm } from '../pubUtils/util'; -import { pvpEndParamInter, RewardInter } from '../pubUtils/interface'; -import { gameData, getPLvByScore, getPvpHeroRewardsByScore, getPvpRankRewardsByRank, getPvpDifficultByScore, getPlvAndScore, getPvpBoxsBySeasonNum, getPvpRankMaxRewardsBySeasonNum, randomGoodsByItid } from "../pubUtils/data"; -import { EXTERIOR, PVP } from '../pubUtils/dicParam'; -import { PVPConfigModel } from '../db/PvpConfig' -import { nowSeconds, getTimeFun, getZeroPointD } from '../pubUtils/timeUtil'; -import { HeroesRecord, PvpRecordPlayerInfo } from '../db/PvpRecord'; -import { HeroModel, HeroType } from '../db/Hero'; -import { AttributeCal } from '../domain/roleField/attribute'; -import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral'; -import { pinus } from 'pinus'; -import { PvpHistoryOppModel, PvpHistoryOppType, PvpOppCreateParam } from '../db/PvpHistoryOpp'; -import { Rank } from './rankService'; -import { DicRankRewads } from '../pubUtils/dictionary/DicPvpRankReward'; -import { PvpSeasonResultModel, PvpSeasonResultType } from '../db/PvpSeasonResult'; -import { checkTask } from './task/taskService'; -import { sendMailByContent } from './mailService'; -import { RoleRankInfo } from '../domain/rank'; -import { reportTAEvent } from './sdkService'; -import { getVipPvpChallengeMaxCnt } from './activity/monthlyTicketService'; -import { getHeroesAttributes } from './playerCeService'; -import { setPvpSettleSeasonNumToRemote } from './timeTaskService'; -import { ArtifactModel } from '../db/Artifact'; -import { getPVPGroupIdOfServer, getPvpServersByGroupId } from './serverService'; -import { findKeys } from './redisService'; -import { JewelModel } from '../db/Jewel'; - -/** - * 返回对手三人信息 - * - * @param oppPlayers pvpDefense表中的oppPlayers字段,需要populate过的 - * @param pLv 玩家本人的队伍等级 - */ -export async function getEnemies(r: Rank, oppPlayers: OppPlayer[], winStreakNum: number) { - - let result = new Array(); - for (let oppPlayer of oppPlayers) { - let dicOpponent = dicPvpOpponent.get(oppPlayer.pos); - if(!dicOpponent) continue; - let oppDef = oppPlayer.oppDef; // select 'oppRoleId pos roleName head frame spine rankLv pLv defCe' - - if (oppDef) delete oppDef.heroes; - let myRank = await r.getMyRank({ roleId: robotIdComBack(oppDef.oppRoleId) });//去redis中获取排名 - result.push({ - ...oppDef, - roleId: oppDef.oppRoleId, - defCe: oppDef.defCe, - addScore: dicOpponent.score, - rankLv: myRank||0, - plusScore: getPlusScore(winStreakNum) - }); - } - return result -} - -/** - * @description 刷新对手三个人 - * @param role 数据库里我的role - * @param score 我的军功 - * @param pLv 我的排名 - */ -export async function refreshEnemies(role: RoleType, seasonNum: number, sumScore: number, score: number, pLv: number) { - let { roleId, serverId } = role; - let groupId = await getPVPGroupIdOfServer(serverId); - let chosenOpps: string[] = []; - let pvpHistoryOppParam: PvpOppCreateParam[] = []; - for(let pos = 1; pos <= 3; pos++) { - let dicOpp = gameData.pvpOpponent.get(pos); - if(!dicOpp) continue; - let pvpHistoryOpp: PvpOppCreateParam; // 是否筛选成功 - if (sumScore >= PVP.PVP_MATCH_ROBOT) { - pvpHistoryOpp = await matchPlayer(groupId, seasonNum, chosenOpps, roleId, pLv, dicOpp); // 按照等级匹配对手 - if (!pvpHistoryOpp) pvpHistoryOpp = await matchPlayerByRank(groupId, seasonNum, chosenOpps, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家 - if (!pvpHistoryOpp) pvpHistoryOpp = await matchRobot(chosenOpps, role, score, dicOpp); - } else { - pvpHistoryOpp = await matchRobot(chosenOpps, role, score, dicOpp); - } - if (!pvpHistoryOpp) continue; - pvpHistoryOppParam.push(pvpHistoryOpp); - } - - let oppPlayers: OppPlayer[] = []; - pvpHistoryOppParam.sort((a, b) => { - if(a.pLv != b.pLv) return b.pLv - a.pLv; - return b.defCe - a.defCe; - }); - for(let i = 0; i < pvpHistoryOppParam.length; i++) { - let param = pvpHistoryOppParam[i]; - param.pos = i + 1; - let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp(param); - oppPlayers.push({ - roleId: pvpHistoryOpp.oppRoleId, - oppDef: pvpHistoryOpp._id, - isRobot: pvpHistoryOpp.isRobot, - pos: pvpHistoryOpp.pos, - }); - } - if(dicPvpOpponent.size > 3 && !pinus.app.get('dicPvpOpponent')) { - pinus.app.set('dicPvpOpponent', dicPvpOpponent); - } - return oppPlayers; -} - -export async function matchPlayerByRank(groupId: number, seasonNum: number, chosenOpps: string[], roleId: string, pos: number) { - // console.log('matchPlayerByRank', JSON.stringify(oppPlayers)) - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let ridRanks = new Array(); // 已经被使用了的排名 - for (let curRoleId of chosenOpps) { - let rankLv = await r.getMyRank({ roleId: robotIdComBack(curRoleId) }); - ridRanks.push(rankLv); - } - - let myRank = await r.getMyRank({ roleId }); - ridRanks.push(myRank); - - let oppRoleId = ''; - let oppRank = 0; - if (myRank == 0) { - return null - } else if (myRank == 1) { // 第一名 - if (pos == 1) { - oppRank = 2; - while (ridRanks.includes(oppRank)) { - oppRank--; - } - } else if (pos == 2) { - oppRank = 3; - while (ridRanks.includes(oppRank)) { - oppRank--; - } - } else { - oppRank = 4; - while (ridRanks.includes(oppRank)) { - oppRank++; - } - } - } else if (myRank == 2) { // 第二名 - if (pos == 1) { - oppRank = 1; - while (ridRanks.includes(oppRank)) { - oppRank--; - } - } else if (pos == 2) { - oppRank = 3; - while (ridRanks.includes(oppRank)) { - oppRank++; - } - } else { - oppRank = 4; - while (ridRanks.includes(oppRank)) { - oppRank++; - } - } - } else { - if (pos == 1 || pos == 2) { // 刷新我前一名 - oppRank = myRank - 1; - while (ridRanks.includes(oppRank)) { - oppRank--; - } - } else { // 刷新我后一名 - oppRank = myRank + 1; - while (ridRanks.includes(oppRank)) { - oppRank++; - } - } - } - if(oppRank <= 0) return null; - let result = await r.getUserByRank(oppRank); - if (result.length <= 0) return null; - oppRoleId = result[0]; - - let pvpdefense = await PvpDefenseModel.findByRoleIdIncludeAll(oppRoleId); - if (!pvpdefense || pvpdefense.seasonNum != seasonNum || !pvpdefense.hasDefense) return null; - let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, roleId, pos, groupId); - if (!pvpHistoryOpp) return null; - - chosenOpps.push(pvpHistoryOpp.oppRoleId); - return pvpHistoryOpp; -} - -async function matchPlayer(groupId: number, seasonNum: number, chosenOpps: string[], roleId: string, pLv: number, dicOpp: DicPvpOpponent) { - // console.log('matchPlayer', JSON.stringify(oppPlayers)) - - let serverIds = await getPvpServersByGroupId(groupId); - let { id: pos, minLv, maxLv } = dicOpp; - let min = pLv + minLv > 1? pLv + minLv: 1; - let max = pLv + maxLv > 1? pLv + maxLv: 1; - let range = await PvpDefenseModel.findByTeamLv(serverIds, seasonNum, min, max); - range = range.filter(cur => { - return chosenOpps.indexOf(makeRobotId(cur.roleId)) == -1; - }); - if (range.length <= 0) return null; - - let index = getRandSingleIndex(range.length); - let result = range[index]; // 本次匹配结果 pvpdefense - if (!result) return null; - if (result.roleId == roleId) { - range.splice(index, 1); - if (range.length <= 0) return null; - index = getRandSingleIndex(range.length); - result = range[index]; - } - let pvpHistoryOpp = await generPlayerOppHis(result, roleId, pos, groupId); - if (!pvpHistoryOpp) return null; - - chosenOpps.push(pvpHistoryOpp.oppRoleId); - return pvpHistoryOpp; -} - -/** - * @description 对手是玩家时,生成并返回pvpHistoryOpp - * @param result 随机出的对手pvpDefense - * @param roleId 自己的玩家id - * @param pos 刷新这个对手的位置 - */ -async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos: number, groupId: number) { - let { heroScores, defense } = pvpdefense; - if(!defense) return false; - let { warId, heroes: defenseHeroes } = defense; - let role = pvpdefense.role; - - let seasonNum: number = pinus.app.get('pvpSeasonNum'); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - let rankLv = await r.getMyRank({ roleId: role.roleId }); - let dbHeroes = await HeroModel.findByRole(role.roleId, [{ field: 'ce', sortBy: -1 }]); - let heroes = new Array(); - let otherHeroes = new Array(); // 阵容外的所有武将信息 - let defCe = 0; - let attrByHid = await getHeroesAttributes(role.roleId); - let hids = defenseHeroes.map(cur => cur.actorId); - - let artifacts = await ArtifactModel.findbyHids(role.roleId, hids); - let jewels = await JewelModel.findbyRoleAndHids(role.roleId, hids); - - for (let dbHero of dbHeroes) { - let artifact = dbHero.artifact? artifacts.find(cur => cur.seqId == dbHero.artifact): null; - let h = defenseHeroes.find(cur => cur.actorId == dbHero.hid); // 阵容里是否有这个武将 - let hs = heroScores.find(cur => cur.hid == dbHero.hid); // 这个武将是否有这个得分 - if (!!h) { - let dicWar = gameData.war.get(warId); - let mapWarJson = gameData.warJson.get(dicWar.dispatchJsonId); - let warJson = mapWarJson.find(cur => cur.dataId == h.dataId); - if (warJson && warJson.relation == 2) { - let heroInfo = new PvpHeroInfo(); - heroInfo.setHeroInfo(dbHero, artifact, dbHero.ePlace.map(cur => ({ ...cur, jewel: jewels.find(ccur => cur.jewel == ccur.seqId) }))); - // heroInfo.setOutIndex(h.order); - let attr = attrByHid.get(h.actorId); - if(!attr) continue; - let attribute = attr.getAttributesToString(); - let ce = attr.calCe(); - if(isNaN(ce)) ce = 0; - heroInfo.setAttribute(attribute); - let subHero = h.subHid? dbHeroes.find(hero => hero.hid == h.subHid): null; - let enemy = new PvpEnemies(warJson, heroInfo, hs ? hs.score : 0, ce, subHero); - enemy.setOutIndex(h.order); - enemy.initial_ai = h.ai; - heroes.push(enemy); - defCe += ce; - } - } else { - let heroInfo = new PvpOtherHeroes(hs ? hs.score : 0); - heroInfo.setHeroInfo(dbHero, artifact); - otherHeroes.push(heroInfo); - } - } - heroes.sort((a, b) => b.score - a.score); - otherHeroes.sort((a, b) => b.score - a.score); - - return { - isRobot: false, ...defense, defCe, ...role, pos, rankLv, heroes, otherHeroes, roleId, oppRoleId: makeRobotId(pvpdefense.roleId) - }; -} - -async function matchRobot(chosenOpps: string[], role: RoleType, score: number, dicOpp: DicPvpOpponent) { - // console.log('matchRobot', JSON.stringify(oppPlayers)) - - let { lv: myLv, roleId } = role; - let { id: pos, minLv, maxLv, ratio } = dicOpp; - - let pvpConfig = await PVPConfigModel.findCurPVPConfig(); - let range = pvpConfig?.warIds||[]; - let warId = getRandSingleEelm(range); - if (!warId) return null; - let result = gameData.war.get(warId); - if (!result) return null; - - let robotWarjson = gameData.warJson.get(result.dispatchJsonId); - if (!robotWarjson) return null - let heroes: PvpEnemies[] = []; - let defCe = 0; - for (let h of robotWarjson) { - if (h.relation == 1) continue; - let actorId = h.randomEnemy.length > 0? getRandSingleEelm(h.randomEnemy): 0; - let dicHero = gameData.hero.get(actorId); - if (!dicHero) continue; - let heroInfo = new PvpHeroInfo(); - let robotInfo = getRobotAttribute(actorId, ratio, score); - if(!robotInfo) continue; - let { attribute, ce, lv } = robotInfo; - heroInfo.setRobotInfo(dicHero, lv); - defCe += ce; - heroInfo.setAttribute(attribute); - let enemy = new PvpEnemies(h, heroInfo, 0, ce); - enemy.setOutIndex(h.outIndex); - heroes.push(enemy); - } - - let oppRoleId = generateRobotRoleId(); - chosenOpps.push(oppRoleId); - let roleName = getChineseName(); - let pLv = getPLvByScore(score); - let hisPLv = Math.floor(pLv + (minLv + maxLv) / 2); - if (hisPLv < 1) hisPLv = 1 - return { - isRobot: true, roleId, oppRoleId, roleName, pos, defCe, pLv: hisPLv, lv: myLv, heroes, rankLv: 0, warId: result.war_id, buff: getRandSingleEelm(result.mapseid)||0, - head: randomHead(), frame: randomFrame(), spine: randomSpine() - }; -} - -function randomHead() { - return randomGoodsByItid(getHeadItid())||EXTERIOR.EXTERIOR_FACE; -} - -function randomFrame() { - return randomGoodsByItid(getFrameItid())||EXTERIOR.EXTERIOR_FACECASE; -} - -function randomSpine() { - return randomGoodsByItid(getSpineItid())||EXTERIOR.EXTERIOR_APPEARANCE; -} - -// 生成机器人roleId -function generateRobotRoleId() { - return `${genCode(10)}_r`; -} - -// 根据连胜次数,获得加成的积分 -export function getPlusScore(win: number) { - let result = win - 1; - if (result < 0) result = 0; - if (result > PVP.PVP_WINREWARD_UPLIMIT) result = PVP.PVP_WINREWARD_UPLIMIT; - return result; -} - -export function getLvByScore(heroScores: HeroScore[]) { - heroScores.sort((a, b) => b.score - a.score); - let score = 0; - for (let i = 0; i < 5; i++) { - if (!heroScores[i]) break; - score += heroScores[i].score; - } - return getPLvByScore(score); -} - -export async function refChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number, roleId: string, vipStartTime?: number) { - let hasChanged = false; - let initCount = await getVipPvpChallengeMaxCnt(roleId, vipStartTime) - if (challengeCnt >= initCount) { - return { hasChanged, challengeCnt, challengeRefTime: nowSeconds() }; - } - let period = PVP.PVP_CHALLENGE_NORMALTIMES * 60; - if (getTimeFun(seasonEndTime).checkDay()) { - period = PVP.PVP_CHALLENGE_FINALTIMES * 60; - } - let time = nowSeconds(); - let num = Math.floor((time - challengeRefTime) / period); - if (num > 0) { - challengeCnt += num; - challengeRefTime = challengeRefTime + period * num; - hasChanged = true; - } - if(challengeCnt > initCount) challengeCnt = initCount; - return { hasChanged, challengeCnt, challengeRefTime }; -} - -export async function comsumeChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number, roleId: string) { - let initCount = await getVipPvpChallengeMaxCnt(roleId) - - challengeCnt--; - if (challengeCnt >= initCount) { - return { challengeCnt, challengeRefTime }; - } - if (challengeCnt == initCount - 1) { - challengeRefTime = nowSeconds(); - return { challengeCnt, challengeRefTime }; - } - return refChallengeCnt(challengeCnt, challengeRefTime, seasonEndTime, roleId); -} - -export async function sendLastSeasonRewardIfNotSent(pvpDefense: PvpDefenseType) { - let seasonSettleNum: number = pinus.app.get('pvpSettleSeasonNum'); - console.log('##### sendLastSeasonRewardIfNotSent seasonSettleNum', pvpDefense.roleId, pvpDefense.rankSeasonNum, seasonSettleNum) - if(seasonSettleNum && pvpDefense.rankSeasonNum <= seasonSettleNum) { - let oldPvpCongig = await PVPConfigModel.findPVPConfig(seasonSettleNum); - let result = await sendPVPRewardToUser(pvpDefense, seasonSettleNum, oldPvpCongig.seasonEndTime); - pvpDefense = result.pvpDefense; - } - return pvpDefense; -} - -// async function checkHasSettled(seasonSettleNum: number, roleId: string) { -// let hasData = await PvpSeasonResultModel.checkResultBySeasonNum(roleId, seasonSettleNum); -// return hasData; -// } - -// 获取刷新对手次数及消耗 -export function refreshRefOppCnt(pvpDefense: PvpDefenseType) { - let { refOppCnt = 0, setAttackCnt = 0, buyAttackCnt = 0, refDaily } = pvpDefense; - let curTime = new Date(); - let shouldRefOpp = shouldRefresh(refDaily, curTime); - if (shouldRefOpp) { - refOppCnt = 0; setAttackCnt = 0; buyAttackCnt =0; refDaily = curTime; - } - return { - shouldRefOpp, - refOppCnt, refDaily, setAttackCnt, buyAttackCnt, - consume: gameData.pvpRefreshConsume.get(refOppCnt + 1) - } -} - - -/** - * 根据比例计算机器人属性 - * @param attribute 出兵表中的属性字段 - * @param ce 我的战力 - * @param enemyCe 出兵表对手战力 - * @param ratio 系数 - */ -export function getRobotAttribute(hid: number, posRatio: number, score: number) { - - let difficultRatio = getPvpDifficultByScore(score); - if(!difficultRatio) return null - let dicHero = gameData.hero.get(hid); - - let newAttribute = new AttributeCal(); - newAttribute.setLv(difficultRatio.enemyLv); - newAttribute.setByMap(hid, dicHero.baseAbilityArr, difficultRatio.value / 10000 * posRatio); - let subAttr = gameData.towerPvpSubAttr.get(difficultRatio.secondAttrLevel); - if(subAttr) newAttribute.setByWarJson(hid, subAttr.secondAtr); - let attrArr = newAttribute.getAttributesToString(); - let newCe = newAttribute.calCe(); - return { attribute: attrArr, ce: newCe, lv: difficultRatio.enemyLv }; -} - -// 获取我方战报记录 -export async function generMyRecInfo(pvpDefense: PvpDefenseType, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) { - let { attack, defense, heroScores, winStreakNum, hisWinStreakNum = 0, score, hisScore, seasonWinNum = 0 } = pvpDefense; - let { roleId } = role; - if (isSuccess) { - winStreakNum ++; - seasonWinNum ++; - } else { - winStreakNum = 0; - } - if(winStreakNum > hisWinStreakNum) { - hisWinStreakNum = winStreakNum; - } - - const dicOpp = gameData.pvpOpponent.get(pos); - const plusScore = getPlusScore(winStreakNum); - - let myHeroRecords: HeroesRecord[] = []; // 存入rec里面的数据 - let showHeroScores = new Array<{ hid: number, addScore: number, plusScore: number, score: number }>(); - let addSumScore = 0; - for (let { actorId: hid } of attack.heroes) { - if(hid == 0) continue; - let params = myHeroes.find(cur => cur.hid == hid); - let curHeroScore = heroScores.find(cur => cur.hid == hid); - if (isSuccess) { - if (!curHeroScore) { - curHeroScore = { - hid, score: dicOpp.score + plusScore - }; - heroScores.push(curHeroScore); - } else { - curHeroScore.score += dicOpp.score + plusScore; - } - addSumScore += dicOpp.score + plusScore; - showHeroScores.push({ - hid, addScore: dicOpp.score, plusScore, score: curHeroScore.score - }); - } else { - showHeroScores.push({ - hid, addScore: 0, plusScore: 0, score: curHeroScore ? curHeroScore.score : 0 - }); - } - const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv skinId'); - - let record = new HeroesRecord(); - record.setByHero(myHero, params); - myHeroRecords.push(record); - } - - let attackInfo = new PvpRecordPlayerInfo(); - attackInfo.setByRole(role, myHeroRecords, isSuccess, isSuccess ? addSumScore : 0, role.lv); - - let newAttack = calLineupScore(attack, heroScores); - let newDefense = calLineupScore(defense, heroScores); - - let updateParam = { - winStreakNum, hisWinStreakNum, attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore, hisScore: hisScore > score + addSumScore? hisScore: score + addSumScore, seasonWinNum - } - - return { attackInfo, showHeroScores, updateParam } -} - -export function calLineupScore(lineup: Attack|Defense, heroScores: HeroScore[]) { - // if(!lineup) return lineup; - let scores: number[] = []; - // for(let { actorId } of lineup.heroes) { - // let hs = heroScores.find(cur => cur.hid == actorId); - // if(hs) { - // scores.push(hs.score); - // } - // } - for(let {score} of heroScores){ - scores.push(score); - } - let { pLv, score } = getPlvAndScore(scores); - return {...lineup, score, pLv} -} - -// 获取对手战报记录 -export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayer, oppHeroes: pvpEndParamInter[], serverId: number) { - let oppHeroRecords = new Array(); - let oppRole = curOpp.oppDef; - if (!oppRole) { console.error('opp role not found') } - - for (let params of oppHeroes) { - let historyHero = oppRole.heroes.find(cur => cur.actorId == params.hid); - if (historyHero) { - let hs = new HeroesRecord(); - hs.setByPvpHeroInfo(historyHero, params); - oppHeroRecords.push(hs); - } - } - let addSumScore = 0; - let pvpDefense = curOpp.isRobot? null: await PvpDefenseModel.findByRoleId(robotIdComBack(curOpp.roleId)); - // if(pvpDefense && !isSuccess) { - // if(pvpDefense && pvpDefense.defense) { - // let { attack, defense, heroScores, score, defenseScoreCnt, refDefenseScore } = pvpDefense; - // if(shouldRefresh(refDefenseScore, new Date())) { - // defenseScoreCnt = 0; refDefenseScore = new Date(); - // } - // if(defenseScoreCnt < PVP.PVP_DEFENSE_SUCCESS_REWARD_MAX_CNT) { - // for(let { actorId } of defense.heroes) { - // let hs = heroScores.find(cur => cur.hid == actorId); - // const dicOpp = gameData.pvpOpponent.get(curOpp.pos); - // let addScore = PVP.PVP_DEFENSE_SUCCESS_REWARD - dicOpp.score; - // if(hs) { - // hs.score += addScore; - // } else { - // heroScores.push({ hid: actorId, score: addScore }) - // } - // addSumScore += addScore; - // } - - // let newAttack = calLineupScore(attack, heroScores); - // let newDefense = calLineupScore(defense, heroScores); - - - // await PvpDefenseModel.updateInfo(pvpDefense.roleId, { attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore, defenseScoreCnt: defenseScoreCnt + 1, refDefenseScore }); - - // } else { - // await PvpDefenseModel.updateInfo(pvpDefense.roleId, { defenseScoreCnt: defenseScoreCnt + 1, refDefenseScore }); - // } - // } - // } - - let defenseInfo = new PvpRecordPlayerInfo(); - defenseInfo.setByHistoryOpp(oppRole, oppHeroRecords, !isSuccess, isSuccess ? 0 : addSumScore, pvpDefense?.serverId||serverId) - return defenseInfo -} - -/** - * pvp定时任务赛季结算 - * @param obj - */ - export async function pvpSeasonEnd(seasonNum: number) { - let pvpConfig = await PVPConfigModel.findPVPConfig(seasonNum); - if(pvpConfig.hasSettleReward) return; - - console.log('exce pvpSeasonEnd ' + pvpConfig.seasonNum); - let resultMaxRank = getPvpRankMaxRewardsBySeasonNum(pvpConfig.seasonNum);//根据排行榜的奖励表,获得最大排名挡位的最小值,其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算 - if(!resultMaxRank) return; - - let pvpKeys = await findKeys(`${REDIS_KEY.PVP_RANK}:${pvpConfig.seasonNum}:`); - for(let key of pvpKeys) { - let [,, groupId] = key.split(':'); - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpConfig.seasonNum, groupId: parseInt(groupId) }, false, resultMaxRank.min - 1); - let allRank = (await r.getRankByRange()); - console.log('******** allRank', 0, resultMaxRank.min - 2, allRank) - for(let { rank, roleId } of allRank) { - console.log('******** pvpSeasonEnd: ', rank, roleId); - let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); - let { pvpSeasonResult } = await sendPVPRewardToUser(pvpDefense, pvpConfig.seasonNum, pvpConfig.seasonEndTime); - reportTAEvent(roleId, TA_EVENT.PVP_SEASON_END, { top_rank: rank, hero_score: pvpSeasonResult.heroScores }) - } - } - await PvpDefenseModel.resetDefense(); - let settledPvpConfig = await PVPConfigModel.setReward(pvpConfig.seasonNum); - await setPvpSettleSeasonNumToRemote(settledPvpConfig); -} - -/** - * pvp定时任务结算获得添加邮件信息 - * @param pvpDefense - * @param seasonNum - * @param oldSeasonEndTime - */ -export async function sendPVPRewardToUser(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number) { - //检查并返回排名结算以及武将功勋结算 - let pvpSeasonResult = await savePvpSeasonResult(pvpDefense, seasonNum, seasonEndTime); - let { rankGoods, heroGoods, rankLv, seasonWinNum, receivedBox } = pvpSeasonResult; - //下发邮件 - if (rankGoods.length > 0) //排名奖励 - await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, pvpDefense.roleId, { - params: [JSON.stringify(seasonNum), ((rankLv == 0 || rankLv > 1000) ? '999+' : JSON.stringify(rankLv))], - goods: rankGoods - }); - if (heroGoods.length > 0) //武将功勋奖励 - await sendMailByContent(MAIL_TYPE.PVP_RESULT, pvpDefense.roleId, { - params: [JSON.stringify(seasonNum)], - goods: heroGoods - }); - - if(receivedBox.length > 0) - await sendUnreceivedPvpBox(pvpDefense.roleId, seasonNum, seasonWinNum, receivedBox); - - return { - pvpSeasonResult, - pvpDefense: await resetPvpScores(pvpDefense, pvpSeasonResult) - } -} - -async function sendUnreceivedPvpBox(roleId: string, seasonNum: number, seasonWinNum: number, receivedBox: number[]) { - let rewards: RewardInter[] = []; - let pvpBoxes = getPvpBoxsBySeasonNum(seasonNum); - for(let { index, winTimes, reward } of pvpBoxes) { - if(seasonWinNum >= winTimes && receivedBox.indexOf(index) == -1) { - rewards.push(...reward); - } - } - if(rewards.length > 0) { - await sendMailByContent(MAIL_TYPE.PVP_BOX, roleId, { - goods: rewards - }); - } -} - -async function resetPvpScores(pvpDefense: PvpDefenseType, pvpSeasonResult: PvpSeasonResultType) { - let { roleId, attack } = pvpDefense; - let { newHeroScores, newScore, seasonNum } = pvpSeasonResult; - let initCount = await getVipPvpChallengeMaxCnt(roleId) - - let newAttack = calLineupScore(attack, newHeroScores); - - pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { - heroScores: newHeroScores, score: newScore, attack: newAttack, defense: null, hasDefense: false, rankSeasonNum: seasonNum + 1, - challengeCnt: initCount, challengeRefTime: 0, winStreakNum: 0, - seasonWinNum: 0, receivedBox: [] - }); - return pvpDefense; -} - -/** - * 检查并返回排名结算以及武将功勋结算 - * @param pvpDefense - * @param seasonNum - * @param oldSeasonEndTime - * @param rankLv - */ -export async function savePvpSeasonResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, rankLv?: number) { - let groupId = await getPVPGroupIdOfServer(pvpDefense.serverId); - if (!rankLv) { - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); - rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名 - } - let pvpRankReward: DicRankRewads = getPvpRankRewardsByRank(seasonNum, rankLv, pvpDefense.score); - let rankGoods: RewardInter[] = []; - if (pvpRankReward) { - rankGoods = pvpRankReward.reward;//排名奖励 - } - let heroGoods: HeroReward[] = []; - let newHeroScores: HeroScore[] = [], newScore = 0; - for (let heroScore of pvpDefense.heroScores) { - let pvpHeroReward = getPvpHeroRewardsByScore(heroScore.score); //获得武将功勋奖励 - if (pvpHeroReward) { - newHeroScores.push({...heroScore, score: pvpHeroReward.heroscore }); - for(let { id, count } of pvpHeroReward.reward) { - heroGoods.push({ - hid: heroScore.hid, id, count - }); - } - newScore += pvpHeroReward.heroscore; - } else { - newHeroScores.push({...heroScore, score:0}); - // newScore += heroScore.score; - } - } - - //pvp锁定的信息存入赛季结算表中 - let {receivedBox, score, seasonWinNum, heroScores } = pvpDefense; - let pvpSeasonResult = await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, seasonNum, { - receivedBox, score, seasonWinNum, heroScores, rankLv, heroGoods, rankGoods, show: true, newScore, newHeroScores, seasonEndTime - });//结算修改玩家pvp信息 - if(newScore > 0) { - let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: seasonNum + 1, groupId }); - await r.setRankWithRoleInfo(pvpDefense.roleId, newScore, Date.now()); - } - - // 更新任务 - await checkTask(pvpDefense.serverId, pvpDefense.roleId, null, TASK_TYPE.PVP_HERO_SCORE, { heroScores: pvpDefense.heroScores }); - await checkTask(pvpDefense.serverId, pvpDefense.roleId, null, TASK_TYPE.PVP_RANK, { pvpRank: rankLv }); - return pvpSeasonResult; -} - -export async function generPvpLineupCe(roleId: string, lineupCe: LineupCe[], attackHero: AttackHero[], defenseHero: DefenseHero[], dbHeroes: HeroType[]) { - let newHids: number[] = []; // 本次新增武将 - let newLineupCe: { hid: number, ce: number }[] = []; // 新生成的lineupCe字段 - for(let { actorId } of [...attackHero, ...defenseHero]) { - let n = newLineupCe.find(cur => cur.hid == actorId); - if(!n) { - let lineup = lineupCe.find(cur => cur.hid == actorId); - if(lineup) { - newLineupCe.push(lineup); - } else { - let dbHero = dbHeroes.find(cur => cur.hid == actorId); - if(dbHero) { - newLineupCe.push({ hid: actorId, ce: dbHero.ce }); - } else { - newHids.push(actorId); - } - } - } - } - let heroes = await HeroModel.findByHidRange(newHids, roleId, 'hid ce', true); - for(let { hid, ce } of heroes) { - newLineupCe.push({ hid, ce }); - } - return newLineupCe; -} - - -export function getPvpSeasonStatus() { - let { seasonEndTime, seasonStartTime, seasonRewardTime } = getPvpTime(); - let now = nowSeconds(); - if(now >= seasonStartTime && now < seasonEndTime) { - return PVP_SEASON_STATUS.START; - } else if (now >= seasonEndTime && now < seasonRewardTime) { - return PVP_SEASON_STATUS.SUMMIT; - } else { - return PVP_SEASON_STATUS.WAITING; - } -} - -interface PvpTime { - seasonNum: number, seasonEndTime: number, seasonStartTime: number, seasonRewardTime: number -} -export function getPvpTime(): PvpTime { - return { - seasonNum: pinus.app.get('pvpSeasonNum'), - seasonEndTime: pinus.app.get('pvpSeasonEndTime'), - seasonStartTime: pinus.app.get('pvpSeasonStartTime'), - seasonRewardTime: pinus.app.get('pvpSeasonRewardTime') - } -} - -export async function getPvpTimeFromRemote(): Promise { - let serverType = pinus.app.getServerType(); - if(serverType == 'battle') { - return getPvpTime(); - } else { - let battleServers = pinus.app.getServersByType('battle'); - let server = getRandSingleEelm(battleServers); - return await pinus.app.rpc.battle.battleRemote.getPvpTime.toServer(server.id); - } -} - -export function checkPvpSeasonIsStart() { - let status = getPvpSeasonStatus(); - return status == PVP_SEASON_STATUS.START; -} - -export function checkPvpSeasonIsSummit() { - let status = getPvpSeasonStatus(); - return status == PVP_SEASON_STATUS.SUMMIT; -} - -export function checkPvpSeasonIsWaiting() { - let status = getPvpSeasonStatus(); - return status == PVP_SEASON_STATUS.WAITING; -} - -export function refreshBuyChallengeCnt(buyChallengeTime:number = 0){ - let refTime = getZeroPointD(SHOP_REFRESH_TYPE.DAILY); - if(refTime.getTime() > buyChallengeTime){ - return true - } - return false; -} \ No newline at end of file + +import { PvpDefenseModel, PvpDefenseType, pvpUpdateInter } from '@db/PvpDefense'; +import { Defense, Attack, LineupCe, OppPlayer, HeroScore, HeroReward, OppPlayerReturn, AttackHero, DefenseHero } from '@domain/battleField/pvp'; +import { RoleType } from '@db/Role'; +import { REDIS_KEY, TASK_TYPE, MAIL_TYPE, TA_EVENT, ITID, getHeadItid, getFrameItid, getSpineItid, PVP_SEASON_STATUS, SHOP_REFRESH_TYPE } from '@consts'; +import { dicPvpOpponent, DicPvpOpponent } from "@pubUtils/dictionary/DicPvpOpponent"; +import { getRandSingleIndex, genCode, shouldRefresh, getChineseName, makeRobotId, robotIdComBack, getRandSingleEelm } from '@pubUtils/util'; +import { pvpEndParamInter, RewardInter } from '@pubUtils/interface'; +import { gameData, getPLvByScore, getPvpHeroRewardsByScore, getPvpRankRewardsByRank, getPvpDifficultByScore, getPlvAndScore, getPvpBoxsBySeasonNum, getPvpRankMaxRewardsBySeasonNum, randomGoodsByItid } from "@pubUtils/data"; +import { EXTERIOR, PVP } from '@pubUtils/dicParam'; +import { PVPConfigModel } from '@db/PvpConfig' +import { nowSeconds, getTimeFun, getZeroPointD } from '@pubUtils/timeUtil'; +import { HeroesRecord, PvpRecordPlayerInfo } from '@db/PvpRecord'; +import { HeroModel, HeroType } from '@db/Hero'; +import { AttributeCal } from '@domain/roleField/attribute'; +import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '@domain/dbGeneral'; +import { pinus } from 'pinus'; +import { PvpHistoryOppModel, PvpHistoryOppType, PvpOppCreateParam } from '@db/PvpHistoryOpp'; +import { Rank } from './rankService'; +import { DicRankRewads } from '@pubUtils/dictionary/DicPvpRankReward'; +import { PvpSeasonResultModel, PvpSeasonResultType } from '@db/PvpSeasonResult'; +import { checkTask } from './task/taskService'; +import { sendMailByContent } from './mailService'; +import { RoleRankInfo } from '@domain/rank'; +import { reportTAEvent } from './sdkService'; +import { getVipPvpChallengeMaxCnt } from './activity/monthlyTicketService'; +import { getHeroesAttributes } from './playerCeService'; +import { setPvpSettleSeasonNumToRemote } from './timeTaskService'; +import { ArtifactModel } from '@db/Artifact'; +import { getPVPGroupIdOfServer, getPvpServersByGroupId } from './serverService'; +import { findKeys } from './redisService'; +import { JewelModel } from '@db/Jewel'; + +/** + * 返回对手三人信息 + * + * @param oppPlayers pvpDefense表中的oppPlayers字段,需要populate过的 + * @param pLv 玩家本人的队伍等级 + */ +export async function getEnemies(r: Rank, oppPlayers: OppPlayer[], winStreakNum: number) { + + let result = new Array(); + for (let oppPlayer of oppPlayers) { + let dicOpponent = dicPvpOpponent.get(oppPlayer.pos); + if(!dicOpponent) continue; + let oppDef = oppPlayer.oppDef; // select 'oppRoleId pos roleName head frame spine rankLv pLv defCe' + + if (oppDef) delete oppDef.heroes; + let myRank = await r.getMyRank({ roleId: robotIdComBack(oppDef.oppRoleId) });//去redis中获取排名 + result.push({ + ...oppDef, + roleId: oppDef.oppRoleId, + defCe: oppDef.defCe, + addScore: dicOpponent.score, + rankLv: myRank||0, + plusScore: getPlusScore(winStreakNum) + }); + } + return result +} + +/** + * @description 刷新对手三个人 + * @param role 数据库里我的role + * @param score 我的军功 + * @param pLv 我的排名 + */ +export async function refreshEnemies(role: RoleType, seasonNum: number, sumScore: number, score: number, pLv: number) { + let { roleId, serverId } = role; + let groupId = await getPVPGroupIdOfServer(serverId); + let chosenOpps: string[] = []; + let pvpHistoryOppParam: PvpOppCreateParam[] = []; + for(let pos = 1; pos <= 3; pos++) { + let dicOpp = gameData.pvpOpponent.get(pos); + if(!dicOpp) continue; + let pvpHistoryOpp: PvpOppCreateParam; // 是否筛选成功 + if (sumScore >= PVP.PVP_MATCH_ROBOT) { + pvpHistoryOpp = await matchPlayer(groupId, seasonNum, chosenOpps, roleId, pLv, dicOpp); // 按照等级匹配对手 + if (!pvpHistoryOpp) pvpHistoryOpp = await matchPlayerByRank(groupId, seasonNum, chosenOpps, roleId, dicOpp.id); // 当前后分数段没有时,返回前一名的玩家 + if (!pvpHistoryOpp) pvpHistoryOpp = await matchRobot(chosenOpps, role, score, dicOpp); + } else { + pvpHistoryOpp = await matchRobot(chosenOpps, role, score, dicOpp); + } + if (!pvpHistoryOpp) continue; + pvpHistoryOppParam.push(pvpHistoryOpp); + } + + let oppPlayers: OppPlayer[] = []; + pvpHistoryOppParam.sort((a, b) => { + if(a.pLv != b.pLv) return b.pLv - a.pLv; + return b.defCe - a.defCe; + }); + for(let i = 0; i < pvpHistoryOppParam.length; i++) { + let param = pvpHistoryOppParam[i]; + param.pos = i + 1; + let pvpHistoryOpp = await PvpHistoryOppModel.createPvpOpp(param); + oppPlayers.push({ + roleId: pvpHistoryOpp.oppRoleId, + oppDef: pvpHistoryOpp._id, + isRobot: pvpHistoryOpp.isRobot, + pos: pvpHistoryOpp.pos, + }); + } + if(dicPvpOpponent.size > 3 && !pinus.app.get('dicPvpOpponent')) { + pinus.app.set('dicPvpOpponent', dicPvpOpponent); + } + return oppPlayers; +} + +export async function matchPlayerByRank(groupId: number, seasonNum: number, chosenOpps: string[], roleId: string, pos: number) { + // console.log('matchPlayerByRank', JSON.stringify(oppPlayers)) + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let ridRanks = new Array(); // 已经被使用了的排名 + for (let curRoleId of chosenOpps) { + let rankLv = await r.getMyRank({ roleId: robotIdComBack(curRoleId) }); + ridRanks.push(rankLv); + } + + let myRank = await r.getMyRank({ roleId }); + ridRanks.push(myRank); + + let oppRoleId = ''; + let oppRank = 0; + if (myRank == 0) { + return null + } else if (myRank == 1) { // 第一名 + if (pos == 1) { + oppRank = 2; + while (ridRanks.includes(oppRank)) { + oppRank--; + } + } else if (pos == 2) { + oppRank = 3; + while (ridRanks.includes(oppRank)) { + oppRank--; + } + } else { + oppRank = 4; + while (ridRanks.includes(oppRank)) { + oppRank++; + } + } + } else if (myRank == 2) { // 第二名 + if (pos == 1) { + oppRank = 1; + while (ridRanks.includes(oppRank)) { + oppRank--; + } + } else if (pos == 2) { + oppRank = 3; + while (ridRanks.includes(oppRank)) { + oppRank++; + } + } else { + oppRank = 4; + while (ridRanks.includes(oppRank)) { + oppRank++; + } + } + } else { + if (pos == 1 || pos == 2) { // 刷新我前一名 + oppRank = myRank - 1; + while (ridRanks.includes(oppRank)) { + oppRank--; + } + } else { // 刷新我后一名 + oppRank = myRank + 1; + while (ridRanks.includes(oppRank)) { + oppRank++; + } + } + } + if(oppRank <= 0) return null; + let result = await r.getUserByRank(oppRank); + if (result.length <= 0) return null; + oppRoleId = result[0]; + + let pvpdefense = await PvpDefenseModel.findByRoleIdIncludeAll(oppRoleId); + if (!pvpdefense || pvpdefense.seasonNum != seasonNum || !pvpdefense.hasDefense) return null; + let pvpHistoryOpp = await generPlayerOppHis(pvpdefense, roleId, pos, groupId); + if (!pvpHistoryOpp) return null; + + chosenOpps.push(pvpHistoryOpp.oppRoleId); + return pvpHistoryOpp; +} + +async function matchPlayer(groupId: number, seasonNum: number, chosenOpps: string[], roleId: string, pLv: number, dicOpp: DicPvpOpponent) { + // console.log('matchPlayer', JSON.stringify(oppPlayers)) + + let serverIds = await getPvpServersByGroupId(groupId); + let { id: pos, minLv, maxLv } = dicOpp; + let min = pLv + minLv > 1? pLv + minLv: 1; + let max = pLv + maxLv > 1? pLv + maxLv: 1; + let range = await PvpDefenseModel.findByTeamLv(serverIds, seasonNum, min, max); + range = range.filter(cur => { + return chosenOpps.indexOf(makeRobotId(cur.roleId)) == -1; + }); + if (range.length <= 0) return null; + + let index = getRandSingleIndex(range.length); + let result = range[index]; // 本次匹配结果 pvpdefense + if (!result) return null; + if (result.roleId == roleId) { + range.splice(index, 1); + if (range.length <= 0) return null; + index = getRandSingleIndex(range.length); + result = range[index]; + } + let pvpHistoryOpp = await generPlayerOppHis(result, roleId, pos, groupId); + if (!pvpHistoryOpp) return null; + + chosenOpps.push(pvpHistoryOpp.oppRoleId); + return pvpHistoryOpp; +} + +/** + * @description 对手是玩家时,生成并返回pvpHistoryOpp + * @param result 随机出的对手pvpDefense + * @param roleId 自己的玩家id + * @param pos 刷新这个对手的位置 + */ +async function generPlayerOppHis(pvpdefense: PvpDefenseType, roleId: string, pos: number, groupId: number) { + let { heroScores, defense } = pvpdefense; + if(!defense) return false; + let { warId, heroes: defenseHeroes } = defense; + let role = pvpdefense.role; + + let seasonNum: number = pinus.app.get('pvpSeasonNum'); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + let rankLv = await r.getMyRank({ roleId: role.roleId }); + let dbHeroes = await HeroModel.findByRole(role.roleId, [{ field: 'ce', sortBy: -1 }]); + let heroes = new Array(); + let otherHeroes = new Array(); // 阵容外的所有武将信息 + let defCe = 0; + let attrByHid = await getHeroesAttributes(role.roleId); + let hids = defenseHeroes.map(cur => cur.actorId); + + let artifacts = await ArtifactModel.findbyHids(role.roleId, hids); + let jewels = await JewelModel.findbyRoleAndHids(role.roleId, hids); + + for (let dbHero of dbHeroes) { + let artifact = dbHero.artifact? artifacts.find(cur => cur.seqId == dbHero.artifact): null; + let h = defenseHeroes.find(cur => cur.actorId == dbHero.hid); // 阵容里是否有这个武将 + let hs = heroScores.find(cur => cur.hid == dbHero.hid); // 这个武将是否有这个得分 + if (!!h) { + let dicWar = gameData.war.get(warId); + let mapWarJson = gameData.warJson.get(dicWar.dispatchJsonId); + let warJson = mapWarJson.find(cur => cur.dataId == h.dataId); + if (warJson && warJson.relation == 2) { + let heroInfo = new PvpHeroInfo(); + heroInfo.setHeroInfo(dbHero, artifact, dbHero.ePlace.map(cur => ({ ...cur, jewel: jewels.find(ccur => cur.jewel == ccur.seqId) }))); + // heroInfo.setOutIndex(h.order); + let attr = attrByHid.get(h.actorId); + if(!attr) continue; + let attribute = attr.getAttributesToString(); + let ce = attr.calCe(); + if(isNaN(ce)) ce = 0; + heroInfo.setAttribute(attribute); + let subHero = h.subHid? dbHeroes.find(hero => hero.hid == h.subHid): null; + let enemy = new PvpEnemies(warJson, heroInfo, hs ? hs.score : 0, ce, subHero); + enemy.setOutIndex(h.order); + enemy.initial_ai = h.ai; + heroes.push(enemy); + defCe += ce; + } + } else { + let heroInfo = new PvpOtherHeroes(hs ? hs.score : 0); + heroInfo.setHeroInfo(dbHero, artifact); + otherHeroes.push(heroInfo); + } + } + heroes.sort((a, b) => b.score - a.score); + otherHeroes.sort((a, b) => b.score - a.score); + + return { + isRobot: false, ...defense, defCe, ...role, pos, rankLv, heroes, otherHeroes, roleId, oppRoleId: makeRobotId(pvpdefense.roleId) + }; +} + +async function matchRobot(chosenOpps: string[], role: RoleType, score: number, dicOpp: DicPvpOpponent) { + // console.log('matchRobot', JSON.stringify(oppPlayers)) + + let { lv: myLv, roleId } = role; + let { id: pos, minLv, maxLv, ratio } = dicOpp; + + let pvpConfig = await PVPConfigModel.findCurPVPConfig(); + let range = pvpConfig?.warIds||[]; + let warId = getRandSingleEelm(range); + if (!warId) return null; + let result = gameData.war.get(warId); + if (!result) return null; + + let robotWarjson = gameData.warJson.get(result.dispatchJsonId); + if (!robotWarjson) return null + let heroes: PvpEnemies[] = []; + let defCe = 0; + for (let h of robotWarjson) { + if (h.relation == 1) continue; + let actorId = h.randomEnemy.length > 0? getRandSingleEelm(h.randomEnemy): 0; + let dicHero = gameData.hero.get(actorId); + if (!dicHero) continue; + let heroInfo = new PvpHeroInfo(); + let robotInfo = getRobotAttribute(actorId, ratio, score); + if(!robotInfo) continue; + let { attribute, ce, lv } = robotInfo; + heroInfo.setRobotInfo(dicHero, lv); + defCe += ce; + heroInfo.setAttribute(attribute); + let enemy = new PvpEnemies(h, heroInfo, 0, ce); + enemy.setOutIndex(h.outIndex); + heroes.push(enemy); + } + + let oppRoleId = generateRobotRoleId(); + chosenOpps.push(oppRoleId); + let roleName = getChineseName(); + let pLv = getPLvByScore(score); + let hisPLv = Math.floor(pLv + (minLv + maxLv) / 2); + if (hisPLv < 1) hisPLv = 1 + return { + isRobot: true, roleId, oppRoleId, roleName, pos, defCe, pLv: hisPLv, lv: myLv, heroes, rankLv: 0, warId: result.war_id, buff: getRandSingleEelm(result.mapseid)||0, + head: randomHead(), frame: randomFrame(), spine: randomSpine() + }; +} + +function randomHead() { + return randomGoodsByItid(getHeadItid())||EXTERIOR.EXTERIOR_FACE; +} + +function randomFrame() { + return randomGoodsByItid(getFrameItid())||EXTERIOR.EXTERIOR_FACECASE; +} + +function randomSpine() { + return randomGoodsByItid(getSpineItid())||EXTERIOR.EXTERIOR_APPEARANCE; +} + +// 生成机器人roleId +function generateRobotRoleId() { + return `${genCode(10)}_r`; +} + +// 根据连胜次数,获得加成的积分 +export function getPlusScore(win: number) { + let result = win - 1; + if (result < 0) result = 0; + if (result > PVP.PVP_WINREWARD_UPLIMIT) result = PVP.PVP_WINREWARD_UPLIMIT; + return result; +} + +export function getLvByScore(heroScores: HeroScore[]) { + heroScores.sort((a, b) => b.score - a.score); + let score = 0; + for (let i = 0; i < 5; i++) { + if (!heroScores[i]) break; + score += heroScores[i].score; + } + return getPLvByScore(score); +} + +export async function refChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number, roleId: string, vipStartTime?: number) { + let hasChanged = false; + let initCount = await getVipPvpChallengeMaxCnt(roleId, vipStartTime) + if (challengeCnt >= initCount) { + return { hasChanged, challengeCnt, challengeRefTime: nowSeconds() }; + } + let period = PVP.PVP_CHALLENGE_NORMALTIMES * 60; + if (getTimeFun(seasonEndTime).checkDay()) { + period = PVP.PVP_CHALLENGE_FINALTIMES * 60; + } + let time = nowSeconds(); + let num = Math.floor((time - challengeRefTime) / period); + if (num > 0) { + challengeCnt += num; + challengeRefTime = challengeRefTime + period * num; + hasChanged = true; + } + if(challengeCnt > initCount) challengeCnt = initCount; + return { hasChanged, challengeCnt, challengeRefTime }; +} + +export async function comsumeChallengeCnt(challengeCnt: number, challengeRefTime: number, seasonEndTime: number, roleId: string) { + let initCount = await getVipPvpChallengeMaxCnt(roleId) + + challengeCnt--; + if (challengeCnt >= initCount) { + return { challengeCnt, challengeRefTime }; + } + if (challengeCnt == initCount - 1) { + challengeRefTime = nowSeconds(); + return { challengeCnt, challengeRefTime }; + } + return refChallengeCnt(challengeCnt, challengeRefTime, seasonEndTime, roleId); +} + +export async function sendLastSeasonRewardIfNotSent(pvpDefense: PvpDefenseType) { + let seasonSettleNum: number = pinus.app.get('pvpSettleSeasonNum'); + console.log('##### sendLastSeasonRewardIfNotSent seasonSettleNum', pvpDefense.roleId, pvpDefense.rankSeasonNum, seasonSettleNum) + if(seasonSettleNum && pvpDefense.rankSeasonNum <= seasonSettleNum) { + let oldPvpCongig = await PVPConfigModel.findPVPConfig(seasonSettleNum); + let result = await sendPVPRewardToUser(pvpDefense, seasonSettleNum, oldPvpCongig.seasonEndTime); + pvpDefense = result.pvpDefense; + } + return pvpDefense; +} + +// async function checkHasSettled(seasonSettleNum: number, roleId: string) { +// let hasData = await PvpSeasonResultModel.checkResultBySeasonNum(roleId, seasonSettleNum); +// return hasData; +// } + +// 获取刷新对手次数及消耗 +export function refreshRefOppCnt(pvpDefense: PvpDefenseType) { + let { refOppCnt = 0, setAttackCnt = 0, buyAttackCnt = 0, refDaily } = pvpDefense; + let curTime = new Date(); + let shouldRefOpp = shouldRefresh(refDaily, curTime); + if (shouldRefOpp) { + refOppCnt = 0; setAttackCnt = 0; buyAttackCnt =0; refDaily = curTime; + } + return { + shouldRefOpp, + refOppCnt, refDaily, setAttackCnt, buyAttackCnt, + consume: gameData.pvpRefreshConsume.get(refOppCnt + 1) + } +} + + +/** + * 根据比例计算机器人属性 + * @param attribute 出兵表中的属性字段 + * @param ce 我的战力 + * @param enemyCe 出兵表对手战力 + * @param ratio 系数 + */ +export function getRobotAttribute(hid: number, posRatio: number, score: number) { + + let difficultRatio = getPvpDifficultByScore(score); + if(!difficultRatio) return null + let dicHero = gameData.hero.get(hid); + + let newAttribute = new AttributeCal(); + newAttribute.setLv(difficultRatio.enemyLv); + newAttribute.setByMap(hid, dicHero.baseAbilityArr, difficultRatio.value / 10000 * posRatio); + let subAttr = gameData.towerPvpSubAttr.get(difficultRatio.secondAttrLevel); + if(subAttr) newAttribute.setByWarJson(hid, subAttr.secondAtr); + let attrArr = newAttribute.getAttributesToString(); + let newCe = newAttribute.calCe(); + return { attribute: attrArr, ce: newCe, lv: difficultRatio.enemyLv }; +} + +// 获取我方战报记录 +export async function generMyRecInfo(pvpDefense: PvpDefenseType, role: RoleType, isSuccess: boolean, pos: number, myHeroes: pvpEndParamInter[]) { + let { attack, defense, heroScores, winStreakNum, hisWinStreakNum = 0, score, hisScore, seasonWinNum = 0 } = pvpDefense; + let { roleId } = role; + if (isSuccess) { + winStreakNum ++; + seasonWinNum ++; + } else { + winStreakNum = 0; + } + if(winStreakNum > hisWinStreakNum) { + hisWinStreakNum = winStreakNum; + } + + const dicOpp = gameData.pvpOpponent.get(pos); + const plusScore = getPlusScore(winStreakNum); + + let myHeroRecords: HeroesRecord[] = []; // 存入rec里面的数据 + let showHeroScores = new Array<{ hid: number, addScore: number, plusScore: number, score: number }>(); + let addSumScore = 0; + for (let { actorId: hid } of attack.heroes) { + if(hid == 0) continue; + let params = myHeroes.find(cur => cur.hid == hid); + let curHeroScore = heroScores.find(cur => cur.hid == hid); + if (isSuccess) { + if (!curHeroScore) { + curHeroScore = { + hid, score: dicOpp.score + plusScore + }; + heroScores.push(curHeroScore); + } else { + curHeroScore.score += dicOpp.score + plusScore; + } + addSumScore += dicOpp.score + plusScore; + showHeroScores.push({ + hid, addScore: dicOpp.score, plusScore, score: curHeroScore.score + }); + } else { + showHeroScores.push({ + hid, addScore: 0, plusScore: 0, score: curHeroScore ? curHeroScore.score : 0 + }); + } + const myHero = await HeroModel.findByHidAndRole(hid, roleId, 'quality star colorStar lv skinId'); + + let record = new HeroesRecord(); + record.setByHero(myHero, params); + myHeroRecords.push(record); + } + + let attackInfo = new PvpRecordPlayerInfo(); + attackInfo.setByRole(role, myHeroRecords, isSuccess, isSuccess ? addSumScore : 0, role.lv); + + let newAttack = calLineupScore(attack, heroScores); + let newDefense = calLineupScore(defense, heroScores); + + let updateParam = { + winStreakNum, hisWinStreakNum, attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore, hisScore: hisScore > score + addSumScore? hisScore: score + addSumScore, seasonWinNum + } + + return { attackInfo, showHeroScores, updateParam } +} + +export function calLineupScore(lineup: Attack|Defense, heroScores: HeroScore[]) { + // if(!lineup) return lineup; + let scores: number[] = []; + // for(let { actorId } of lineup.heroes) { + // let hs = heroScores.find(cur => cur.hid == actorId); + // if(hs) { + // scores.push(hs.score); + // } + // } + for(let {score} of heroScores){ + scores.push(score); + } + let { pLv, score } = getPlvAndScore(scores); + return {...lineup, score, pLv} +} + +// 获取对手战报记录 +export async function generPVPOppRecInfo(isSuccess: boolean, curOpp: OppPlayer, oppHeroes: pvpEndParamInter[], serverId: number) { + let oppHeroRecords = new Array(); + let oppRole = curOpp.oppDef; + if (!oppRole) { console.error('opp role not found') } + + for (let params of oppHeroes) { + let historyHero = oppRole.heroes.find(cur => cur.actorId == params.hid); + if (historyHero) { + let hs = new HeroesRecord(); + hs.setByPvpHeroInfo(historyHero, params); + oppHeroRecords.push(hs); + } + } + let addSumScore = 0; + let pvpDefense = curOpp.isRobot? null: await PvpDefenseModel.findByRoleId(robotIdComBack(curOpp.roleId)); + // if(pvpDefense && !isSuccess) { + // if(pvpDefense && pvpDefense.defense) { + // let { attack, defense, heroScores, score, defenseScoreCnt, refDefenseScore } = pvpDefense; + // if(shouldRefresh(refDefenseScore, new Date())) { + // defenseScoreCnt = 0; refDefenseScore = new Date(); + // } + // if(defenseScoreCnt < PVP.PVP_DEFENSE_SUCCESS_REWARD_MAX_CNT) { + // for(let { actorId } of defense.heroes) { + // let hs = heroScores.find(cur => cur.hid == actorId); + // const dicOpp = gameData.pvpOpponent.get(curOpp.pos); + // let addScore = PVP.PVP_DEFENSE_SUCCESS_REWARD - dicOpp.score; + // if(hs) { + // hs.score += addScore; + // } else { + // heroScores.push({ hid: actorId, score: addScore }) + // } + // addSumScore += addScore; + // } + + // let newAttack = calLineupScore(attack, heroScores); + // let newDefense = calLineupScore(defense, heroScores); + + + // await PvpDefenseModel.updateInfo(pvpDefense.roleId, { attack: newAttack, defense: newDefense, heroScores, score: score + addSumScore, defenseScoreCnt: defenseScoreCnt + 1, refDefenseScore }); + + // } else { + // await PvpDefenseModel.updateInfo(pvpDefense.roleId, { defenseScoreCnt: defenseScoreCnt + 1, refDefenseScore }); + // } + // } + // } + + let defenseInfo = new PvpRecordPlayerInfo(); + defenseInfo.setByHistoryOpp(oppRole, oppHeroRecords, !isSuccess, isSuccess ? 0 : addSumScore, pvpDefense?.serverId||serverId) + return defenseInfo +} + +/** + * pvp定时任务赛季结算 + * @param obj + */ + export async function pvpSeasonEnd(seasonNum: number) { + let pvpConfig = await PVPConfigModel.findPVPConfig(seasonNum); + if(pvpConfig.hasSettleReward) return; + + console.log('exce pvpSeasonEnd ' + pvpConfig.seasonNum); + let resultMaxRank = getPvpRankMaxRewardsBySeasonNum(pvpConfig.seasonNum);//根据排行榜的奖励表,获得最大排名挡位的最小值,其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算 + if(!resultMaxRank) return; + + let pvpKeys = await findKeys(`${REDIS_KEY.PVP_RANK}:${pvpConfig.seasonNum}:`); + for(let key of pvpKeys) { + let [,, groupId] = key.split(':'); + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: pvpConfig.seasonNum, groupId: parseInt(groupId) }, false, resultMaxRank.min - 1); + let allRank = (await r.getRankByRange()); + console.log('******** allRank', 0, resultMaxRank.min - 2, allRank) + for(let { rank, roleId } of allRank) { + console.log('******** pvpSeasonEnd: ', rank, roleId); + let pvpDefense = await PvpDefenseModel.findByRoleId(roleId); + let { pvpSeasonResult } = await sendPVPRewardToUser(pvpDefense, pvpConfig.seasonNum, pvpConfig.seasonEndTime); + reportTAEvent(roleId, TA_EVENT.PVP_SEASON_END, { top_rank: rank, hero_score: pvpSeasonResult.heroScores }) + } + } + await PvpDefenseModel.resetDefense(); + let settledPvpConfig = await PVPConfigModel.setReward(pvpConfig.seasonNum); + await setPvpSettleSeasonNumToRemote(settledPvpConfig); +} + +/** + * pvp定时任务结算获得添加邮件信息 + * @param pvpDefense + * @param seasonNum + * @param oldSeasonEndTime + */ +export async function sendPVPRewardToUser(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number) { + //检查并返回排名结算以及武将功勋结算 + let pvpSeasonResult = await savePvpSeasonResult(pvpDefense, seasonNum, seasonEndTime); + let { rankGoods, heroGoods, rankLv, seasonWinNum, receivedBox } = pvpSeasonResult; + //下发邮件 + if (rankGoods.length > 0) //排名奖励 + await sendMailByContent(MAIL_TYPE.PVP_RANK_REWARD, pvpDefense.roleId, { + params: [JSON.stringify(seasonNum), ((rankLv == 0 || rankLv > 1000) ? '999+' : JSON.stringify(rankLv))], + goods: rankGoods + }); + if (heroGoods.length > 0) //武将功勋奖励 + await sendMailByContent(MAIL_TYPE.PVP_RESULT, pvpDefense.roleId, { + params: [JSON.stringify(seasonNum)], + goods: heroGoods + }); + + if(receivedBox.length > 0) + await sendUnreceivedPvpBox(pvpDefense.roleId, seasonNum, seasonWinNum, receivedBox); + + return { + pvpSeasonResult, + pvpDefense: await resetPvpScores(pvpDefense, pvpSeasonResult) + } +} + +async function sendUnreceivedPvpBox(roleId: string, seasonNum: number, seasonWinNum: number, receivedBox: number[]) { + let rewards: RewardInter[] = []; + let pvpBoxes = getPvpBoxsBySeasonNum(seasonNum); + for(let { index, winTimes, reward } of pvpBoxes) { + if(seasonWinNum >= winTimes && receivedBox.indexOf(index) == -1) { + rewards.push(...reward); + } + } + if(rewards.length > 0) { + await sendMailByContent(MAIL_TYPE.PVP_BOX, roleId, { + goods: rewards + }); + } +} + +async function resetPvpScores(pvpDefense: PvpDefenseType, pvpSeasonResult: PvpSeasonResultType) { + let { roleId, attack } = pvpDefense; + let { newHeroScores, newScore, seasonNum } = pvpSeasonResult; + let initCount = await getVipPvpChallengeMaxCnt(roleId) + + let newAttack = calLineupScore(attack, newHeroScores); + + pvpDefense = await PvpDefenseModel.updateInfoAndInclude(roleId, { + heroScores: newHeroScores, score: newScore, attack: newAttack, defense: null, hasDefense: false, rankSeasonNum: seasonNum + 1, + challengeCnt: initCount, challengeRefTime: 0, winStreakNum: 0, + seasonWinNum: 0, receivedBox: [] + }); + return pvpDefense; +} + +/** + * 检查并返回排名结算以及武将功勋结算 + * @param pvpDefense + * @param seasonNum + * @param oldSeasonEndTime + * @param rankLv + */ +export async function savePvpSeasonResult(pvpDefense: PvpDefenseType, seasonNum: number, seasonEndTime: number, rankLv?: number) { + let groupId = await getPVPGroupIdOfServer(pvpDefense.serverId); + if (!rankLv) { + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum, groupId }); + rankLv = await r.getMyRank({ roleId: pvpDefense.roleId });// 获得排行榜排名 + } + let pvpRankReward: DicRankRewads = getPvpRankRewardsByRank(seasonNum, rankLv, pvpDefense.score); + let rankGoods: RewardInter[] = []; + if (pvpRankReward) { + rankGoods = pvpRankReward.reward;//排名奖励 + } + let heroGoods: HeroReward[] = []; + let newHeroScores: HeroScore[] = [], newScore = 0; + for (let heroScore of pvpDefense.heroScores) { + let pvpHeroReward = getPvpHeroRewardsByScore(heroScore.score); //获得武将功勋奖励 + if (pvpHeroReward) { + newHeroScores.push({...heroScore, score: pvpHeroReward.heroscore }); + for(let { id, count } of pvpHeroReward.reward) { + heroGoods.push({ + hid: heroScore.hid, id, count + }); + } + newScore += pvpHeroReward.heroscore; + } else { + newHeroScores.push({...heroScore, score:0}); + // newScore += heroScore.score; + } + } + + //pvp锁定的信息存入赛季结算表中 + let {receivedBox, score, seasonWinNum, heroScores } = pvpDefense; + let pvpSeasonResult = await PvpSeasonResultModel.updatePvpSeasonResult(pvpDefense.roleId, seasonNum, { + receivedBox, score, seasonWinNum, heroScores, rankLv, heroGoods, rankGoods, show: true, newScore, newHeroScores, seasonEndTime + });//结算修改玩家pvp信息 + if(newScore > 0) { + let r = new Rank(REDIS_KEY.PVP_RANK, { seasonNum: seasonNum + 1, groupId }); + await r.setRankWithRoleInfo(pvpDefense.roleId, newScore, Date.now()); + } + + // 更新任务 + await checkTask(pvpDefense.serverId, pvpDefense.roleId, null, TASK_TYPE.PVP_HERO_SCORE, { heroScores: pvpDefense.heroScores }); + await checkTask(pvpDefense.serverId, pvpDefense.roleId, null, TASK_TYPE.PVP_RANK, { pvpRank: rankLv }); + return pvpSeasonResult; +} + +export async function generPvpLineupCe(roleId: string, lineupCe: LineupCe[], attackHero: AttackHero[], defenseHero: DefenseHero[], dbHeroes: HeroType[]) { + let newHids: number[] = []; // 本次新增武将 + let newLineupCe: { hid: number, ce: number }[] = []; // 新生成的lineupCe字段 + for(let { actorId } of [...attackHero, ...defenseHero]) { + let n = newLineupCe.find(cur => cur.hid == actorId); + if(!n) { + let lineup = lineupCe.find(cur => cur.hid == actorId); + if(lineup) { + newLineupCe.push(lineup); + } else { + let dbHero = dbHeroes.find(cur => cur.hid == actorId); + if(dbHero) { + newLineupCe.push({ hid: actorId, ce: dbHero.ce }); + } else { + newHids.push(actorId); + } + } + } + } + let heroes = await HeroModel.findByHidRange(newHids, roleId, 'hid ce', true); + for(let { hid, ce } of heroes) { + newLineupCe.push({ hid, ce }); + } + return newLineupCe; +} + + +export function getPvpSeasonStatus() { + let { seasonEndTime, seasonStartTime, seasonRewardTime } = getPvpTime(); + let now = nowSeconds(); + if(now >= seasonStartTime && now < seasonEndTime) { + return PVP_SEASON_STATUS.START; + } else if (now >= seasonEndTime && now < seasonRewardTime) { + return PVP_SEASON_STATUS.SUMMIT; + } else { + return PVP_SEASON_STATUS.WAITING; + } +} + +interface PvpTime { + seasonNum: number, seasonEndTime: number, seasonStartTime: number, seasonRewardTime: number +} +export function getPvpTime(): PvpTime { + return { + seasonNum: pinus.app.get('pvpSeasonNum'), + seasonEndTime: pinus.app.get('pvpSeasonEndTime'), + seasonStartTime: pinus.app.get('pvpSeasonStartTime'), + seasonRewardTime: pinus.app.get('pvpSeasonRewardTime') + } +} + +export async function getPvpTimeFromRemote(): Promise { + let serverType = pinus.app.getServerType(); + if(serverType == 'battle') { + return getPvpTime(); + } else { + let battleServers = pinus.app.getServersByType('battle'); + let server = getRandSingleEelm(battleServers); + return await pinus.app.rpc.battle.battleRemote.getPvpTime.toServer(server.id); + } +} + +export function checkPvpSeasonIsStart() { + let status = getPvpSeasonStatus(); + return status == PVP_SEASON_STATUS.START; +} + +export function checkPvpSeasonIsSummit() { + let status = getPvpSeasonStatus(); + return status == PVP_SEASON_STATUS.SUMMIT; +} + +export function checkPvpSeasonIsWaiting() { + let status = getPvpSeasonStatus(); + return status == PVP_SEASON_STATUS.WAITING; +} + +export function refreshBuyChallengeCnt(buyChallengeTime:number = 0){ + let refTime = getZeroPointD(SHOP_REFRESH_TYPE.DAILY); + if(refTime.getTime() > buyChallengeTime){ + return true + } + return false; +} diff --git a/game-server/app/services/rankService.ts b/game-server/app/services/rankService.ts index 6a4690ea9..3c3821154 100644 --- a/game-server/app/services/rankService.ts +++ b/game-server/app/services/rankService.ts @@ -1,1361 +1,1361 @@ -import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo, RoleAndGuildRankInfo, LeagueRankParam, LeagueRankInfo } from "../domain/rank"; -import { getInfoKeyByRedisKey, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD, getRedisKeyByRankType, COUNTER, RANK_TYPE, PUSH_ROUTE } from "../consts"; -import { redisClient, delKeys, saveLadderDefCeByData } from "./redisService"; -import { RoleType, RoleModel } from "../db/Role"; -import { GuildType, GuildModel } from "../db/Guild"; -import { HeroModel, HeroType, HeroUpdate } from "../db/Hero"; -import { PvpDefenseModel } from "../db/PvpDefense"; -import { gameData } from "../pubUtils/data"; -import { getSeconds, nowSeconds } from "../pubUtils/timeUtil"; -import { BackendSession, pinus } from "pinus"; -import { RankFirstModel, RankFirstType, RankFirstUpdateParam } from "../db/RankFirst"; -import { getRandSingleEelm } from "../pubUtils/util"; -import { RANK_FIRST_REWARD_STATUS } from '../consts'; -import { CounterModel } from "../db/Counter"; -import { ActivityTimeLimitRankModel } from "../db/ActivityTimeLimitRank"; -import { sendMessageToServerWithSuc } from "./pushService"; -import { LadderMatchModel } from "../db/LadderMatch"; -import { completeRanks } from "./ladderService"; -import { GVGVestigeSumRankModel } from "../db/GVGVestigeSumRank"; -import { GVGLeagueModel, GVGLeagueType } from "../db/GVGLeague"; -import { GVGVestigeLeagueRankModel } from "../db/GVGVestigeLeagueRank"; -import { getDayKeyInfo } from "./gvg/gvgFightService"; -import { ActivityMiniGameModel } from "../db/ActivityMiniGame"; -import { getPVPServerGroup } from "./serverService"; -import { PVPConfigModel } from "../db/PvpConfig"; - - -/** - * @description 排行榜相关操作 - * @export - * @class Rank - */ -export class Rank { - isInit: boolean = false; // 初始排行榜 - key: REDIS_KEY; // 排行榜原始key - keyName: KeyName; // 拼接之后的key - infoKey: REDIS_KEY; // 玩家数据key - extraKeys: string[]; - isUnion: boolean; // 是否使用多个zset联合计算 - limit: number = 200; // 排行榜长度 - unionRankLife: number = 10; - valueConfig: ValueConfig[] = []; // 值的组合方案 - - constructor(key: REDIS_KEY, keyParam: KeyNameParam, isUnion = false, limit = 200) { - this.key = key; - this.keyName = new KeyName(key, keyParam); - let { infoKey, extraKey } = getInfoKeyByRedisKey(key); - this.infoKey = infoKey; - this.extraKeys = extraKey; - this.isUnion = isUnion; - this.limit = limit; - this.setValueConfig(key); - } - - public setIsInit(init: boolean) { - this.isInit = init; - } - - private setValueConfig(key: REDIS_KEY) { - switch (key) { - case REDIS_KEY.LADDER: - this.valueConfig = [ - new ValueConfig(true, 'rank', 0, false, false) - ]; - break; - case REDIS_KEY.TOP_LINEUP_RANK: - case REDIS_KEY.TOP_LINE_SNAPSHOT: - case REDIS_KEY.TOP_HERO_RANK: - case REDIS_KEY.SUM_CE_RANK: - case REDIS_KEY.SUM_CE_SNAPSHOT: - case REDIS_KEY.HERO_RANK: - this.valueConfig = [ - new ValueConfig(true, 'score', 0, false, false) - ]; - break; - case REDIS_KEY.RACE_ACTIVITY: - this.valueConfig = [ - new ValueConfig(true, 'distance', 0, false, false), - new ValueConfig(false, 'time', 6, true, true), - new ValueConfig(false, 'durability', 3, false, false), - ]; - break; - case REDIS_KEY.GATE_ACTIVITY: - case REDIS_KEY.CITY_ACTIVITY: - case REDIS_KEY.USER_GATE_ACTIVITY: - case REDIS_KEY.USER_CITY_ACTIVITY: - this.valueConfig = [ - new ValueConfig(true, 'score', 0, false, false), - new ValueConfig(false, 'time', 4, true, false), - ]; - break; - case REDIS_KEY.GUILD_LV_RANK: - this.valueConfig = [ - new ValueConfig(true, 'lv', 0, false, false), - new ValueConfig(false, 'active', 5, false, false), - new ValueConfig(false, 'time', 6, true, true) - ]; - break; - default: - this.valueConfig = [ - new ValueConfig(true, 'score', 0, false, false), - new ValueConfig(false, 'time', 10, true, true) - ]; - break; - } - - for(let i = 0; i < this.valueConfig.length; i++) { - let weight = 0; - for(let j = i + 1; j < this.valueConfig.length; j++) { - weight += this.valueConfig[j].len; - } - this.valueConfig[i].setWeight(weight); - } - } - - /** - * 返回字段修改 - * @param obj - */ - private async generFields(obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) { - return obj; - } - - /** - * 从外部设置返回字段 - * @param cb - */ - public setGenerFieldsFun(cb: (obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) => any) { - this.generFields = cb; - } - - /** - * 设置合成的排行榜的生命时长 单位s - * @param unionRankLife - */ - public setUnionRankLife(unionRankLife: number) { - this.unionRankLife = unionRankLife; - } - - /** - * 该排行是否为空 - * @param void - */ - public async existsRank() { - const result = await redisClient().existsAsync(this.keyName.getName()); - return result; - } - - /** - * 根据role表设置更新排行榜&玩家信息 - * @param roleId 玩家id - * @param score 得分 - * @param timestamp 时间点 - * @param role 玩家数据库数据 - * @param isInc 得分是累加上的还是直接设置的 - */ - public async setRankWithRoleInfo(roleId: string, score: number, timestamp: number, role?: RoleType, isInc = false) { - // 如果没有信息,更新玩家信息 - for (let infoKey of [this.infoKey, ...this.extraKeys]) { - const hasCurUser = await redisClient().hexistsAsync(infoKey, roleId); - if (!hasCurUser) { - await this.generParamAndSet(infoKey, { roleId }, { role }); - } - } - let newScore = await this.setRank({ roleId }, [score, timestamp], isInc); - - return newScore; - } - - /** - * 根据军团表设置更新排行榜&军团信息 - * @param guildCode 军团code - * @param score 得分 - * @param timestamp 时间点 - * @param guild 军团数据库 - * @param isInc 得分是累加上的还是直接设置的 - */ - public async setRankWithGuildInfo(guildCode: string, score: number, timestamp: number, guild?: GuildType, isInc = false) { - return await this.setRankWithGuildInfoArrParam(guildCode, [score, timestamp], guild, isInc); - } - - public async setRankWithGuildInfo2(guildCode: string, num1: number, num2: number, num3: number, guild?: GuildType, isInc = false) { - return await this.setRankWithGuildInfoArrParam(guildCode, [num1, num2, num3], guild, isInc); - } - - public async setRankWithGuildInfoArrParam(guildCode: string, scores: number[], guild?: GuildType, isInc = false) { - for (let infoKey of [this.infoKey, ...this.extraKeys]) { - const hasCurUser = await redisClient().hexistsAsync(infoKey, guildCode); - if (!hasCurUser) { - await this.generParamAndSet(infoKey, { guildCode }, { guild }); - } - } - let newScore = await this.setRank({ guildCode }, scores, isInc); - - return newScore; - } - - public async setRankWithLeagueInfo(leagueCode: string, score: number, timestamp: number, league?: GVGLeagueType, isInc = false) { - return await this.setRankWithLeagueInfoArrParam(leagueCode, [score, timestamp], league, isInc); - } - - public async setRankWithLeagueInfoArrParam(leagueCode: string, scores: number[], league?: GVGLeagueType, isInc = false) { - for (let infoKey of [this.infoKey, ...this.extraKeys]) { - const hasCurUser = await redisClient().hexistsAsync(infoKey, leagueCode); - if (!hasCurUser) { - await this.generParamAndSet(infoKey, { leagueCode }, { league }); - } - } - let newScore = await this.setRank({ leagueCode }, scores, isInc); - - return newScore; - } - - /** - * 根据武将表设置更新排行榜&玩家信息 - * @param roleId 玩家id - * @param hid 武将id - * @param score 得分 - * @param timestamp 时间点 - * @param hero 武将数据库 - * @param isInc 得分是累加上的还是直接设置的 - */ - public async setRankWithHeroInfo(roleId: string, hid: number, score: number, timestamp: number, hero?: HeroUpdate, isInc = false) { - // 如果没有信息,更新玩家信息 - for (let infoKey of [this.infoKey, ...this.extraKeys]) { - await this.generParamAndSet(infoKey, { roleId, hid }, { hero }); - } - let newScore = await this.setRank({ roleId, hid }, [score, timestamp], isInc); - - return newScore; - } - - /** - * 将玩家信息按顺序组成 如:roleId:hid - * @param {{ string }} key redis key - * @param {{ roleId?: string; guildCode?: string; hid?: number; leagueCode?: string }} param 玩家信息 - */ - private composeFields(key: REDIS_KEY, param: myIdInter) { - let type = KEY_TO_COMPOSE_FIELD.get(key); - - if (type == COMPOSE_FIELD_TYPE.ROLE) { - return param.roleId; - } else if (type == COMPOSE_FIELD_TYPE.GUILD) { - return param.guildCode; - } else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) { - return `${param.roleId}:${param.hid}`; - } else if (type == COMPOSE_FIELD_TYPE.LEAGUE) { - return `${param.leagueCode}`; - } else { - return ''; - } - } - - /** - * 将合成了的玩家顺序解开 - * @param key redis key - * @param field - * @returns {{ roleId?: string; guildCode?: string; hid?: number }} - */ - private decodeFields(key: REDIS_KEY, field: string) { - let type = KEY_TO_COMPOSE_FIELD.get(key); - - let arr = field.split(':'); - if (type == COMPOSE_FIELD_TYPE.ROLE) { - return { roleId: arr[0] }; - } else if (type == COMPOSE_FIELD_TYPE.GUILD) { - return { guildCode: arr[0] }; - } else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) { - return { roleId: arr[0], hid: parseInt(arr[1]) }; - } else if (type == COMPOSE_FIELD_TYPE.LEAGUE) { - return { leagueCode: arr[0] }; - } else { - return {}; - } - } - - /** - * 将玩家数据设置进redis - * @param infoKey 玩家信息的redis key - * @param fields 玩家id - * @param db 数据库内的数据 - */ - public async generParamAndSet(infoKey: string, fields: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroUpdate, league?: GVGLeagueType }) { - let { roleId, guildCode, hid, leagueCode } = fields; - let { role, guild, hero, league } = db; - - if (infoKey == REDIS_KEY.USER_INFO) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - if(!role) return; - } - let param = new RankParam(role); - await this.setUserInfo(infoKey, { roleId }, param); - } else if (infoKey == REDIS_KEY.GUILD_INFO) { - if (!guild) { - guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK) - if(!guild) return; - } - let param = new GuildRankParam(guild); - await this.setUserInfo(infoKey, { guildCode }, param); - } else if (infoKey == REDIS_KEY.LEAGUE_INFO) { - if (!league) { - league = await GVGLeagueModel.findByCode(leagueCode); - if(!league) return; - } - let param = new LeagueRankParam(league); - await this.setUserInfo(infoKey, { leagueCode }, param); - } else if (infoKey == REDIS_KEY.TOP_LINEUP_INFO) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - if(!role) return; - } - let { topLineup = [] } = role; - let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); - let arr = new Array(); - for (let { hid } of topLineup) { - let curHero = heroes.find(cur => cur.hid == hid); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - await this.setUserInfo(infoKey, { roleId }, arr); - } else if (infoKey == REDIS_KEY.HERO_INFO) { - if (!hero) { - hero = await HeroModel.findByHidAndRole(hid, roleId, HERO_SELECT.RANK_LINEUP, true); - if(!hero) return; - } - let arr = new Array(); - if (hero) { - let param = new LineupParam(hero); - arr.push(param); - await this.setUserInfo(infoKey, { roleId, hid }, arr); - } - } else if (infoKey == REDIS_KEY.DUNGEON_LINEUP) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - if(!role) return; - } - let { dungeonWarId, dungeonHeroes } = role; - if (dungeonWarId > 0) { - let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId); - let lineup = cur ? cur.heroes : []; - let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); - let arr = new Array(); - for (let seqId of lineup) { - let curHero = heroes.find(cur => cur.seqId == seqId); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - await this.setUserInfo(infoKey, { roleId }, arr); - } - } else if (infoKey == REDIS_KEY.SHOW_LINEUP) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - if(!role) return; - } - let { showLineup, topLineup = [] } = role; - let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); - let arr = new Array(); - if (!showLineup) showLineup = topLineup.map(cur => cur.hid); - for (let hid of showLineup) { - let curHero = heroes.find(cur => cur.hid == hid); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - await this.setUserInfo(infoKey, { roleId }, arr); - } - } - - /** - * 设置信息 - * @param infoKey - * @param myId - * @param param - */ - private async setUserInfo(infoKey: REDIS_KEY, myId: myIdInter, param: RankParam | GuildRankParam | LineupParam[] | LeagueRankParam) { - let field = this.composeFields(infoKey, myId); - let value = JSON.stringify(param); - return await redisClient().hsetAsync(infoKey, field, value); - } - - /** - * 更新排行榜数据 - * @param myId - * @param score - * @param timestamp - * @param isInc - */ - public async setRank(myId: myIdInter, scores: number[], isInc = false) { - let oldTop = await this.getRankByRank(0, 0); - let oldScore = oldTop.length > 0 && oldTop[0] ? oldTop[0].num : 0; - // 更新分数 - let newScore = 0; - if (this.isUnion) { - newScore = await this.updateRankScoreAtom(myId, scores, isInc); - } else { - newScore = await this.updateRankScoreEncode(myId, scores, isInc) - } - this.checkFirstRankAndPush(myId, oldScore, newScore); - return newScore; - } - - /** - * @description 使用将score和time合成一个字段更新分数 - * @param myId - * @param score - * @param timestamp - */ - private async updateRankScoreEncode(myId: myIdInter, scores: number[] = [], isInc = false) { - let newScore = 0; - let key = this.keyName.getName(); - let newScores: number[] = []; - for(let index = 0; index < this.valueConfig.length; index ++) { - let config = this.valueConfig[index]; - let score = scores[index]; - if(config.isMain) { - if (isInc) { - let oldScore = await this.getMyScore(myId); - newScore = oldScore + score; - } else { - newScore = score; - } - newScores.push(newScore); - } else { - newScores.push(score); - } - } - - let scoreStr = this.encodeScore(newScores); - await redisClient().zaddAsync(key, scoreStr, this.composeFields(this.key, myId)); - return newScore - } - - /** - * @description 使用分两个zset更新redis中某field的值 - * @param myId - * @param score - * @param timestamp - * @param isInc - * @class Rank - */ - private async updateRankScoreAtom(myId: myIdInter, scores: number[], isInc = false) { - - let newScore = 0; - for(let index = 0; index < this.valueConfig.length; index ++) { - let config = this.valueConfig[index]; - let score = scores[index]; - if(config.isMain) { - let key = this.keyName.getName(); - // 分数zset - if (isInc) { - newScore = await redisClient().zincrbyAsync(key, score, this.composeFields(this.key, myId)); - } else { - newScore = await redisClient().zaddAsync(key, score, this.composeFields(this.key, myId)); - } - } else { - let key = this.keyName.getNameWithPlus(config.name); - if(config.isTimestamp) score = this.handleTimestamp(score, config.len); - if(config.reverse) { - let pow = Math.pow(10, config.len); - score = pow - 1 - score; - } - await redisClient().zaddAsync(key, score, this.composeFields(this.key, myId)); - } - } - return parseInt(newScore.toString()); - } - - - /** - * @description 设置到期时间 - * @param time 到期时间,10位时间戳 - * @class Rank - */ - public async setExpire(time: number) { - let key = this.keyName.getName(); - let timeKey = this.keyName.getTimeName(); - - await redisClient().expireatAsync(key, time); - await redisClient().expireatAsync(timeKey, time); - } - - public async generMyRankWithRole(roleId: string, score: number = 0, time: number = 0, role?: RoleType) { - // 如果没有信息,更新玩家信息 - let param: RoleRankInfo; - - let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); - if (!hasCurUser) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - } - param = new RoleRankInfo(role); - param.setInfo(0, { roleId }, score, time); - } else { - const info = await redisClient().hgetAsync(this.infoKey, roleId); - const userInfo = JSON.parse(info); - - param = new RoleRankInfo(userInfo); - param.setInfo(0, { roleId }, score, time); - } - - for (let extraKey of this.extraKeys) { - await this.setExInfoToParam(extraKey, param, { roleId }, { role }); - } - - return await this.generFields(param); - } - - public async generMyRankWithGuild(guildCode: string, score: number, time: number, guild?: GuildType) { - // 如果没有信息,更新玩家信息 - let param: GuildRankInfo; - - let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); - if (!hasCurUser) { - if (!guild) { - guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); - if(!guild) return null - } - param = new GuildRankInfo(guild); - param.setInfo(0, { guildCode }, score, time); - } else { - const info = await redisClient().hgetAsync(this.infoKey, guildCode); - if(!info) return null - const guildInfo = JSON.parse(info); - param = new GuildRankInfo(guildInfo); - param.setInfo(0, { guildCode }, score, time); - } - - for (let extraKey of this.extraKeys) { - await this.setExInfoToParam(extraKey, param, { guildCode }, { guild }); - } - - return await this.generFields(param); - } - - public async generMyRankWithGuild2(guildCode: string, score: number, time: number, active: number, guild?: GuildType) { - // 如果没有信息,更新玩家信息 - let param: GuildRankInfo; - - let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); - if (!hasCurUser) { - if (!guild) { - guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); - if(!guild) return null - } - param = new GuildRankInfo(guild); - param.setInfo2(0, { guildCode }, score, time, active); - } else { - const info = await redisClient().hgetAsync(this.infoKey, guildCode); - const guildInfo = JSON.parse(info); - if(!guildInfo) return null - param = new GuildRankInfo(guildInfo); - param.setInfo2(0, { guildCode }, score, time, active); - } - - for (let extraKey of this.extraKeys) { - await this.setExInfoToParam(extraKey, param, { guildCode }, { guild }); - } - - return await this.generFields(param); - } - - public async generMyRankWithLeague(leagueCode: string, score: number, time: number, league?: GVGLeagueType) { - // 如果没有信息,更新玩家信息 - let param: LeagueRankInfo; - - let hasCurUser = await redisClient().hexistsAsync(this.infoKey, leagueCode); - if (!hasCurUser) { - if (!league) { - league = await GVGLeagueModel.findByCode(leagueCode); - if(!league) return null - } - param = new LeagueRankInfo(league); - param.setInfo(0, { leagueCode }, score, time); - } else { - const info = await redisClient().hgetAsync(this.infoKey, leagueCode); - if(!info) return null - const leagueInfo = JSON.parse(info); - param = new LeagueRankInfo(leagueInfo); - param.setInfo(0, { leagueCode }, score, time); - } - - return await this.generFields(param); - } - - public async generMyRankWithHero(roleId: string, hid: number, score: number, time: number, hero?: HeroType, role?: RoleType) { - // 如果没有信息,更新玩家信息 - let param: RoleRankInfo; - - let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); - if (!hasCurUser) { - if (!role) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - } - param = new RoleRankInfo(role); - param.setInfo(0, { roleId, hid }, score, time); - } else { - const info = await redisClient().hgetAsync(this.infoKey, roleId); - const userInfo = JSON.parse(info); - - param = new RoleRankInfo(userInfo); - param.setInfo(0, { roleId, hid }, score, time); - } - - for (let extraKey of this.extraKeys) { - await this.setExInfoToParam(extraKey, param, { roleId, hid }, { hero, role }); - } - - return await this.generFields(param); - } - - private async setExInfoToParam(extraKey: string, param: RoleRankInfo | GuildRankInfo | LeagueRankInfo, myId: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) { - let { role, guild, hero } = db; - - if (extraKey == REDIS_KEY.TOP_LINEUP_INFO) { - param = param; - - let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); - if (!hasCurUser) { - if (!role) { - role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); - } - - let { topLineup } = role; - let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL); - let arr = new Array(); - for (let { hid } of topLineup) { - let curHero = heroes.find(cur => cur.hid == hid); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - param.setTopLine(arr); - } else { - const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); - const infoObj = JSON.parse(info); - param.setTopLine(infoObj); - } - } else if (extraKey == REDIS_KEY.HERO_INFO) { - param = param; - - let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); - if (!hasCurUser) { - if (!hero) { - hero = await HeroModel.findByHidAndRole(myId.hid, myId.roleId, HERO_SELECT.RANK_LINEUP); - } - let arr = new Array(); - let lineParam = new LineupParam(hero); - arr.push(lineParam); - if (this.key == REDIS_KEY.HERO_RANK) { - param.setSingleHero(arr); - } else { - param.setTopLine(arr); - } - } else { - const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); - const infoObj = JSON.parse(info); - if (this.key == REDIS_KEY.HERO_RANK) { - param.setSingleHero(infoObj); - } else { - param.setTopLine(infoObj); - } - } - } else if (extraKey == REDIS_KEY.DUNGEON_LINEUP) { - param = param; - - let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); - if (!hasCurUser) { - if (!role) { - role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); - } - let { dungeonWarId, dungeonHeroes } = role; - let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId); - let lineup = cur ? cur.heroes : []; - let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.RANK_LINEUP); - let arr = new Array(); - for (let seqId of lineup) { - let curHero = heroes.find(cur => cur.seqId == seqId); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - param.setTopLine(arr); - } else { - const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); - const infoObj = JSON.parse(info); - param.setTopLine(infoObj); - } - } else if (extraKey == REDIS_KEY.SHOW_LINEUP) { - param = param; - - let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); - if (!hasCurUser) { - if (!role) { - role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); - } - - let { showLineup, topLineup = [] } = role; - let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL); - let arr = new Array(); - if (!showLineup) showLineup = topLineup.map(cur => cur.hid); - for (let hid of showLineup) { - let curHero = heroes.find(cur => cur.hid == hid); - if (curHero) { - let param = new LineupParam(curHero); - arr.push(param); - } - } - param.setTopLine(arr); - } else { - const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); - const infoObj = JSON.parse(info); - param.setTopLine(infoObj); - } - } - } - - public async getRankListWithMyRank(myId: myIdInter, isReverse = true) { - let ranks = await this.getRankByRange(1000, 0, isReverse); - let newRanks = [], newMyRank: any; - let myRank = ranks.find(cur => { - return cur.isMyInfo(myId); - }); - if (this.generFields) { - for (let rank of ranks) { - let n = await this.generFields(rank); - if(n) newRanks.push(n); - } - if (myRank) { - newMyRank = await this.generFields(myRank); - } - } - - return { myRank: newMyRank, ranks: newRanks } - } - - /** - * 获取排行榜原始数据 - * @param from - * @param to - */ - public async getRankDataByRankWithoutDetail(from: number | '+inf' = '+inf', to: number | '-inf' = '-inf') { - let key = this.keyName.getName(); - if (this.isUnion) { - key = await this.generateUnionRank(); - } - - const rankFromDb = (from == '+inf' && to == '-inf')? - (await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES")): - (await redisClient().zrevrangeAsync(key, from, to, "WITHSCORES")) - ; - let ranks: { rank: number, myId: {roleId?: string, guildCode?: string, hid?: number}, scores: number[] }[] = []; - - let num = 0; - for (let ii = 0; ii < rankFromDb.length; ii += 2) { - if (num >= this.limit) break; - - const field = rankFromDb[ii]; - let myId = this.decodeFields(this.key, field); - const scores = this.decodeScore(rankFromDb[ii + 1]); - - ranks.push({ rank: num, myId, scores }); - num++; - } - return ranks - } - - // 获取区间里的排行榜,格式 {rank, field, score}[] - public async getRankByRangeRaw(max: number | string = '+inf', min: number | string = '-inf', isReverse = true, byScore = false) { - let ranks: { rank: number, field: string, scores: number[] }[] = []; - let key = this.keyName.getName(); - if (this.isUnion) { - key = await this.generateUnionRank(); - } - - const rankFromDb = isReverse? - (((max == '+inf' && min == '-inf') || byScore)? - (await redisClient().zrevrangebyscoreAsync(key, max, min, "WITHSCORES")): - (await redisClient().zrevrangeAsync(key, min, max, "WITHSCORES")) - ): - (((max == '+inf' && min == '-inf') || byScore)? - (await redisClient().zrangebyscoreAsync(key, min, max, "WITHSCORES")): - (await redisClient().zrangeAsync(key, min, max, "WITHSCORES")) - ) - - let num = 0; - for (let ii = 0; ii < rankFromDb.length; ii += 2) { - if (num >= this.limit) break; - ranks.push({ rank: Math.floor(ii / 2) + 1, field: rankFromDb[ii], scores: this.decodeScore(rankFromDb[ii + 1]) }); - num++; - } - return ranks - } - - public async getRankByRange(max: number | string = '+inf', min: number | string = '-inf', isReverse = true, byScore = false) { - let raws = await this.getRankByRangeRaw(max, min, isReverse, byScore); - - let ranks = new Array(); - let l = 1; - for (let { field, scores } of raws) { - let param = await this.getParam(l, field, scores); - if(param) { - ranks.push(param); l++; - } - } - return ranks - } - - public async getParam(rank: number, field: string, scores: number[]) { - let myId = this.decodeFields(this.key, field); - - const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId)); - const userInfo = JSON.parse(info); - if(!userInfo) return null; - - let param: RoleRankInfo | GuildRankInfo | LeagueRankInfo; - if (this.infoKey == REDIS_KEY.USER_INFO) { - // if (this.key != REDIS_KEY.LADDER && this.key != REDIS_KEY.GVG_VESTIGE_MEMBER && nowSeconds() - userInfo.updatedAt > 2 * 30 * 24 * 60 * 60) { - // return null; - // } - param = new RoleRankInfo(userInfo); - param.setInfo(rank, myId, scores[0], scores[1]); - } else if (this.infoKey == REDIS_KEY.GUILD_INFO) { - if(this.key == REDIS_KEY.GUILD_LV_RANK|| this.key == REDIS_KEY.RACE_ACTIVITY) { - param = new GuildRankInfo(userInfo); - param.setInfo2(rank, myId, scores[0], scores[1], scores[2]); - } else { - param = new GuildRankInfo(userInfo); - param.setInfo(rank, myId, scores[0], scores[1]); - } - } else if (this.infoKey == REDIS_KEY.LEAGUE_INFO) { - param = new LeagueRankInfo(userInfo); - param.setInfo(rank, myId, scores[0], scores[1]); - - } - - for (let extraKey of this.extraKeys) { - await this.setExInfoToParam(extraKey, param, myId, {}); - } - return param - } - - public async getRankByRank(start: number, end: number) { - - let ranks = new Array(); - let key = this.keyName.getName(); - if (this.isUnion) { - key = await this.generateUnionRank(); - } - - const rankFromDb = await redisClient().zrevrangeAsync(key, start, end, "WITHSCORES"); - - // console.log(key, start, end, rankFromDb) - - let num = 0; - for (let ii = 0; ii < rankFromDb.length; ii += 2) { - if (num >= this.limit) break; - let param = await this.getParam(Math.floor(ii / 2) + 1, rankFromDb[ii], this.decodeScore(rankFromDb[ii + 1])); - if(param) ranks.push(param); - num++; - } - return ranks - } - - - // 获取我的排名 - public async getMyRank(myId: myIdInter) { - let key = this.keyName.getName(); - if (this.isUnion) { - key = await this.generateUnionRank(); - } - // console.log('**getMyRank',key, this.composeFields(this.key, myId), this.key, myId) - let myRank = await redisClient().zrevrankAsync(key, this.composeFields(this.key, myId)); - if (!myRank && myRank != 0) { - return 0; - } else { - return myRank + 1; - } - } - - // 获取排名第几名的信息 - public async getUserByRank(rank: number) { - let key = this.keyName.getName(); - let myRank = await redisClient().zrevrangeAsync(key, rank - 1, rank - 1); - return myRank; - } - - - // 获取排名第几名的信息 - public async getMyScore(myId: myIdInter) { - let key = this.keyName.getName(); - let score = await redisClient().zscoreAsync(key, this.composeFields(this.key, myId)); - if (!score) score = 0; - if (!this.isUnion) { - let result = this.decodeScore(score.toString()); - score = result[0]; - } - return parseInt(score.toString()); - } - - // 从排行榜中移除 - public async removeFromRank(myId: myIdInter) { - let key = this.keyName.getName(); - await redisClient().zremAsync(key, this.composeFields(this.key, myId)); - - return true; - } - - private async generateUnionRank() { - let unionKey = this.keyName.getUnionName(); // 联合的key - - let keys = [], weights = []; - this.valueConfig.forEach(({ isMain, name, weight }) => { - if(isMain) { - keys.push(this.keyName.getName()); - } else { - keys.push(this.keyName.getNameWithPlus(name)); - } - weights.push(Math.pow(10, weight)) - - }) - - await redisClient().zunionstoreAsync(unionKey, 2, ...keys, 'WEIGHTS', ...weights); - await redisClient().expireAsync(unionKey, this.unionRankLife); // 10秒更新一次 - return unionKey; - } - - // 有序排行综合时间和得分排序 - private encodeScore(scores: number[]) { - let encodeResult = 0; - // console.log('#### decoencodeResultdeScore', this.key, scores, this.valueConfig); - this.valueConfig.forEach(({ name, reverse, isTimestamp, len, weight }, index) => { - let score = scores[index]; - // console.log('*** 1', name, len, weight, score, encodeResult) - if(isTimestamp) score = this.handleTimestamp(score, len); - // console.log('*** 2', name, len, weight, score, encodeResult) - if(!reverse) { - encodeResult += score * Math.pow(10, weight); - } else { - let pow = Math.pow(10, len); - encodeResult += (pow - 1 - score) * Math.pow(10, weight); - } - // console.log('*** 3', name, len, weight, score, encodeResult) - }) - return encodeResult - } - - private decodeScore(num: string) { - let _num = parseInt(num); - let scores: number[] = []; - this.valueConfig.forEach(({ name, reverse, isTimestamp, len, weight }) => { - let pow = Math.pow(10, weight); - let score = Math.floor(_num / pow); - // console.log('*** 1', name, len, weight, score) - _num -= pow * score; - if(isTimestamp) score = this.handleTimestamp(score, len); - // console.log('*** 2', name, len, weight, score) - if(reverse) { - let pow = Math.pow(10, len); - score = pow - 1 - score; - } - // console.log('*** 3', name, len, weight, score) - scores.push(score); - }) - // console.log('#### decodeScore', this.key, scores, this.valueConfig); - return scores; - } - - private handleTimestamp(timestamp: number = 0, len: number) { - let l = timestamp.toString().length; - if (l > len) { - timestamp = Math.floor(timestamp / Math.pow(10, l - len)); - } - return timestamp - } - - private async getFirstUserInfo(myId: myIdInter) { - const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId)); - if(!info) return null - const playerInfo = JSON.parse(info); - - if (this.infoKey == REDIS_KEY.USER_INFO) { - let userInfo = new RankParam(playerInfo); - return { userInfo } - } else if (this.infoKey == REDIS_KEY.GUILD_INFO) { - let guildInfo = new GuildRankInfo(playerInfo); - return { guildInfo } - } - return false - } - - // 首通 - private async checkFirstRankAndPush(myId: myIdInter, oldScore: number, newScore: number) { - let ts = this; - if (ts.isInit) return; - - let serverId = this.keyName.serverId; - let dicRank = gameData.rank.find(({ id }) => { - let redisKey = getRedisKeyByRankType(id); - return redisKey == ts.key - }); - if(!dicRank) return; - - let infos = await this.getFirstUserInfo(myId); - if(!infos) return; - - let { userInfo, guildInfo } = infos - let rankFirstRecs: (RankFirstType & { status: number })[] = []; - for(let [id, { rankId, condition }] of gameData.generalRankReward) { - // console.log(rankId, dicRank.id, oldScore, condition, newScore); - let hasRankFirst = await getRankFirstRewardById(serverId, id); - if(!hasRankFirst && dicRank.id == rankId && oldScore < condition && newScore >= condition) { - let rankFirstRec = await RankFirstModel.createRankFirst(serverId, id, rankId, { userInfo, guildInfo }); - if(rankFirstRec && getSeconds(rankFirstRec.createdAt) == getSeconds(rankFirstRec.updatedAt)) { - await setRankFirst(rankFirstRec); - rankFirstRecs.push({ ... rankFirstRec, status: 1}); - } - } - } - - if(rankFirstRecs.length > 0) { - await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.RANK_TOP_UPDATE, { ranks: rankFirstRecs }, true); - } - } -} - -/** - * 从其他服获取首通信息 - * @param serverId - * @param id dic_zyz_rankingType的id - * @returns - */ -async function getRankFirstRewardById(serverId: number, id: number) { - let rankFirst: RankFirstType; - if(pinus.app.getServerType() == 'role') { - rankFirst = pinus.app.get('rankFirstRewards').get(serverId)?.get(id); - } else { - let roleServers = pinus.app.getServersByType('role'); - let server = getRandSingleEelm(roleServers); - rankFirst = await pinus.app.rpc.role.roleRemote.getRankFirstById.toServer(server.id, serverId, id); - } - return rankFirst; -} - -async function setRankFirst(rankFirstRec: RankFirstType) { - let roleServers = pinus.app.getServersByType('role'); - for(let server of roleServers) { - pinus.app.rpc.role.roleRemote.setRankFirst.toServer(server.id, rankFirstRec); - } -} - -/** - * 从数据库内获取排行榜存入redis - * @param type 排行榜类型 - * @param serverId 分服 - */ -export async function setRankRedisFromDb(type: string, args?: { serverId?: number, groupId?: number }) { - if (type == REDIS_KEY.TOWER_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('tower', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - // console.log(roleId); - if(role.towerLv > 1) { - await r.setRankWithRoleInfo(role.roleId, role.towerLv - 1, role.towerUpTime ? role.towerUpTime.getTime() : 0, role); - } - } - } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { - let serverId = args.serverId; - let ranks = await GuildModel.getRank(type, serverId); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let guild of ranks) { - await r.setRankWithGuildInfo(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); - } - } else if (type == REDIS_KEY.GUILD_LV_RANK) { - - let serverId = args.serverId; - let ranks = await GuildModel.getRank(type, serverId); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let guild of ranks) { - await r.setRankWithGuildInfoArrParam(guild.code, [guild.lv, guild.activeWeekly, guild.activeUpdateTime], guild); - } - } else if (type == REDIS_KEY.PVP_RANK) { - let pvpConfig = await PVPConfigModel.findCurPVPConfig(); - let seasonNum = pvpConfig?.seasonNum; - if(seasonNum > 0) { - let serverGroup = await getPVPServerGroup(); - for(let [groupId, serverIds] of serverGroup) { - let keyName = new KeyName(type, { seasonNum, groupId }) - await delKeys(keyName.getName()); - let ranks = await PvpDefenseModel.getRank(serverIds, seasonNum);//获得全服前1000名的排名,加入到redis中 - - let r = new Rank(type, { seasonNum, groupId }); - r.setIsInit(true); - for (let { roleId, role: _role, score, updatedAt } of ranks) { - let role = _role; - if (!role) { - continue; - } - await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role); - } - } - } - } else if (type == REDIS_KEY.TOP_LINEUP_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('topLineup', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - // console.log(roleId); - await r.setRankWithRoleInfo(role.roleId, role.topLineupCe, role.updatedAt.getTime(), role); - } - } else if (type == REDIS_KEY.TOP_HERO_RANK) { - let serverId = args.serverId; - let ranks = await HeroModel.getAllRank(serverId, HERO_SELECT.RANK_LINEUP); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let hero of ranks) { - await r.setRankWithHeroInfo(hero.roleId, hero.hid, hero.ce, hero.updatedAt.getTime(), hero); - } - } else if (type == REDIS_KEY.HERO_NUM_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('heroNum', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.heroNum, role.heroNumUpdatedAt, role); - } - } else if (type == REDIS_KEY.USER_LV) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('lv', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.lv, role.updatedAt.getTime(), role); - } - } else if (type == REDIS_KEY.SUM_CE_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('ce', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.ce, role.updatedAt.getTime(), role); - } - } else if (type == REDIS_KEY.DUNGEON_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('dungeon', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); - } - } else if (type == REDIS_KEY.MAIN_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('main', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.mainWarId, role.mainUpdatedAt, role); - } - } else if (type == REDIS_KEY.MAIN_ELITE_RANK) { - let serverId = args.serverId; - let ranks = await RoleModel.getRank('mainElite', serverId, ROLE_SELECT.RANK); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let role of ranks) { - await r.setRankWithRoleInfo(role.roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); - } - // } else if (type == REDIS_KEY.HERO_RANK) { - // let serverId = args.serverId; - - // for (let [hid] of gameData.recruit) { - // let ranks = await Hero.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP); - // let r = new Rank(type, { serverId, hid }); - // r.setIsInit(true); - // for (let hero of ranks) { - // await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero); - // } - // } - } else if (type == REDIS_KEY.HERO_RANK) { - let serverId = args.serverId; - - for (let [hid] of gameData.recruit) { - let ranks = await HeroModel.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP); - let r = new Rank(type, { serverId, hid }); - r.setIsInit(true); - for (let hero of ranks) { - await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero); - } - } - } else if (type == REDIS_KEY.LADDER) { - let serverId = args.serverId; - let ranks = await LadderMatchModel.findAll(serverId); - let r = new Rank(type, { serverId }); - r.setIsInit(true); - for (let rank of ranks) { - let role = rank.role; - await r.setRankWithRoleInfo(rank.roleId, rank.rank, 0, role); - await saveLadderDefCeByData(rank.roleId, rank); - } - } else if (type == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) { - let ranks = await GVGVestigeSumRankModel.findRankByGroupId(); - for(let { _id: groupKey, arr, roleIds } of ranks) { - let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.RANK); - let r = new Rank(type, { groupKey, day: getDayKeyInfo() }); - r.setIsInit(true); - for(let { roleId, score, updatedAt } of arr) { - let role = roles.find(cur => cur.roleId == roleId); - if(role) { - await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role); - } - } - } - } else if (type == REDIS_KEY.GVG_VESTIGE_LEAGUE) { - let ranks = await GVGVestigeLeagueRankModel.findRank(); - for(let { _id: groupKey, arr, leagueCodes } of ranks) { - let leagues = await GVGLeagueModel.findByCodes(leagueCodes); - let r = new Rank(type, { groupKey, day: getDayKeyInfo() }); - r.setIsInit(true); - for(let { leagueCode, score, updatedAt } of arr) { - let league = leagues.find(cur => cur.leagueCode == leagueCode); - if(league) { - await r.setRankWithLeagueInfo(leagueCode, score, updatedAt.getTime(), league); - } - } - } - } else if (type == REDIS_KEY.ACTIVITY_MINI_GAME) { - let ranks = await ActivityMiniGameModel.findRank(); - for(let { _id: { activityId, roundIndex }, roleIds, arr } of ranks) { - let r = new Rank(type, { activityId, roundIndex }); - let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.RANK); - for(let { roleId, score, updatedAt } of arr) { - let role = roles.find(cur => cur.roleId == roleId); - if(role) await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role, false); - } - } - } -} - -/** - * 获取排行榜总览 - * @param role 玩家数据 - * @param serverId 所在服务器 - */ -export async function getGeneralRank(role: RoleType & { rankReceived: number[] }, serverId: number) { - let { rankReceived = [] } = role; - - let result: (GeneralRankParam & {general: number})[] = []; - - for (let { id, general } of gameData.rank) { - let redisKey = getRedisKeyByRankType(id); - if (redisKey) { - let received = rankReceived.filter(rewardId => { - let dic = gameData.generalRankReward.get(rewardId); - return dic && dic.rankId == id; - }); - let r = new Rank(redisKey, { serverId }, false, 1); - let ranks = await r.getRankByRange(1, 0, id != RANK_TYPE.LADDER); - // if (ranks.length > 0) { - let param = new GeneralRankParam(id, ranks[0], general, received); - result.push({...param, general}); - } - } - return result; -} - -/** - * 获取排行榜总览 - * @param role 玩家数据 - * @param serverId 所在服务器 - */ - export async function getRankFirstReward(role: RoleType & { rankReceived: number[] }, serverId: number) { - let { rankReceived = [] } = role; - - let result: (RankFirstUpdateParam & {status: number})[] = []; - - for (let [id, { rankId: type } ] of gameData.generalRankReward) { - let rankFirst = await getRankFirstRewardById(serverId, id); - - if(rankFirst) { - let status = rankReceived.includes(id)?RANK_FIRST_REWARD_STATUS.RECEIVED: RANK_FIRST_REWARD_STATUS.CAN_RECEIVE; - result.push({...rankFirst, status}); - } else { - result.push({ id, type, status: RANK_FIRST_REWARD_STATUS.WAITING }); - } - } - return result; -} - -export async function getRankInHandler(redisKey: REDIS_KEY, type: RANK_TYPE, keyParam: KeyNameParam, session: BackendSession) { - - const roleId = session.get('roleId'); - const serverId = session.get('serverId'); - const guildCode = session.get('guildCode'); - - let r = new Rank(redisKey, keyParam); - r.setGenerFieldsFun((obj => { - let result = new RoleAndGuildRankInfo(obj.rank, obj.num); - if(type == RANK_TYPE.LADDER) { - result = new RoleAndGuildRankInfo(obj.num, 0); - } - if(obj instanceof GuildRankInfo) { - result.setGuildInfo(obj); - } - if(obj instanceof RoleRankInfo) { - result.setUserInfo(obj); - } - return result - })); - - let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }, type != RANK_TYPE.LADDER); - if (!myRank) { - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); - if (type == RANK_TYPE.TOP_LINTUP) { - myRank = await r.generMyRankWithRole(roleId, role.topLineupCe, 0, role); - } else if (type == RANK_TYPE.TOP_HERO) { - let hero = await HeroModel.getMyTopHero(roleId, HERO_SELECT.RANK_LINEUP); - myRank = await r.generMyRankWithHero(roleId, hero.hid, hero.ce, 0, hero, role); - } else if (type == RANK_TYPE.HERO_NUM) { - myRank = await r.generMyRankWithRole(roleId, role.heroNum, role.heroNumUpdatedAt, role); - } else if (type == RANK_TYPE.USER_LV) { - myRank = await r.generMyRankWithRole(roleId, role.lv, role.updatedAt.getTime(), role); - } else if (type == RANK_TYPE.SUM_CE) { - myRank = await r.generMyRankWithRole(roleId, role.ce, role.updatedAt.getTime(), role); - } else if (type == RANK_TYPE.TOWER) { - myRank = await r.generMyRankWithRole(roleId, role.towerLv - 1, role.towerUpTime?.getTime() || 0, role); - // } else if (type == RANK_TYPE.DUNGEON) { - // myRank = await r.generMyRankWithRole(roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); - } else if (type == RANK_TYPE.MAIN) { - myRank = await r.generMyRankWithRole(roleId, role.mainWarId, role.mainUpdatedAt, role); - } else if (type == RANK_TYPE.MAIN_ELITE) { - myRank = await r.generMyRankWithRole(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); - } else if (type == RANK_TYPE.GUILD_LV) { - if(role.hasGuild) { - let guild = await GuildModel.findByCode(guildCode, serverId); - if(guild) myRank = await r.generMyRankWithGuild2(roleId, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); - } - } else if (type == RANK_TYPE.GUILD_FUND) { - if(role.hasGuild) { - let limitRank = await ActivityTimeLimitRankModel.findByCode(serverId, keyParam.activityId, guildCode); - myRank = await r.generMyRankWithGuild(guildCode, limitRank?.score||0, limitRank?.time); - } - } else if (type == RANK_TYPE.LADDER) { - myRank = await r.generMyRankWithRole(roleId, 0, 0, role); - } - } - // if(type == RANK_TYPE.LADDER) { - ranks = completeRanks(ranks); - // } - return { ranks, myRank } -} \ No newline at end of file +import { KeyName, KeyNameParam, RankParam, GuildRankParam, RoleRankInfo, LineupParam, myIdInter, GeneralRankParam, ValueConfig, GuildRankInfo, RoleAndGuildRankInfo, LeagueRankParam, LeagueRankInfo } from "@domain/rank"; +import { getInfoKeyByRedisKey, ROLE_SELECT, GUILD_SELECT, REDIS_KEY, HERO_SELECT, COMPOSE_FIELD_TYPE, KEY_TO_COMPOSE_FIELD, getRedisKeyByRankType, COUNTER, RANK_TYPE, PUSH_ROUTE } from "@consts"; +import { redisClient, delKeys, saveLadderDefCeByData } from "./redisService"; +import { RoleType, RoleModel } from "@db/Role"; +import { GuildType, GuildModel } from "@db/Guild"; +import { HeroModel, HeroType, HeroUpdate } from "@db/Hero"; +import { PvpDefenseModel } from "@db/PvpDefense"; +import { gameData } from "@pubUtils/data"; +import { getSeconds, nowSeconds } from "@pubUtils/timeUtil"; +import { BackendSession, pinus } from "pinus"; +import { RankFirstModel, RankFirstType, RankFirstUpdateParam } from "@db/RankFirst"; +import { getRandSingleEelm } from "@pubUtils/util"; +import { RANK_FIRST_REWARD_STATUS } from '@consts'; +import { CounterModel } from "@db/Counter"; +import { ActivityTimeLimitRankModel } from "@db/ActivityTimeLimitRank"; +import { sendMessageToServerWithSuc } from "./pushService"; +import { LadderMatchModel } from "@db/LadderMatch"; +import { completeRanks } from "./ladderService"; +import { GVGVestigeSumRankModel } from "@db/GVGVestigeSumRank"; +import { GVGLeagueModel, GVGLeagueType } from "@db/GVGLeague"; +import { GVGVestigeLeagueRankModel } from "@db/GVGVestigeLeagueRank"; +import { getDayKeyInfo } from "./gvg/gvgFightService"; +import { ActivityMiniGameModel } from "@db/ActivityMiniGame"; +import { getPVPServerGroup } from "./serverService"; +import { PVPConfigModel } from "@db/PvpConfig"; + + +/** + * @description 排行榜相关操作 + * @export + * @class Rank + */ +export class Rank { + isInit: boolean = false; // 初始排行榜 + key: REDIS_KEY; // 排行榜原始key + keyName: KeyName; // 拼接之后的key + infoKey: REDIS_KEY; // 玩家数据key + extraKeys: string[]; + isUnion: boolean; // 是否使用多个zset联合计算 + limit: number = 200; // 排行榜长度 + unionRankLife: number = 10; + valueConfig: ValueConfig[] = []; // 值的组合方案 + + constructor(key: REDIS_KEY, keyParam: KeyNameParam, isUnion = false, limit = 200) { + this.key = key; + this.keyName = new KeyName(key, keyParam); + let { infoKey, extraKey } = getInfoKeyByRedisKey(key); + this.infoKey = infoKey; + this.extraKeys = extraKey; + this.isUnion = isUnion; + this.limit = limit; + this.setValueConfig(key); + } + + public setIsInit(init: boolean) { + this.isInit = init; + } + + private setValueConfig(key: REDIS_KEY) { + switch (key) { + case REDIS_KEY.LADDER: + this.valueConfig = [ + new ValueConfig(true, 'rank', 0, false, false) + ]; + break; + case REDIS_KEY.TOP_LINEUP_RANK: + case REDIS_KEY.TOP_LINE_SNAPSHOT: + case REDIS_KEY.TOP_HERO_RANK: + case REDIS_KEY.SUM_CE_RANK: + case REDIS_KEY.SUM_CE_SNAPSHOT: + case REDIS_KEY.HERO_RANK: + this.valueConfig = [ + new ValueConfig(true, 'score', 0, false, false) + ]; + break; + case REDIS_KEY.RACE_ACTIVITY: + this.valueConfig = [ + new ValueConfig(true, 'distance', 0, false, false), + new ValueConfig(false, 'time', 6, true, true), + new ValueConfig(false, 'durability', 3, false, false), + ]; + break; + case REDIS_KEY.GATE_ACTIVITY: + case REDIS_KEY.CITY_ACTIVITY: + case REDIS_KEY.USER_GATE_ACTIVITY: + case REDIS_KEY.USER_CITY_ACTIVITY: + this.valueConfig = [ + new ValueConfig(true, 'score', 0, false, false), + new ValueConfig(false, 'time', 4, true, false), + ]; + break; + case REDIS_KEY.GUILD_LV_RANK: + this.valueConfig = [ + new ValueConfig(true, 'lv', 0, false, false), + new ValueConfig(false, 'active', 5, false, false), + new ValueConfig(false, 'time', 6, true, true) + ]; + break; + default: + this.valueConfig = [ + new ValueConfig(true, 'score', 0, false, false), + new ValueConfig(false, 'time', 10, true, true) + ]; + break; + } + + for(let i = 0; i < this.valueConfig.length; i++) { + let weight = 0; + for(let j = i + 1; j < this.valueConfig.length; j++) { + weight += this.valueConfig[j].len; + } + this.valueConfig[i].setWeight(weight); + } + } + + /** + * 返回字段修改 + * @param obj + */ + private async generFields(obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) { + return obj; + } + + /** + * 从外部设置返回字段 + * @param cb + */ + public setGenerFieldsFun(cb: (obj: GuildRankInfo | RoleRankInfo | LeagueRankInfo) => any) { + this.generFields = cb; + } + + /** + * 设置合成的排行榜的生命时长 单位s + * @param unionRankLife + */ + public setUnionRankLife(unionRankLife: number) { + this.unionRankLife = unionRankLife; + } + + /** + * 该排行是否为空 + * @param void + */ + public async existsRank() { + const result = await redisClient().existsAsync(this.keyName.getName()); + return result; + } + + /** + * 根据role表设置更新排行榜&玩家信息 + * @param roleId 玩家id + * @param score 得分 + * @param timestamp 时间点 + * @param role 玩家数据库数据 + * @param isInc 得分是累加上的还是直接设置的 + */ + public async setRankWithRoleInfo(roleId: string, score: number, timestamp: number, role?: RoleType, isInc = false) { + // 如果没有信息,更新玩家信息 + for (let infoKey of [this.infoKey, ...this.extraKeys]) { + const hasCurUser = await redisClient().hexistsAsync(infoKey, roleId); + if (!hasCurUser) { + await this.generParamAndSet(infoKey, { roleId }, { role }); + } + } + let newScore = await this.setRank({ roleId }, [score, timestamp], isInc); + + return newScore; + } + + /** + * 根据军团表设置更新排行榜&军团信息 + * @param guildCode 军团code + * @param score 得分 + * @param timestamp 时间点 + * @param guild 军团数据库 + * @param isInc 得分是累加上的还是直接设置的 + */ + public async setRankWithGuildInfo(guildCode: string, score: number, timestamp: number, guild?: GuildType, isInc = false) { + return await this.setRankWithGuildInfoArrParam(guildCode, [score, timestamp], guild, isInc); + } + + public async setRankWithGuildInfo2(guildCode: string, num1: number, num2: number, num3: number, guild?: GuildType, isInc = false) { + return await this.setRankWithGuildInfoArrParam(guildCode, [num1, num2, num3], guild, isInc); + } + + public async setRankWithGuildInfoArrParam(guildCode: string, scores: number[], guild?: GuildType, isInc = false) { + for (let infoKey of [this.infoKey, ...this.extraKeys]) { + const hasCurUser = await redisClient().hexistsAsync(infoKey, guildCode); + if (!hasCurUser) { + await this.generParamAndSet(infoKey, { guildCode }, { guild }); + } + } + let newScore = await this.setRank({ guildCode }, scores, isInc); + + return newScore; + } + + public async setRankWithLeagueInfo(leagueCode: string, score: number, timestamp: number, league?: GVGLeagueType, isInc = false) { + return await this.setRankWithLeagueInfoArrParam(leagueCode, [score, timestamp], league, isInc); + } + + public async setRankWithLeagueInfoArrParam(leagueCode: string, scores: number[], league?: GVGLeagueType, isInc = false) { + for (let infoKey of [this.infoKey, ...this.extraKeys]) { + const hasCurUser = await redisClient().hexistsAsync(infoKey, leagueCode); + if (!hasCurUser) { + await this.generParamAndSet(infoKey, { leagueCode }, { league }); + } + } + let newScore = await this.setRank({ leagueCode }, scores, isInc); + + return newScore; + } + + /** + * 根据武将表设置更新排行榜&玩家信息 + * @param roleId 玩家id + * @param hid 武将id + * @param score 得分 + * @param timestamp 时间点 + * @param hero 武将数据库 + * @param isInc 得分是累加上的还是直接设置的 + */ + public async setRankWithHeroInfo(roleId: string, hid: number, score: number, timestamp: number, hero?: HeroUpdate, isInc = false) { + // 如果没有信息,更新玩家信息 + for (let infoKey of [this.infoKey, ...this.extraKeys]) { + await this.generParamAndSet(infoKey, { roleId, hid }, { hero }); + } + let newScore = await this.setRank({ roleId, hid }, [score, timestamp], isInc); + + return newScore; + } + + /** + * 将玩家信息按顺序组成 如:roleId:hid + * @param {{ string }} key redis key + * @param {{ roleId?: string; guildCode?: string; hid?: number; leagueCode?: string }} param 玩家信息 + */ + private composeFields(key: REDIS_KEY, param: myIdInter) { + let type = KEY_TO_COMPOSE_FIELD.get(key); + + if (type == COMPOSE_FIELD_TYPE.ROLE) { + return param.roleId; + } else if (type == COMPOSE_FIELD_TYPE.GUILD) { + return param.guildCode; + } else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) { + return `${param.roleId}:${param.hid}`; + } else if (type == COMPOSE_FIELD_TYPE.LEAGUE) { + return `${param.leagueCode}`; + } else { + return ''; + } + } + + /** + * 将合成了的玩家顺序解开 + * @param key redis key + * @param field + * @returns {{ roleId?: string; guildCode?: string; hid?: number }} + */ + private decodeFields(key: REDIS_KEY, field: string) { + let type = KEY_TO_COMPOSE_FIELD.get(key); + + let arr = field.split(':'); + if (type == COMPOSE_FIELD_TYPE.ROLE) { + return { roleId: arr[0] }; + } else if (type == COMPOSE_FIELD_TYPE.GUILD) { + return { guildCode: arr[0] }; + } else if (type == COMPOSE_FIELD_TYPE.ROLE_HERO) { + return { roleId: arr[0], hid: parseInt(arr[1]) }; + } else if (type == COMPOSE_FIELD_TYPE.LEAGUE) { + return { leagueCode: arr[0] }; + } else { + return {}; + } + } + + /** + * 将玩家数据设置进redis + * @param infoKey 玩家信息的redis key + * @param fields 玩家id + * @param db 数据库内的数据 + */ + public async generParamAndSet(infoKey: string, fields: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroUpdate, league?: GVGLeagueType }) { + let { roleId, guildCode, hid, leagueCode } = fields; + let { role, guild, hero, league } = db; + + if (infoKey == REDIS_KEY.USER_INFO) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + if(!role) return; + } + let param = new RankParam(role); + await this.setUserInfo(infoKey, { roleId }, param); + } else if (infoKey == REDIS_KEY.GUILD_INFO) { + if (!guild) { + guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK) + if(!guild) return; + } + let param = new GuildRankParam(guild); + await this.setUserInfo(infoKey, { guildCode }, param); + } else if (infoKey == REDIS_KEY.LEAGUE_INFO) { + if (!league) { + league = await GVGLeagueModel.findByCode(leagueCode); + if(!league) return; + } + let param = new LeagueRankParam(league); + await this.setUserInfo(infoKey, { leagueCode }, param); + } else if (infoKey == REDIS_KEY.TOP_LINEUP_INFO) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + if(!role) return; + } + let { topLineup = [] } = role; + let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); + let arr = new Array(); + for (let { hid } of topLineup) { + let curHero = heroes.find(cur => cur.hid == hid); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + await this.setUserInfo(infoKey, { roleId }, arr); + } else if (infoKey == REDIS_KEY.HERO_INFO) { + if (!hero) { + hero = await HeroModel.findByHidAndRole(hid, roleId, HERO_SELECT.RANK_LINEUP, true); + if(!hero) return; + } + let arr = new Array(); + if (hero) { + let param = new LineupParam(hero); + arr.push(param); + await this.setUserInfo(infoKey, { roleId, hid }, arr); + } + } else if (infoKey == REDIS_KEY.DUNGEON_LINEUP) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + if(!role) return; + } + let { dungeonWarId, dungeonHeroes } = role; + if (dungeonWarId > 0) { + let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId); + let lineup = cur ? cur.heroes : []; + let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); + let arr = new Array(); + for (let seqId of lineup) { + let curHero = heroes.find(cur => cur.seqId == seqId); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + await this.setUserInfo(infoKey, { roleId }, arr); + } + } else if (infoKey == REDIS_KEY.SHOW_LINEUP) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + if(!role) return; + } + let { showLineup, topLineup = [] } = role; + let heroes = await HeroModel.findByRole(roleId, [], HERO_SELECT.RANK_LINEUP); + let arr = new Array(); + if (!showLineup) showLineup = topLineup.map(cur => cur.hid); + for (let hid of showLineup) { + let curHero = heroes.find(cur => cur.hid == hid); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + await this.setUserInfo(infoKey, { roleId }, arr); + } + } + + /** + * 设置信息 + * @param infoKey + * @param myId + * @param param + */ + private async setUserInfo(infoKey: REDIS_KEY, myId: myIdInter, param: RankParam | GuildRankParam | LineupParam[] | LeagueRankParam) { + let field = this.composeFields(infoKey, myId); + let value = JSON.stringify(param); + return await redisClient().hsetAsync(infoKey, field, value); + } + + /** + * 更新排行榜数据 + * @param myId + * @param score + * @param timestamp + * @param isInc + */ + public async setRank(myId: myIdInter, scores: number[], isInc = false) { + let oldTop = await this.getRankByRank(0, 0); + let oldScore = oldTop.length > 0 && oldTop[0] ? oldTop[0].num : 0; + // 更新分数 + let newScore = 0; + if (this.isUnion) { + newScore = await this.updateRankScoreAtom(myId, scores, isInc); + } else { + newScore = await this.updateRankScoreEncode(myId, scores, isInc) + } + this.checkFirstRankAndPush(myId, oldScore, newScore); + return newScore; + } + + /** + * @description 使用将score和time合成一个字段更新分数 + * @param myId + * @param score + * @param timestamp + */ + private async updateRankScoreEncode(myId: myIdInter, scores: number[] = [], isInc = false) { + let newScore = 0; + let key = this.keyName.getName(); + let newScores: number[] = []; + for(let index = 0; index < this.valueConfig.length; index ++) { + let config = this.valueConfig[index]; + let score = scores[index]; + if(config.isMain) { + if (isInc) { + let oldScore = await this.getMyScore(myId); + newScore = oldScore + score; + } else { + newScore = score; + } + newScores.push(newScore); + } else { + newScores.push(score); + } + } + + let scoreStr = this.encodeScore(newScores); + await redisClient().zaddAsync(key, scoreStr, this.composeFields(this.key, myId)); + return newScore + } + + /** + * @description 使用分两个zset更新redis中某field的值 + * @param myId + * @param score + * @param timestamp + * @param isInc + * @class Rank + */ + private async updateRankScoreAtom(myId: myIdInter, scores: number[], isInc = false) { + + let newScore = 0; + for(let index = 0; index < this.valueConfig.length; index ++) { + let config = this.valueConfig[index]; + let score = scores[index]; + if(config.isMain) { + let key = this.keyName.getName(); + // 分数zset + if (isInc) { + newScore = await redisClient().zincrbyAsync(key, score, this.composeFields(this.key, myId)); + } else { + newScore = await redisClient().zaddAsync(key, score, this.composeFields(this.key, myId)); + } + } else { + let key = this.keyName.getNameWithPlus(config.name); + if(config.isTimestamp) score = this.handleTimestamp(score, config.len); + if(config.reverse) { + let pow = Math.pow(10, config.len); + score = pow - 1 - score; + } + await redisClient().zaddAsync(key, score, this.composeFields(this.key, myId)); + } + } + return parseInt(newScore.toString()); + } + + + /** + * @description 设置到期时间 + * @param time 到期时间,10位时间戳 + * @class Rank + */ + public async setExpire(time: number) { + let key = this.keyName.getName(); + let timeKey = this.keyName.getTimeName(); + + await redisClient().expireatAsync(key, time); + await redisClient().expireatAsync(timeKey, time); + } + + public async generMyRankWithRole(roleId: string, score: number = 0, time: number = 0, role?: RoleType) { + // 如果没有信息,更新玩家信息 + let param: RoleRankInfo; + + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); + if (!hasCurUser) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + } + param = new RoleRankInfo(role); + param.setInfo(0, { roleId }, score, time); + } else { + const info = await redisClient().hgetAsync(this.infoKey, roleId); + const userInfo = JSON.parse(info); + + param = new RoleRankInfo(userInfo); + param.setInfo(0, { roleId }, score, time); + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, { roleId }, { role }); + } + + return await this.generFields(param); + } + + public async generMyRankWithGuild(guildCode: string, score: number, time: number, guild?: GuildType) { + // 如果没有信息,更新玩家信息 + let param: GuildRankInfo; + + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); + if (!hasCurUser) { + if (!guild) { + guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); + if(!guild) return null + } + param = new GuildRankInfo(guild); + param.setInfo(0, { guildCode }, score, time); + } else { + const info = await redisClient().hgetAsync(this.infoKey, guildCode); + if(!info) return null + const guildInfo = JSON.parse(info); + param = new GuildRankInfo(guildInfo); + param.setInfo(0, { guildCode }, score, time); + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, { guildCode }, { guild }); + } + + return await this.generFields(param); + } + + public async generMyRankWithGuild2(guildCode: string, score: number, time: number, active: number, guild?: GuildType) { + // 如果没有信息,更新玩家信息 + let param: GuildRankInfo; + + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, guildCode); + if (!hasCurUser) { + if (!guild) { + guild = await GuildModel.findByCode(guildCode, this.keyName.serverId, GUILD_SELECT.RANK); + if(!guild) return null + } + param = new GuildRankInfo(guild); + param.setInfo2(0, { guildCode }, score, time, active); + } else { + const info = await redisClient().hgetAsync(this.infoKey, guildCode); + const guildInfo = JSON.parse(info); + if(!guildInfo) return null + param = new GuildRankInfo(guildInfo); + param.setInfo2(0, { guildCode }, score, time, active); + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, { guildCode }, { guild }); + } + + return await this.generFields(param); + } + + public async generMyRankWithLeague(leagueCode: string, score: number, time: number, league?: GVGLeagueType) { + // 如果没有信息,更新玩家信息 + let param: LeagueRankInfo; + + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, leagueCode); + if (!hasCurUser) { + if (!league) { + league = await GVGLeagueModel.findByCode(leagueCode); + if(!league) return null + } + param = new LeagueRankInfo(league); + param.setInfo(0, { leagueCode }, score, time); + } else { + const info = await redisClient().hgetAsync(this.infoKey, leagueCode); + if(!info) return null + const leagueInfo = JSON.parse(info); + param = new LeagueRankInfo(leagueInfo); + param.setInfo(0, { leagueCode }, score, time); + } + + return await this.generFields(param); + } + + public async generMyRankWithHero(roleId: string, hid: number, score: number, time: number, hero?: HeroType, role?: RoleType) { + // 如果没有信息,更新玩家信息 + let param: RoleRankInfo; + + let hasCurUser = await redisClient().hexistsAsync(this.infoKey, roleId); + if (!hasCurUser) { + if (!role) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + } + param = new RoleRankInfo(role); + param.setInfo(0, { roleId, hid }, score, time); + } else { + const info = await redisClient().hgetAsync(this.infoKey, roleId); + const userInfo = JSON.parse(info); + + param = new RoleRankInfo(userInfo); + param.setInfo(0, { roleId, hid }, score, time); + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, { roleId, hid }, { hero, role }); + } + + return await this.generFields(param); + } + + private async setExInfoToParam(extraKey: string, param: RoleRankInfo | GuildRankInfo | LeagueRankInfo, myId: myIdInter, db: { role?: RoleType, guild?: GuildType, hero?: HeroType }) { + let { role, guild, hero } = db; + + if (extraKey == REDIS_KEY.TOP_LINEUP_INFO) { + param = param; + + let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); + if (!hasCurUser) { + if (!role) { + role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); + } + + let { topLineup } = role; + let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL); + let arr = new Array(); + for (let { hid } of topLineup) { + let curHero = heroes.find(cur => cur.hid == hid); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + param.setTopLine(arr); + } else { + const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); + const infoObj = JSON.parse(info); + param.setTopLine(infoObj); + } + } else if (extraKey == REDIS_KEY.HERO_INFO) { + param = param; + + let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); + if (!hasCurUser) { + if (!hero) { + hero = await HeroModel.findByHidAndRole(myId.hid, myId.roleId, HERO_SELECT.RANK_LINEUP); + } + let arr = new Array(); + let lineParam = new LineupParam(hero); + arr.push(lineParam); + if (this.key == REDIS_KEY.HERO_RANK) { + param.setSingleHero(arr); + } else { + param.setTopLine(arr); + } + } else { + const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); + const infoObj = JSON.parse(info); + if (this.key == REDIS_KEY.HERO_RANK) { + param.setSingleHero(infoObj); + } else { + param.setTopLine(infoObj); + } + } + } else if (extraKey == REDIS_KEY.DUNGEON_LINEUP) { + param = param; + + let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); + if (!hasCurUser) { + if (!role) { + role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); + } + let { dungeonWarId, dungeonHeroes } = role; + let cur = dungeonHeroes.find(cur => cur.battleId == dungeonWarId); + let lineup = cur ? cur.heroes : []; + let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.RANK_LINEUP); + let arr = new Array(); + for (let seqId of lineup) { + let curHero = heroes.find(cur => cur.seqId == seqId); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + param.setTopLine(arr); + } else { + const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); + const infoObj = JSON.parse(info); + param.setTopLine(infoObj); + } + } else if (extraKey == REDIS_KEY.SHOW_LINEUP) { + param = param; + + let hasCurUser = await redisClient().hexistsAsync(extraKey, this.composeFields(extraKey, myId)); + if (!hasCurUser) { + if (!role) { + role = await RoleModel.findByRoleId(myId.roleId, ROLE_SELECT.RANK, true); + } + + let { showLineup, topLineup = [] } = role; + let heroes = await HeroModel.findByRole(myId.roleId, [], HERO_SELECT.HERO_DETAIL); + let arr = new Array(); + if (!showLineup) showLineup = topLineup.map(cur => cur.hid); + for (let hid of showLineup) { + let curHero = heroes.find(cur => cur.hid == hid); + if (curHero) { + let param = new LineupParam(curHero); + arr.push(param); + } + } + param.setTopLine(arr); + } else { + const info = await redisClient().hgetAsync(extraKey, this.composeFields(extraKey, myId)); + const infoObj = JSON.parse(info); + param.setTopLine(infoObj); + } + } + } + + public async getRankListWithMyRank(myId: myIdInter, isReverse = true) { + let ranks = await this.getRankByRange(1000, 0, isReverse); + let newRanks = [], newMyRank: any; + let myRank = ranks.find(cur => { + return cur.isMyInfo(myId); + }); + if (this.generFields) { + for (let rank of ranks) { + let n = await this.generFields(rank); + if(n) newRanks.push(n); + } + if (myRank) { + newMyRank = await this.generFields(myRank); + } + } + + return { myRank: newMyRank, ranks: newRanks } + } + + /** + * 获取排行榜原始数据 + * @param from + * @param to + */ + public async getRankDataByRankWithoutDetail(from: number | '+inf' = '+inf', to: number | '-inf' = '-inf') { + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = (from == '+inf' && to == '-inf')? + (await redisClient().zrevrangebyscoreAsync(key, from, to, "WITHSCORES")): + (await redisClient().zrevrangeAsync(key, from, to, "WITHSCORES")) + ; + let ranks: { rank: number, myId: {roleId?: string, guildCode?: string, hid?: number}, scores: number[] }[] = []; + + let num = 0; + for (let ii = 0; ii < rankFromDb.length; ii += 2) { + if (num >= this.limit) break; + + const field = rankFromDb[ii]; + let myId = this.decodeFields(this.key, field); + const scores = this.decodeScore(rankFromDb[ii + 1]); + + ranks.push({ rank: num, myId, scores }); + num++; + } + return ranks + } + + // 获取区间里的排行榜,格式 {rank, field, score}[] + public async getRankByRangeRaw(max: number | string = '+inf', min: number | string = '-inf', isReverse = true, byScore = false) { + let ranks: { rank: number, field: string, scores: number[] }[] = []; + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = isReverse? + (((max == '+inf' && min == '-inf') || byScore)? + (await redisClient().zrevrangebyscoreAsync(key, max, min, "WITHSCORES")): + (await redisClient().zrevrangeAsync(key, min, max, "WITHSCORES")) + ): + (((max == '+inf' && min == '-inf') || byScore)? + (await redisClient().zrangebyscoreAsync(key, min, max, "WITHSCORES")): + (await redisClient().zrangeAsync(key, min, max, "WITHSCORES")) + ) + + let num = 0; + for (let ii = 0; ii < rankFromDb.length; ii += 2) { + if (num >= this.limit) break; + ranks.push({ rank: Math.floor(ii / 2) + 1, field: rankFromDb[ii], scores: this.decodeScore(rankFromDb[ii + 1]) }); + num++; + } + return ranks + } + + public async getRankByRange(max: number | string = '+inf', min: number | string = '-inf', isReverse = true, byScore = false) { + let raws = await this.getRankByRangeRaw(max, min, isReverse, byScore); + + let ranks = new Array(); + let l = 1; + for (let { field, scores } of raws) { + let param = await this.getParam(l, field, scores); + if(param) { + ranks.push(param); l++; + } + } + return ranks + } + + public async getParam(rank: number, field: string, scores: number[]) { + let myId = this.decodeFields(this.key, field); + + const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId)); + const userInfo = JSON.parse(info); + if(!userInfo) return null; + + let param: RoleRankInfo | GuildRankInfo | LeagueRankInfo; + if (this.infoKey == REDIS_KEY.USER_INFO) { + // if (this.key != REDIS_KEY.LADDER && this.key != REDIS_KEY.GVG_VESTIGE_MEMBER && nowSeconds() - userInfo.updatedAt > 2 * 30 * 24 * 60 * 60) { + // return null; + // } + param = new RoleRankInfo(userInfo); + param.setInfo(rank, myId, scores[0], scores[1]); + } else if (this.infoKey == REDIS_KEY.GUILD_INFO) { + if(this.key == REDIS_KEY.GUILD_LV_RANK|| this.key == REDIS_KEY.RACE_ACTIVITY) { + param = new GuildRankInfo(userInfo); + param.setInfo2(rank, myId, scores[0], scores[1], scores[2]); + } else { + param = new GuildRankInfo(userInfo); + param.setInfo(rank, myId, scores[0], scores[1]); + } + } else if (this.infoKey == REDIS_KEY.LEAGUE_INFO) { + param = new LeagueRankInfo(userInfo); + param.setInfo(rank, myId, scores[0], scores[1]); + + } + + for (let extraKey of this.extraKeys) { + await this.setExInfoToParam(extraKey, param, myId, {}); + } + return param + } + + public async getRankByRank(start: number, end: number) { + + let ranks = new Array(); + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + + const rankFromDb = await redisClient().zrevrangeAsync(key, start, end, "WITHSCORES"); + + // console.log(key, start, end, rankFromDb) + + let num = 0; + for (let ii = 0; ii < rankFromDb.length; ii += 2) { + if (num >= this.limit) break; + let param = await this.getParam(Math.floor(ii / 2) + 1, rankFromDb[ii], this.decodeScore(rankFromDb[ii + 1])); + if(param) ranks.push(param); + num++; + } + return ranks + } + + + // 获取我的排名 + public async getMyRank(myId: myIdInter) { + let key = this.keyName.getName(); + if (this.isUnion) { + key = await this.generateUnionRank(); + } + // console.log('**getMyRank',key, this.composeFields(this.key, myId), this.key, myId) + let myRank = await redisClient().zrevrankAsync(key, this.composeFields(this.key, myId)); + if (!myRank && myRank != 0) { + return 0; + } else { + return myRank + 1; + } + } + + // 获取排名第几名的信息 + public async getUserByRank(rank: number) { + let key = this.keyName.getName(); + let myRank = await redisClient().zrevrangeAsync(key, rank - 1, rank - 1); + return myRank; + } + + + // 获取排名第几名的信息 + public async getMyScore(myId: myIdInter) { + let key = this.keyName.getName(); + let score = await redisClient().zscoreAsync(key, this.composeFields(this.key, myId)); + if (!score) score = 0; + if (!this.isUnion) { + let result = this.decodeScore(score.toString()); + score = result[0]; + } + return parseInt(score.toString()); + } + + // 从排行榜中移除 + public async removeFromRank(myId: myIdInter) { + let key = this.keyName.getName(); + await redisClient().zremAsync(key, this.composeFields(this.key, myId)); + + return true; + } + + private async generateUnionRank() { + let unionKey = this.keyName.getUnionName(); // 联合的key + + let keys = [], weights = []; + this.valueConfig.forEach(({ isMain, name, weight }) => { + if(isMain) { + keys.push(this.keyName.getName()); + } else { + keys.push(this.keyName.getNameWithPlus(name)); + } + weights.push(Math.pow(10, weight)) + + }) + + await redisClient().zunionstoreAsync(unionKey, 2, ...keys, 'WEIGHTS', ...weights); + await redisClient().expireAsync(unionKey, this.unionRankLife); // 10秒更新一次 + return unionKey; + } + + // 有序排行综合时间和得分排序 + private encodeScore(scores: number[]) { + let encodeResult = 0; + // console.log('#### decoencodeResultdeScore', this.key, scores, this.valueConfig); + this.valueConfig.forEach(({ name, reverse, isTimestamp, len, weight }, index) => { + let score = scores[index]; + // console.log('*** 1', name, len, weight, score, encodeResult) + if(isTimestamp) score = this.handleTimestamp(score, len); + // console.log('*** 2', name, len, weight, score, encodeResult) + if(!reverse) { + encodeResult += score * Math.pow(10, weight); + } else { + let pow = Math.pow(10, len); + encodeResult += (pow - 1 - score) * Math.pow(10, weight); + } + // console.log('*** 3', name, len, weight, score, encodeResult) + }) + return encodeResult + } + + private decodeScore(num: string) { + let _num = parseInt(num); + let scores: number[] = []; + this.valueConfig.forEach(({ name, reverse, isTimestamp, len, weight }) => { + let pow = Math.pow(10, weight); + let score = Math.floor(_num / pow); + // console.log('*** 1', name, len, weight, score) + _num -= pow * score; + if(isTimestamp) score = this.handleTimestamp(score, len); + // console.log('*** 2', name, len, weight, score) + if(reverse) { + let pow = Math.pow(10, len); + score = pow - 1 - score; + } + // console.log('*** 3', name, len, weight, score) + scores.push(score); + }) + // console.log('#### decodeScore', this.key, scores, this.valueConfig); + return scores; + } + + private handleTimestamp(timestamp: number = 0, len: number) { + let l = timestamp.toString().length; + if (l > len) { + timestamp = Math.floor(timestamp / Math.pow(10, l - len)); + } + return timestamp + } + + private async getFirstUserInfo(myId: myIdInter) { + const info = await redisClient().hgetAsync(this.infoKey, this.composeFields(this.infoKey, myId)); + if(!info) return null + const playerInfo = JSON.parse(info); + + if (this.infoKey == REDIS_KEY.USER_INFO) { + let userInfo = new RankParam(playerInfo); + return { userInfo } + } else if (this.infoKey == REDIS_KEY.GUILD_INFO) { + let guildInfo = new GuildRankInfo(playerInfo); + return { guildInfo } + } + return false + } + + // 首通 + private async checkFirstRankAndPush(myId: myIdInter, oldScore: number, newScore: number) { + let ts = this; + if (ts.isInit) return; + + let serverId = this.keyName.serverId; + let dicRank = gameData.rank.find(({ id }) => { + let redisKey = getRedisKeyByRankType(id); + return redisKey == ts.key + }); + if(!dicRank) return; + + let infos = await this.getFirstUserInfo(myId); + if(!infos) return; + + let { userInfo, guildInfo } = infos + let rankFirstRecs: (RankFirstType & { status: number })[] = []; + for(let [id, { rankId, condition }] of gameData.generalRankReward) { + // console.log(rankId, dicRank.id, oldScore, condition, newScore); + let hasRankFirst = await getRankFirstRewardById(serverId, id); + if(!hasRankFirst && dicRank.id == rankId && oldScore < condition && newScore >= condition) { + let rankFirstRec = await RankFirstModel.createRankFirst(serverId, id, rankId, { userInfo, guildInfo }); + if(rankFirstRec && getSeconds(rankFirstRec.createdAt) == getSeconds(rankFirstRec.updatedAt)) { + await setRankFirst(rankFirstRec); + rankFirstRecs.push({ ... rankFirstRec, status: 1}); + } + } + } + + if(rankFirstRecs.length > 0) { + await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.RANK_TOP_UPDATE, { ranks: rankFirstRecs }, true); + } + } +} + +/** + * 从其他服获取首通信息 + * @param serverId + * @param id dic_zyz_rankingType的id + * @returns + */ +async function getRankFirstRewardById(serverId: number, id: number) { + let rankFirst: RankFirstType; + if(pinus.app.getServerType() == 'role') { + rankFirst = pinus.app.get('rankFirstRewards').get(serverId)?.get(id); + } else { + let roleServers = pinus.app.getServersByType('role'); + let server = getRandSingleEelm(roleServers); + rankFirst = await pinus.app.rpc.role.roleRemote.getRankFirstById.toServer(server.id, serverId, id); + } + return rankFirst; +} + +async function setRankFirst(rankFirstRec: RankFirstType) { + let roleServers = pinus.app.getServersByType('role'); + for(let server of roleServers) { + pinus.app.rpc.role.roleRemote.setRankFirst.toServer(server.id, rankFirstRec); + } +} + +/** + * 从数据库内获取排行榜存入redis + * @param type 排行榜类型 + * @param serverId 分服 + */ +export async function setRankRedisFromDb(type: string, args?: { serverId?: number, groupId?: number }) { + if (type == REDIS_KEY.TOWER_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('tower', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + // console.log(roleId); + if(role.towerLv > 1) { + await r.setRankWithRoleInfo(role.roleId, role.towerLv - 1, role.towerUpTime ? role.towerUpTime.getTime() : 0, role); + } + } + } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { + let serverId = args.serverId; + let ranks = await GuildModel.getRank(type, serverId); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let guild of ranks) { + await r.setRankWithGuildInfo(guild.code, guild.activeWeekly, guild.activeUpdateTime, guild); + } + } else if (type == REDIS_KEY.GUILD_LV_RANK) { + + let serverId = args.serverId; + let ranks = await GuildModel.getRank(type, serverId); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let guild of ranks) { + await r.setRankWithGuildInfoArrParam(guild.code, [guild.lv, guild.activeWeekly, guild.activeUpdateTime], guild); + } + } else if (type == REDIS_KEY.PVP_RANK) { + let pvpConfig = await PVPConfigModel.findCurPVPConfig(); + let seasonNum = pvpConfig?.seasonNum; + if(seasonNum > 0) { + let serverGroup = await getPVPServerGroup(); + for(let [groupId, serverIds] of serverGroup) { + let keyName = new KeyName(type, { seasonNum, groupId }) + await delKeys(keyName.getName()); + let ranks = await PvpDefenseModel.getRank(serverIds, seasonNum);//获得全服前1000名的排名,加入到redis中 + + let r = new Rank(type, { seasonNum, groupId }); + r.setIsInit(true); + for (let { roleId, role: _role, score, updatedAt } of ranks) { + let role = _role; + if (!role) { + continue; + } + await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role); + } + } + } + } else if (type == REDIS_KEY.TOP_LINEUP_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('topLineup', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + // console.log(roleId); + await r.setRankWithRoleInfo(role.roleId, role.topLineupCe, role.updatedAt.getTime(), role); + } + } else if (type == REDIS_KEY.TOP_HERO_RANK) { + let serverId = args.serverId; + let ranks = await HeroModel.getAllRank(serverId, HERO_SELECT.RANK_LINEUP); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let hero of ranks) { + await r.setRankWithHeroInfo(hero.roleId, hero.hid, hero.ce, hero.updatedAt.getTime(), hero); + } + } else if (type == REDIS_KEY.HERO_NUM_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('heroNum', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.heroNum, role.heroNumUpdatedAt, role); + } + } else if (type == REDIS_KEY.USER_LV) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('lv', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.lv, role.updatedAt.getTime(), role); + } + } else if (type == REDIS_KEY.SUM_CE_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('ce', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.ce, role.updatedAt.getTime(), role); + } + } else if (type == REDIS_KEY.DUNGEON_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('dungeon', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); + } + } else if (type == REDIS_KEY.MAIN_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('main', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.mainWarId, role.mainUpdatedAt, role); + } + } else if (type == REDIS_KEY.MAIN_ELITE_RANK) { + let serverId = args.serverId; + let ranks = await RoleModel.getRank('mainElite', serverId, ROLE_SELECT.RANK); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let role of ranks) { + await r.setRankWithRoleInfo(role.roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); + } + // } else if (type == REDIS_KEY.HERO_RANK) { + // let serverId = args.serverId; + + // for (let [hid] of gameData.recruit) { + // let ranks = await Hero.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP); + // let r = new Rank(type, { serverId, hid }); + // r.setIsInit(true); + // for (let hero of ranks) { + // await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero); + // } + // } + } else if (type == REDIS_KEY.HERO_RANK) { + let serverId = args.serverId; + + for (let [hid] of gameData.recruit) { + let ranks = await HeroModel.getRank(hid, serverId, HERO_SELECT.RANK_LINEUP); + let r = new Rank(type, { serverId, hid }); + r.setIsInit(true); + for (let hero of ranks) { + await r.setRankWithHeroInfo(hero.roleId, hid, hero.ce, hero.updatedAt.getTime(), hero); + } + } + } else if (type == REDIS_KEY.LADDER) { + let serverId = args.serverId; + let ranks = await LadderMatchModel.findAll(serverId); + let r = new Rank(type, { serverId }); + r.setIsInit(true); + for (let rank of ranks) { + let role = rank.role; + await r.setRankWithRoleInfo(rank.roleId, rank.rank, 0, role); + await saveLadderDefCeByData(rank.roleId, rank); + } + } else if (type == REDIS_KEY.GVG_VESTIGE_MEMBER_ALL) { + let ranks = await GVGVestigeSumRankModel.findRankByGroupId(); + for(let { _id: groupKey, arr, roleIds } of ranks) { + let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.RANK); + let r = new Rank(type, { groupKey, day: getDayKeyInfo() }); + r.setIsInit(true); + for(let { roleId, score, updatedAt } of arr) { + let role = roles.find(cur => cur.roleId == roleId); + if(role) { + await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role); + } + } + } + } else if (type == REDIS_KEY.GVG_VESTIGE_LEAGUE) { + let ranks = await GVGVestigeLeagueRankModel.findRank(); + for(let { _id: groupKey, arr, leagueCodes } of ranks) { + let leagues = await GVGLeagueModel.findByCodes(leagueCodes); + let r = new Rank(type, { groupKey, day: getDayKeyInfo() }); + r.setIsInit(true); + for(let { leagueCode, score, updatedAt } of arr) { + let league = leagues.find(cur => cur.leagueCode == leagueCode); + if(league) { + await r.setRankWithLeagueInfo(leagueCode, score, updatedAt.getTime(), league); + } + } + } + } else if (type == REDIS_KEY.ACTIVITY_MINI_GAME) { + let ranks = await ActivityMiniGameModel.findRank(); + for(let { _id: { activityId, roundIndex }, roleIds, arr } of ranks) { + let r = new Rank(type, { activityId, roundIndex }); + let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.RANK); + for(let { roleId, score, updatedAt } of arr) { + let role = roles.find(cur => cur.roleId == roleId); + if(role) await r.setRankWithRoleInfo(roleId, score, updatedAt.getTime(), role, false); + } + } + } +} + +/** + * 获取排行榜总览 + * @param role 玩家数据 + * @param serverId 所在服务器 + */ +export async function getGeneralRank(role: RoleType & { rankReceived: number[] }, serverId: number) { + let { rankReceived = [] } = role; + + let result: (GeneralRankParam & {general: number})[] = []; + + for (let { id, general } of gameData.rank) { + let redisKey = getRedisKeyByRankType(id); + if (redisKey) { + let received = rankReceived.filter(rewardId => { + let dic = gameData.generalRankReward.get(rewardId); + return dic && dic.rankId == id; + }); + let r = new Rank(redisKey, { serverId }, false, 1); + let ranks = await r.getRankByRange(1, 0, id != RANK_TYPE.LADDER); + // if (ranks.length > 0) { + let param = new GeneralRankParam(id, ranks[0], general, received); + result.push({...param, general}); + } + } + return result; +} + +/** + * 获取排行榜总览 + * @param role 玩家数据 + * @param serverId 所在服务器 + */ + export async function getRankFirstReward(role: RoleType & { rankReceived: number[] }, serverId: number) { + let { rankReceived = [] } = role; + + let result: (RankFirstUpdateParam & {status: number})[] = []; + + for (let [id, { rankId: type } ] of gameData.generalRankReward) { + let rankFirst = await getRankFirstRewardById(serverId, id); + + if(rankFirst) { + let status = rankReceived.includes(id)?RANK_FIRST_REWARD_STATUS.RECEIVED: RANK_FIRST_REWARD_STATUS.CAN_RECEIVE; + result.push({...rankFirst, status}); + } else { + result.push({ id, type, status: RANK_FIRST_REWARD_STATUS.WAITING }); + } + } + return result; +} + +export async function getRankInHandler(redisKey: REDIS_KEY, type: RANK_TYPE, keyParam: KeyNameParam, session: BackendSession) { + + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + const guildCode = session.get('guildCode'); + + let r = new Rank(redisKey, keyParam); + r.setGenerFieldsFun((obj => { + let result = new RoleAndGuildRankInfo(obj.rank, obj.num); + if(type == RANK_TYPE.LADDER) { + result = new RoleAndGuildRankInfo(obj.num, 0); + } + if(obj instanceof GuildRankInfo) { + result.setGuildInfo(obj); + } + if(obj instanceof RoleRankInfo) { + result.setUserInfo(obj); + } + return result + })); + + let { ranks, myRank } = await r.getRankListWithMyRank({ roleId, guildCode }, type != RANK_TYPE.LADDER); + if (!myRank) { + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK, true); + if (type == RANK_TYPE.TOP_LINTUP) { + myRank = await r.generMyRankWithRole(roleId, role.topLineupCe, 0, role); + } else if (type == RANK_TYPE.TOP_HERO) { + let hero = await HeroModel.getMyTopHero(roleId, HERO_SELECT.RANK_LINEUP); + myRank = await r.generMyRankWithHero(roleId, hero.hid, hero.ce, 0, hero, role); + } else if (type == RANK_TYPE.HERO_NUM) { + myRank = await r.generMyRankWithRole(roleId, role.heroNum, role.heroNumUpdatedAt, role); + } else if (type == RANK_TYPE.USER_LV) { + myRank = await r.generMyRankWithRole(roleId, role.lv, role.updatedAt.getTime(), role); + } else if (type == RANK_TYPE.SUM_CE) { + myRank = await r.generMyRankWithRole(roleId, role.ce, role.updatedAt.getTime(), role); + } else if (type == RANK_TYPE.TOWER) { + myRank = await r.generMyRankWithRole(roleId, role.towerLv - 1, role.towerUpTime?.getTime() || 0, role); + // } else if (type == RANK_TYPE.DUNGEON) { + // myRank = await r.generMyRankWithRole(roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); + } else if (type == RANK_TYPE.MAIN) { + myRank = await r.generMyRankWithRole(roleId, role.mainWarId, role.mainUpdatedAt, role); + } else if (type == RANK_TYPE.MAIN_ELITE) { + myRank = await r.generMyRankWithRole(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); + } else if (type == RANK_TYPE.GUILD_LV) { + if(role.hasGuild) { + let guild = await GuildModel.findByCode(guildCode, serverId); + if(guild) myRank = await r.generMyRankWithGuild2(roleId, guild.lv, guild.activeWeekly, guild.lvUpdateTime, guild); + } + } else if (type == RANK_TYPE.GUILD_FUND) { + if(role.hasGuild) { + let limitRank = await ActivityTimeLimitRankModel.findByCode(serverId, keyParam.activityId, guildCode); + myRank = await r.generMyRankWithGuild(guildCode, limitRank?.score||0, limitRank?.time); + } + } else if (type == RANK_TYPE.LADDER) { + myRank = await r.generMyRankWithRole(roleId, 0, 0, role); + } + } + // if(type == RANK_TYPE.LADDER) { + ranks = completeRanks(ranks); + // } + return { ranks, myRank } +} diff --git a/game-server/app/services/redLockService.ts b/game-server/app/services/redLockService.ts index 062b171d5..64fbfe7bf 100644 --- a/game-server/app/services/redLockService.ts +++ b/game-server/app/services/redLockService.ts @@ -1,120 +1,120 @@ -import { setLock, releaseLock, getLock } from './redlockCacheService'; -var Redlock = require('redlock'); -var _redlockCache; - -export function initRedlock (redisClient) { - _redlockCache = new RedlockService(redisClient); -} - -export class RedlockService { - _redisClient: any; - ttl: number; - redlock: any; - redlockNoRetry: any; // 用于检查锁是否存在,一锁上立刻会解锁 - - constructor(redisClient) { - this._redisClient = redisClient; - this._redisClient.on("error", function (err) { - console.error("Redis:Error:" + err); - }); - this.ttl = 1000; - this.redlock = new Redlock( - [this._redisClient], - { - // the expected clock drift; for more details - // see http://redis.io/topics/distlock - driftFactor: 0.01, // time in ms - - // the max number of times Redlock will attempt - // to lock a resource before erroring - retryCount: 10, - - // the time in ms between attempts - retryDelay: 200, // time in ms - - // the max time in ms randomly added to retries - // to improve performance under high contention - // see https://www.awsarchitectureblog.com/2015/03/backoff.html - retryJitter: 200 // time in ms - } - ); - - this.redlock.on('clientError', function(err) { - console.error('A redis error has occurred:', err); - }); - - this.redlockNoRetry = new Redlock( - [this._redisClient], - { - driftFactor: 0.01, // time in ms - retryCount: 0, - retryDelay: 200, // time in ms - retryJitter: 200 // time in ms - } - ); - - this.redlockNoRetry.on('clientError', function(err) { - console.error('A redis error has occurred:', err); - }); - } - -} - -export async function lockData(serverId: number, dataName: string, id: string ) { - let key = 'serverId_'+serverId+'_'+dataName+'_'+id; - let lockKey = 'locks:' + key; - console.log(' lockKey = '+ lockKey); - return await lock(lockKey); -} - -export async function lockLeagueData(dataName: string, leagueCode: string) { - let key = dataName+'_'+ leagueCode; - let lockKey = 'locks:' + key; - console.log(' lockKey = '+ lockKey); - return await lock(lockKey); -} - -export async function lockDataWithNoParam(dataName: string) { - let key = `${dataName}`; - return await lock(key); -} - -async function lock(lockKey: string) { - return new Promise((resolve) => { - _redlockCache.redlock.lock(lockKey, _redlockCache.ttl, function(err, lock) { - if(err) { - return resolve({ err, releaseCallback: releaseCallback.bind(null, lockKey) }) - } - setLock(lockKey, lock); - return resolve({err: null, releaseCallback: releaseCallback.bind(null, lockKey)}); - }); - }) -} - -function releaseCallback(lockKey: string) { - releaseLock(lockKey); -} - -/** - * 主要用于检查是否锁定,锁上后立刻会解锁,所以entryCount为0 - * - * @param serverId 区服 - * @param dataName 锁名 - * @param id 锁id - */ -export async function lockDataNoRetry(serverId: number, dataName: string, id: string ) { - let key = 'serverId_'+serverId+'_'+dataName+'_'+id; - let lockKey = 'locks:' + key; - console.log(' lockKey = '+ lockKey); - return await lockNoRetry(lockKey); -} - -function lockNoRetry(lockKey: string) { - return _redlockCache.redlockNoRetry.lock(lockKey, _redlockCache.ttl).then(function(lock) { - setLock(lockKey, lock); - return {err: null, releaseCallback: releaseCallback.bind(null, lockKey)}; - }).catch(function(err) { - console.error(err); - return { err, releaseCallback: releaseCallback.bind(null, lockKey) }; - }); -} \ No newline at end of file +import { setLock, releaseLock, getLock } from './redlockCacheService'; +var Redlock = require('redlock'); +var _redlockCache; + +export function initRedlock (redisClient) { + _redlockCache = new RedlockService(redisClient); +} + +export class RedlockService { + _redisClient: any; + ttl: number; + redlock: any; + redlockNoRetry: any; // 用于检查锁是否存在,一锁上立刻会解锁 + + constructor(redisClient) { + this._redisClient = redisClient; + this._redisClient.on("error", function (err) { + console.error("Redis:Error:" + err); + }); + this.ttl = 1000; + this.redlock = new Redlock( + [this._redisClient], + { + // the expected clock drift; for more details + // see http://redis.io/topics/distlock + driftFactor: 0.01, // time in ms + + // the max number of times Redlock will attempt + // to lock a resource before erroring + retryCount: 10, + + // the time in ms between attempts + retryDelay: 200, // time in ms + + // the max time in ms randomly added to retries + // to improve performance under high contention + // see https://www.awsarchitectureblog.com/2015/03/backoff.html + retryJitter: 200 // time in ms + } + ); + + this.redlock.on('clientError', function(err) { + console.error('A redis error has occurred:', err); + }); + + this.redlockNoRetry = new Redlock( + [this._redisClient], + { + driftFactor: 0.01, // time in ms + retryCount: 0, + retryDelay: 200, // time in ms + retryJitter: 200 // time in ms + } + ); + + this.redlockNoRetry.on('clientError', function(err) { + console.error('A redis error has occurred:', err); + }); + } + +} + +export async function lockData(serverId: number, dataName: string, id: string ) { + let key = 'serverId_'+serverId+'_'+dataName+'_'+id; + let lockKey = 'locks:' + key; + console.log(' lockKey = '+ lockKey); + return await lock(lockKey); +} + +export async function lockLeagueData(dataName: string, leagueCode: string) { + let key = dataName+'_'+ leagueCode; + let lockKey = 'locks:' + key; + console.log(' lockKey = '+ lockKey); + return await lock(lockKey); +} + +export async function lockDataWithNoParam(dataName: string) { + let key = `${dataName}`; + return await lock(key); +} + +async function lock(lockKey: string) { + return new Promise((resolve) => { + _redlockCache.redlock.lock(lockKey, _redlockCache.ttl, function(err, lock) { + if(err) { + return resolve({ err, releaseCallback: releaseCallback.bind(null, lockKey) }) + } + setLock(lockKey, lock); + return resolve({err: null, releaseCallback: releaseCallback.bind(null, lockKey)}); + }); + }) +} + +function releaseCallback(lockKey: string) { + releaseLock(lockKey); +} + +/** + * 主要用于检查是否锁定,锁上后立刻会解锁,所以entryCount为0 + * + * @param serverId 区服 + * @param dataName 锁名 + * @param id 锁id + */ +export async function lockDataNoRetry(serverId: number, dataName: string, id: string ) { + let key = 'serverId_'+serverId+'_'+dataName+'_'+id; + let lockKey = 'locks:' + key; + console.log(' lockKey = '+ lockKey); + return await lockNoRetry(lockKey); +} + +function lockNoRetry(lockKey: string) { + return _redlockCache.redlockNoRetry.lock(lockKey, _redlockCache.ttl).then(function(lock) { + setLock(lockKey, lock); + return {err: null, releaseCallback: releaseCallback.bind(null, lockKey)}; + }).catch(function(err) { + console.error(err); + return { err, releaseCallback: releaseCallback.bind(null, lockKey) }; + }); +} diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 369807fee..db23580c1 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -1,796 +1,795 @@ -import { ACTIVITY_TYPE, getRedisKeyByRankType, GUILD_ACTIVITY_TYPE, MAX_ONLINE_USER_COUNT } from './../consts'; -import * as Redis from 'redis'; -import {REDIS_KEY} from '../consts' -import { pinus, ServerInfo } from 'pinus'; -import { GuildRankParam, GuildLeader, RankParam, LineupParam, LeagueLeader } from '../domain/rank'; -import { comBtlRanges } from '../pubUtils/data'; -import { Rank, setRankRedisFromDb } from './rankService'; -import { ServerlistModel } from '../db/Serverlist'; -import moment = require('moment'); -import { getRedisSubChannel } from '../pubUtils/sdkUtil'; -import { getRandSingleEelm, parseNumberList } from '../pubUtils/util'; -import { ActivityModel } from '../db/Activity'; -import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField'; -import { ActivityTimeLimitRankModel } from '../db/ActivityTimeLimitRank'; -import { RoleModel, RoleType } from '../db/Role'; -import { GuildType } from '../db/Guild'; -import { ActivityGroupModel } from '../db/ActivityGroup'; -import { LadderMatchModel, LadderMatchType } from '../db/LadderMatch'; -import { isDevelopEnv } from './utilService'; - -/** - * 在服务重新启动时,将信息存入redis - */ -export async function initAllRank() { - console.log('******* initAllRank ******') - const serverList = await ServerlistModel.findByEnv(pinus.app.get('env')); - await delKeys(REDIS_KEY.ONLINE_USERS); - await delKeys(REDIS_KEY.ONLINE_CNT); - await delKeys(REDIS_KEY.USER_INFO); - await delKeys(REDIS_KEY.GUILD_INFO); - await delKeys(REDIS_KEY.TOP_LINEUP_INFO); - await delKeys(REDIS_KEY.HERO_INFO); - await delKeys(REDIS_KEY.TOWER_RANK); - await delKeys(REDIS_KEY.GUILD_LV_RANK); - await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK); - await delKeys(REDIS_KEY.TOP_LINEUP_RANK); - await delKeys(REDIS_KEY.TOP_HERO_RANK); - await delKeys(REDIS_KEY.HERO_NUM_RANK); - await delKeys(REDIS_KEY.USER_LV); - await delKeys(REDIS_KEY.SUM_CE_RANK); - // await delKeys(REDIS_KEY.DUNGEON_RANK); - await delKeys(REDIS_KEY.DUNGEON_LINEUP); - await delKeys(REDIS_KEY.MAIN_RANK); - await delKeys(REDIS_KEY.MAIN_ELITE_RANK); - await delKeys(REDIS_KEY.HERO_RANK); - await delKeys(REDIS_KEY.SHOW_LINEUP); - // await delKeys(REDIS_KEY.PVP_RANK); - await delKeys(REDIS_KEY.GUILD_FUND); - await delKeys(REDIS_KEY.SUM_CE_SNAPSHOT); - await delKeys(REDIS_KEY.TOP_LINE_SNAPSHOT); - await delKeys(REDIS_KEY.LADDER); - await delKeys(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL); - await delKeys(REDIS_KEY.GVG_VESTIGE_LEAGUE); - await delKeys(REDIS_KEY.ACTIVITY_MINI_GAME); - // 测试服特殊处理,由于重启较频繁且联军数据较少,数据先不删,正式服激战期间不会重启 - if(!isDevelopEnv()) await delKeys(REDIS_KEY.LEAGUE_INFO); - - await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {}); - await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, {}); - await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_LEAGUE, {}); - await setRankRedisFromDb(REDIS_KEY.ACTIVITY_MINI_GAME, {}); - - for(let {id} of serverList) { - await initRankByServerId(id); - await initActivitiesRank(id) - } -} - -/** - * 分服内初始redis排行榜 - * - * @param serverId 服务器 - */ -export async function initRankByServerId(serverId: number) { - // console.log('*****', 'initRank') - await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.GUILD_LV_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.TOP_LINEUP_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.TOP_HERO_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.HERO_NUM_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.USER_LV, { serverId }); - await setRankRedisFromDb(REDIS_KEY.SUM_CE_RANK, { serverId }); - // await setRankRedisFromDb(REDIS_KEY.DUNGEON_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.MAIN_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.HERO_RANK, { serverId }); - await setRankRedisFromDb(REDIS_KEY.LADDER, { serverId }); -} - -export async function initActivitiesRank(serverId: number) { - let serverTime = await getServerCreateTime(serverId); - let activityGroup = await ActivityGroupModel.findByServerId(serverId); - let activityGroupId = activityGroup.map(cur => cur.groupId); - let activities = await ActivityModel.findOpenActivityByType(activityGroupId, ACTIVITY_TYPE.TIME_LIMIT_RANK); - for(let activity of activities) { - let data = new TimeLimitRankData(activity, 0, serverTime); - if(data.beginTime <= Date.now() && data.endTime >= Date.now()) { - let redisKey = getRedisKeyByRankType(data.rankType, true); - - let ranks = await ActivityTimeLimitRankModel.getRank(serverId, data.activityId); - let r = new Rank(redisKey, { serverId, activityId: data.activityId }); - r.setIsInit(true); - for (let rank of ranks) { - if(r.infoKey == REDIS_KEY.USER_INFO) { - await r.setRankWithRoleInfo(rank.roleId, rank.score, rank.time||0, rank.role); - } else if(r.infoKey == REDIS_KEY.GUILD_INFO) { - await r.setRankWithGuildInfo(rank.guildCode, rank.score, rank.time||0, rank.guild); - } - } - } - } -} - -/** - * 初始化某一个排行榜,如定时器内 - * @param key redis内的key - */ -export async function initSingleRank(key: string) { - - await delKeys(key); - - if(key == REDIS_KEY.PVP_RANK) { - await setRankRedisFromDb(key, {}); - } else { - const serverList = await ServerlistModel.findByEnv(pinus.app.get('env')); - for(let { id } of serverList) { - await setRankRedisFromDb(key, { serverId: id }); - } - } -} - -/** - * debug接口使用,直接删除排行榜数据 - * @param params serverId => guildCodes - */ -export async function delGuildActivityRank(aid: number) { - if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - await delKeys(REDIS_KEY.USER_GATE_ACTIVITY); - await delKeys(REDIS_KEY.GATE_ACTIVITY); - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - await delKeys(REDIS_KEY.USER_CITY_ACTIVITY); - await delKeys(REDIS_KEY.CITY_ACTIVITY); - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - await delKeys(REDIS_KEY.RACE_ACTIVITY); - } -} - -export async function delKeys(key: string) { - let keys = await redisClient().keysAsync(`${key}*`); - for(let key of keys) { - await redisClient().delAsync(key); - } - return keys -} - -export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam|LineupParam[]) { - let value = JSON.stringify(params); - return await redisClient().hsetAsync(key, roleId, value); -} - -export async function updateUserInfo(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader|LeagueLeader)}>) { - let params = await redisClient().hgetAsync(key, roleId); - if(params) { - let obj = JSON.parse(params); - for(let {field, value} of arr) { - obj[field] = value; - } - return await redisClient().hsetAsync(key, roleId, JSON.stringify(obj)); - } -} - -export async function findKeys(key: string) { - let keys = await redisClient().keysAsync(`${key}*`); - return keys -} - - -/********排行榜结束 */ - - -/**************** 寻宝相关 start */ - -/** - * @description 拼接匹配分组的 key - * @param {number} lv 藏宝图品阶 - */ -function getComTeamKey(lv: number) { - return `${REDIS_KEY.COM_TEAM_SEARCH_PRE}:${lv}`; -} - -/** - * @description 拼接匹配分组中 member 的值 - * @param {string} roleId - * @param {string} sid connector serverId - * @returns - */ -function getComTeamValue(roleId: string, sid: string) { - return `${roleId}:${sid}`; -} - -/** - * @description 把寻宝的玩家信息存入 redis - * @export - * @param {string} roleId - * @param {string} sid - * @param {Array} qualityArr - * @param {number} lvRange - * @returns - */ -export async function setTeamSearchReq(roleId: string, sid: string, lvs: number[]) { - let cmds = []; - lvs.forEach(lv => { - if (lv) { - cmds.push(['sadd', getComTeamKey(lv), getComTeamValue(roleId, sid)]); - } - }); - const res = await redisClient().multi(cmds).execAsync(); - - return res; -} - -/** - * @description 从匹配队列中删除某个用户 - * @export - * @param {string} roleId - * @param {string} sid - * @param {number} lv 如果不填表示所有品阶 - */ -export async function rmRoleFromQueue(roleId: string, sid: string, lvs?: number[]) { - - let cmds = []; - if (lvs) { - for(let lv of lvs) { - cmds.push(['srem', getComTeamKey(lv), getComTeamValue(roleId, sid)]); - } - } else { - for (let range of comBtlRanges()) { - cmds.push(['srem', getComTeamKey(range), getComTeamValue(roleId, sid)]); - } - } - await redisClient().multi(cmds).execAsync(); -} - -function getComCreateTeamKey(lv: number) { - return `${REDIS_KEY.COM_TEAM_CREATED_TEAM}:${lv}`; -} - -export async function setCreatedTeamToRedis(teamCode: string, lv: number) { - let sid = pinus.app.getCurServer().id; - await redisClient().hsetAsync(getComCreateTeamKey(lv), teamCode, sid); -} - -export async function rmCreatedTeamFromRedis(teamCode: string, lv: number) { - await redisClient().hdelAsync(getComCreateTeamKey(lv), teamCode); -} - -/** - * @description 在寻宝匹配队列中随机两个玩家 - * @export - * @param {number} quality 队伍品质 - * @param {number} lvRange 等级范围 - * @returns - */ -export async function getTeamSearchByLv(lv: number) { - // TODO: 操作不具有原子性 - const userInfos = await redisClient().srandmemberAsync(getComTeamKey(lv), 2); - console.log('getTeamSearchByLv: ' + userInfos); - if (!userInfos || !userInfos.length) return null; - - let res = []; - for (let userInfo of userInfos) { - const decodeData = `${userInfo}`.split(':'); - if (decodeData.length !== 2) return null; - res.push({roleId: decodeData[0], sid: decodeData[1]}); - } - console.log('getTeamSearchByLv res: ', res); - return res; -} - -export async function getCreatedTeamByLv(lvs: number[]) { - let team: {lv: number, teamCode: string}[] = []; - for(let lv of lvs) { - let teams = await redisClient().hkeysAsync(getComCreateTeamKey(lv)); - team.push(...teams.map(teamCode => ({ lv, teamCode }))); - } - return team; -} - -export async function getComTeamSidByCode(lv: number, teamCode: string) { - let sid = await redisClient().hgetAsync(getComCreateTeamKey(lv), teamCode); - return sid -} - -/** - * @description 检查玩家是否在某个队列中等待寻宝匹配 - * @export - * @param {string} roleId - * @param {string} sid - * @param {number} lv - * @returns - */ -export async function checkRoleInQueue(roleId: string, sid: string, lvs: number[]) { - for (let lv of lvs) { - let res = await redisClient().sismemberAsync(getComTeamKey(lv), `${roleId}:${sid}`); - if (res) { - return true; - } - }; - - return false; -} - -/** - * @description 清除所有的寻宝匹配队列 - * @export - */ -export async function clearComBtlQueue() { - await delKeys(REDIS_KEY.COM_TEAM_SEARCH_PRE); - await delKeys(REDIS_KEY.COM_TEAM_CREATED_TEAM); -} - -export function setRedis(key: string, data: string) { - redisClient().setAsync(key, data); -} - -export async function getRedis(key: string) { - const str = await redisClient().getAsync(key); - return str; -} - -export async function delRedis(key: string) { - await redisClient().delAsync(key); -} - -export function redisSidKey(roleId: string) { - return `login_roleId_${roleId}`; -} - -export async function redisChannelServer(roomId: string) { - const sid = await redisClient().hgetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId); - return sid; -} - -export async function addRedisChannel(roomId: string, sid: string) { - const result = await redisClient().hsetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId, sid); - return result; -} - -export async function clearChannelServers() { - const result = await redisClient().delAsync(REDIS_KEY.CHANNEL_SERVERS); - return result; -} - -/** - * 玩家上线 - * @param roleId role表id - * @param userCode user表唯一字符串标识 - * @param sid connector服的那个sid - */ -export async function roleLogin(roleId: string, userCode: string, sid: string, createTime: number, serverId: number, lv: number, topLineupCe: number) { - await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, 1); - await redisClient().hsetAsync(REDIS_KEY.USER_CODE, userCode, roleId); - return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${userCode}|${sid}|${createTime}|${serverId}|${lv}|${topLineupCe}`); -} - -export async function updateRoleOnlineInfo(roleId: string, updateData: {lv?: number, topLineupCe?: number}) { - let info = await getRoleOnlineInfo(roleId); - if(info.isOnline) { - return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${info.userCode}|${info.sid}|${info.createtime}|${info.serverId}|${updateData?.lv??info.lv}|${updateData?.topLineupCe??info.topLineupCe}`); - } -} - -/** - * 玩家下线 - * @param roleId role表id - */ -export async function roleLeave(roleId: string) { - let role = await getRoleOnlineInfo(roleId); - let count = await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, -1); - if(count <= 0) { - await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId); - await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId); - if(role) await redisClient().hdelAsync(REDIS_KEY.USER_CODE, role.userCode); - await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId); - } - return role; -} - -/** - * 判断玩家是否在线 - * @param roleId role表id - */ -export async function isRoleOnline(roleId: string) { - let result = await redisClient().hexistsAsync(REDIS_KEY.ONLINE_USERS, roleId); - return !!result; -} - -export async function getOnlineRoleByUserCode(userCode: string) { - let roleId = await redisClient().hgetAsync(REDIS_KEY.USER_CODE, userCode); - return roleId; -} - -/** - * 获得在线玩家userCode和sid - * @param roleId - */ -export async function getRoleOnlineInfo(roleId: string) { - let str = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roleId); - if(str) { - try { - let result = str.split('|'); - let [userCode, sid, createTime, serverId, lv, topLineupCe] = result; - - return { - isOnline: true, userCode, sid, - createtime: parseInt(createTime), - serverId: parseInt(serverId), - lv: parseInt(lv), - topLineupCe: parseInt(topLineupCe) - } - } catch(e) { - return { isOnline: false } - } - } else { - return { isOnline: false } - } -} - -export async function getRoleCreateTime(roleId: string, role?: RoleType) { - if(role && role.createTime) return role.createTime; - - let onlineInfo = await getRoleOnlineInfo(roleId); - if(onlineInfo.isOnline) { - return onlineInfo.createtime; - } else { - let role = await RoleModel.findByRoleId(roleId); - return role?.createTime||0; - } -} - -/** - * 获得所有在线的玩家 - */ -export async function getAllOnlineRoles() { - let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS); - let result = new Array<{roleId: string, userCode: string, sid: string, serverId: number, lv: number, topLineupCe: number}>(); - for(let roleId in allRoles) { - try{ - let param = allRoles[roleId].split('|'); - let [userCode, sid, _createTime, serverId, lv, topLineupCe] = param; - - result.push({ roleId, userCode, sid, serverId: parseInt(serverId), lv: parseInt(lv), topLineupCe: parseInt(topLineupCe) }); - - } catch(e) { - continue; - } - } - return result; -} - -/** - * 将玩家登录时间记录到 - * @param userCode 玩家user表里的userCode - * @param isToday 累计记录还是当日记录 - * @returns 分钟 - */ -export async function incOnlineTime(userCode: string, isToday: boolean, incTime: number) { - moment.locale('zh-cn'); - let today = moment().format('YYYYMMDD'); - let key = isToday? `${REDIS_KEY.ONLINE_TIME}:${today}`: REDIS_KEY.ONLINE_TIME; - if(isToday) { - let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).unix(); - let result = await redisClient().hincrbyAsync(key, userCode, incTime); - let result2 = await redisClient().expireatAsync(key, tomorrow); - // console.log(result2) - return result; - } else { - return await redisClient().hincrbyAsync(key, userCode, incTime); - } -} - -export async function setOnlineTime(userCode: string, isToday: boolean, setTime: number) { - moment.locale('zh-cn'); - let today = moment().format('YYYYMMDD'); - let key = isToday? REDIS_KEY.ONLINE_TIME: `${REDIS_KEY.ONLINE_TIME}:${today}`; - if(isToday) { - let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).format('x'); - await redisClient().expireatAsync(key, parseInt(tomorrow)); - } - return await redisClient().hsetAsync(key, userCode, setTime); -} - - -// 排行榜是否存在 -export async function smembersAsync(key: string) { - const result = await redisClient().smembersAsync(key); - return result; -} - -export async function saddAsync(key: string, values: Array) { - const result = await redisClient().saddAsync(key, values); - return result; -} - -export async function sismemberAsync(key: string, value: string) { - const result = await redisClient().sismemberAsync(key, value); - return result; -} - -export async function delAsync(key:string) { - await redisClient().delAsync(key); -} - -export async function sremAsync(key:string, member:string) { - await redisClient().sremAsync(key, member); -} -/**************** 寻宝相关 end */ - -/**************** 数据库表存入缓存 */ - -export async function readDataBase() { - await setServerList(); -} - -async function setServerList() { - const serverList = await ServerlistModel.getAllServerList(); - await redisClient().delAsync(REDIS_KEY.SERVER); - await redisClient().delAsync(REDIS_KEY.SERVER_OPEN_TIME); - - for(let { id, serverId, name, openTime, env } of serverList) { - if(env == pinus.app.get('env')) { - // console.log(roleId); - await redisClient().hsetAsync(REDIS_KEY.SERVER, `${id}`, `${name}`); - await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${id}`, `${openTime}`); - } - } -} - -export async function getAllServers() { - let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER); - let serverlist = new Array(); - for(let serverStr in servers) { - let serverId = parseInt(serverStr); - - if(!isNaN(serverId) && !serverlist.includes(serverId)) { - serverlist.push(serverId); - } - } - return serverlist; -} - -export async function getAllServerName(): Promise<{[serverId: string]: string}> { - let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER); - return servers; -} - -export async function getServerName(serverId: number) { - let name = await redisClient().hgetAsync(REDIS_KEY.SERVER, `${serverId}`); - return name||'常山少年' -} - -export async function getServerCreateTime(serverId: number) { - let time = await redisClient().hgetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${serverId}`); - return parseInt(time); -} - -export async function getAllServerCreateTime() { - let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER_OPEN_TIME); - return servers; -} - -export function redisClient() { - const client: Redis.RedisClient = pinus.app.get('redis'); - return client; -} - -export async function hasKey(key: string) { - return await redisClient().existsAsync(key); -} - -/**************** 数据库表end */ - -/**************** 名将擂台防守战力 */ -export async function saveLadderDefCeByData(roleId: string, ladderMatch?: LadderMatchType) { - if(!ladderMatch) { - ladderMatch = await LadderMatchModel.findByRoleId(roleId); - if(!ladderMatch) return; - } - let heroes = ladderMatch.defense?.heroes||[]; - let defCe = heroes.reduce((pre, cur) => pre + cur.ce, 0); - await saveLadderDefCe(roleId, defCe); -} - -export async function saveLadderDefCe(roleId: string, defCe: number) { - await redisClient().hsetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`, defCe); -} - -export async function getLadderDefCe(roleId: string) { - let defCe = await redisClient().hgetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`); - return defCe||0; -} - -/**************** 名将擂台防守战力end */ - -/*************** 将connector服插入redis *******/ - -export async function setConnectors(servers: ServerInfo[]) { - for(let server of servers) { - if(server.serverType == 'connector' && server.id != 'connector-server-gm') { - let { serverType, clientHost, clientPort, id } = server; - await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, server.id, JSON.stringify({ serverType, clientHost, clientPort, id })); - } - } -} - -export async function removeConnectors(servers: string[]) { - for(let server of servers) { - let hasServer = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, server); - if(!!hasServer) await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, server); - } -} - -export async function checkConnectors() { - let servers = pinus.app.getServersByType('connector'); - let redisServers = await redisClient().hgetallAsync(REDIS_KEY.SYS_SERVER); - for(let id in redisServers) { - let server = servers.find(cur => cur.id == id); - if(!server || server.id == 'connector-server-gm') { - await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, id); - } - } -} - -export async function incConnectorNum(sid: string, inc: number) { - let server = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, sid); - let json = JSON.parse(server); - let { id, serverType, clientHost, clientPort, num = 0 } = json; - let newNum = num + inc; - if(newNum < 0) newNum = 0; - await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: newNum })); -} - -/*************** 将connector服插入redis *******/ - - -/*************** 订阅短链接redis *******/ - -export function redisClientPub() { - const client: Redis.RedisClient = pinus.app.get('redisPub'); - return client; -} - -export async function redisSubScribe() { - let env = pinus.app.get('env'); - if(env == 'development') env = 'local'; // 本地处理 - let payChannel = getRedisSubChannel(REDIS_KEY.PAY_CHANNEL, env); - let refundChannel = getRedisSubChannel(REDIS_KEY.REFUND_CHANNEL, env); - let treatRoleChannel = getRedisSubChannel(REDIS_KEY.TREAT_ROLE_CHANNEL, env); - let treatGuildChannel = getRedisSubChannel(REDIS_KEY.TREAT_GUILD_CHANNEL, env); - let surveyChannel = getRedisSubChannel(REDIS_KEY.SURVEY_CHANNEL, env); - let userChannel = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, env); - let publicAccountChannel = getRedisSubChannel(REDIS_KEY.PUBLIC_ACCOUNT_GIFT, env); - let sendGiftCodeChannel = getRedisSubChannel(REDIS_KEY.SEND_GIFT_CODE, env); - await redisClientPub().subscribeAsync(payChannel, treatRoleChannel, treatGuildChannel, refundChannel, surveyChannel, userChannel, publicAccountChannel, sendGiftCodeChannel); - redisClientPub().on('message', (channel, message) => { - console.log('**********redisSubScribe*******') - console.log('channel: ', channel, payChannel); - - if(channel == payChannel) { - let servers = pinus.app.getServersByType('order'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.order.orderRemote.settleOrderFromRedisPub.toServer(server.id, message); - } else if (channel == treatRoleChannel) { - let servers = pinus.app.getServersByType('role'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.role.roleRemote.treatRoleName.toServer(server.id, message); - } else if (channel == treatGuildChannel) { - let servers = pinus.app.getServersByType('guild'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.guild.guildRemote.treatGuildName.toServer(server.id, message); - } else if (channel == refundChannel) { - let servers = pinus.app.getServersByType('order'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.order.orderRemote.refundOrderFromRedisPub.toServer(server.id, message); - } else if (channel == surveyChannel) { - let servers = pinus.app.getServersByType('role'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.role.roleRemote.sendSurveyMail.toServer(server.id, message); - } else if(channel == userChannel) { - let [sid, roleId] = (message||'').split('|'); - if(!!sid && !!roleId) pinus.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId); - } else if (channel == publicAccountChannel) { - let servers = pinus.app.getServersByType('activity'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.activity.activityRemote.sendPublicAccountGift.toServer(server.id, message); - } else if (channel == sendGiftCodeChannel) { - let servers = pinus.app.getServersByType('role'); - let server = getRandSingleEelm(servers); - pinus.app.rpc.role.roleRemote.sendGiftCodeMail.toServer(server.id, message); - - } - }); -} -/*************** 订阅短链接redis *******/ - -/***诸侯混战 */ -export async function getHistoryCity(roleId: string) { - return await redisClient().hgetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`); -} - -export async function setHistoryCity(roleId: string, cityId: number) { - await redisClient().hsetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`, cityId); -} - -// gvg激战期玩家之前所处的区域,用于退出的时候查询 -export async function getGVGHistoryAreas(roleId: string) { - let areaIds = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId); - if(!areaIds) return [] - return areaIds.split('&'); -} - -export async function addGVGHistoryAreas(roleId: string, groupKey: string, areaIds: number[]) { - let key = areaIds.map(areaId => `${groupKey}_${areaId}`).join('&'); - const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId, key); - return result; -} - -export async function delGVGHistoryAreas(roleId: string) { - const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId); - return result; -} - -export async function clearGVGHistoryAreas() { - const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA); - return result; -} - - -export async function getGVGHistoryAreaTeam(roleId: string) { - let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId); - return channelName -} - -export async function addGVGHistoryAreaTeam(roleId: string, groupKey: string, areaId: number) { - const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId, `${groupKey}_${areaId}`); - return result; -} - -export async function delGVGHistoryAreaTeam(roleId: string) { - const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId); - return result; -} - -export async function clearGVGHistoryAreaTeam() { - const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM); - return result; -} - - -export async function getGVGHistoryCityTeam(roleId: string) { - let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId); - return channelName -} - -export async function addGVGHistoryCityTeam(roleId: string, groupKey: string, cityId: number) { - const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId, `${groupKey}_${cityId}`); - return result; -} - -export async function delGVGHistoryCityTeam(roleId: string) { - const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId); - return result; -} - -export async function clearGVGHistoryCityTeam() { - const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_CITY); - return result; -} - -// 设置最大同时在线人数 -export async function resetMaxOnlineUsers() { - const res = await redisClient().setAsync(REDIS_KEY.MAX_ONLINE_USERS, `${MAX_ONLINE_USER_COUNT}`); - return res; -} - -export async function checkRecalJewelOpen() { - // 设置redis开关 - let isCheckBlock = await redisClient().getAsync(REDIS_KEY.RE_CAL_JEWEL); - if (!isCheckBlock || isCheckBlock == undefined) { - //首次写入 默认是关 - await redisClient().setAsync(REDIS_KEY.RE_CAL_JEWEL, 'false'); - return false - } - return isCheckBlock == 'true' -} \ No newline at end of file +import { ACTIVITY_TYPE, getRedisKeyByRankType, GUILD_ACTIVITY_TYPE, MAX_ONLINE_USER_COUNT, REDIS_KEY } from '@consts'; +import * as Redis from 'redis'; +import { pinus, ServerInfo } from 'pinus'; +import { GuildRankParam, GuildLeader, RankParam, LineupParam, LeagueLeader } from '@domain/rank'; +import { comBtlRanges } from '@pubUtils/data'; +import { Rank, setRankRedisFromDb } from './rankService'; +import { ServerlistModel } from '@db/Serverlist'; +import moment = require('moment'); +import { getRedisSubChannel } from '@pubUtils/sdkUtil'; +import { getRandSingleEelm, parseNumberList } from '@pubUtils/util'; +import { ActivityModel } from '@db/Activity'; +import { TimeLimitRankData } from '@domain/activityField/timeLimitRankField'; +import { ActivityTimeLimitRankModel } from '@db/ActivityTimeLimitRank'; +import { RoleModel, RoleType } from '@db/Role'; +import { GuildType } from '@db/Guild'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { LadderMatchModel, LadderMatchType } from '@db/LadderMatch'; +import { isDevelopEnv } from './utilService'; + +/** + * 在服务重新启动时,将信息存入redis + */ +export async function initAllRank() { + console.log('******* initAllRank ******') + const serverList = await ServerlistModel.findByEnv(pinus.app.get('env')); + await delKeys(REDIS_KEY.ONLINE_USERS); + await delKeys(REDIS_KEY.ONLINE_CNT); + await delKeys(REDIS_KEY.USER_INFO); + await delKeys(REDIS_KEY.GUILD_INFO); + await delKeys(REDIS_KEY.TOP_LINEUP_INFO); + await delKeys(REDIS_KEY.HERO_INFO); + await delKeys(REDIS_KEY.TOWER_RANK); + await delKeys(REDIS_KEY.GUILD_LV_RANK); + await delKeys(REDIS_KEY.GUILD_ACTIVE_RANK); + await delKeys(REDIS_KEY.TOP_LINEUP_RANK); + await delKeys(REDIS_KEY.TOP_HERO_RANK); + await delKeys(REDIS_KEY.HERO_NUM_RANK); + await delKeys(REDIS_KEY.USER_LV); + await delKeys(REDIS_KEY.SUM_CE_RANK); + // await delKeys(REDIS_KEY.DUNGEON_RANK); + await delKeys(REDIS_KEY.DUNGEON_LINEUP); + await delKeys(REDIS_KEY.MAIN_RANK); + await delKeys(REDIS_KEY.MAIN_ELITE_RANK); + await delKeys(REDIS_KEY.HERO_RANK); + await delKeys(REDIS_KEY.SHOW_LINEUP); + // await delKeys(REDIS_KEY.PVP_RANK); + await delKeys(REDIS_KEY.GUILD_FUND); + await delKeys(REDIS_KEY.SUM_CE_SNAPSHOT); + await delKeys(REDIS_KEY.TOP_LINE_SNAPSHOT); + await delKeys(REDIS_KEY.LADDER); + await delKeys(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL); + await delKeys(REDIS_KEY.GVG_VESTIGE_LEAGUE); + await delKeys(REDIS_KEY.ACTIVITY_MINI_GAME); + // 测试服特殊处理,由于重启较频繁且联军数据较少,数据先不删,正式服激战期间不会重启 + if(!isDevelopEnv()) await delKeys(REDIS_KEY.LEAGUE_INFO); + + await setRankRedisFromDb(REDIS_KEY.PVP_RANK, {}); + await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, {}); + await setRankRedisFromDb(REDIS_KEY.GVG_VESTIGE_LEAGUE, {}); + await setRankRedisFromDb(REDIS_KEY.ACTIVITY_MINI_GAME, {}); + + for(let {id} of serverList) { + await initRankByServerId(id); + await initActivitiesRank(id) + } +} + +/** + * 分服内初始redis排行榜 + * + * @param serverId 服务器 + */ +export async function initRankByServerId(serverId: number) { + // console.log('*****', 'initRank') + await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.GUILD_LV_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.TOP_LINEUP_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.TOP_HERO_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.HERO_NUM_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.USER_LV, { serverId }); + await setRankRedisFromDb(REDIS_KEY.SUM_CE_RANK, { serverId }); + // await setRankRedisFromDb(REDIS_KEY.DUNGEON_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.MAIN_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.HERO_RANK, { serverId }); + await setRankRedisFromDb(REDIS_KEY.LADDER, { serverId }); +} + +export async function initActivitiesRank(serverId: number) { + let serverTime = await getServerCreateTime(serverId); + let activityGroup = await ActivityGroupModel.findByServerId(serverId); + let activityGroupId = activityGroup.map(cur => cur.groupId); + let activities = await ActivityModel.findOpenActivityByType(activityGroupId, ACTIVITY_TYPE.TIME_LIMIT_RANK); + for(let activity of activities) { + let data = new TimeLimitRankData(activity, 0, serverTime); + if(data.beginTime <= Date.now() && data.endTime >= Date.now()) { + let redisKey = getRedisKeyByRankType(data.rankType, true); + + let ranks = await ActivityTimeLimitRankModel.getRank(serverId, data.activityId); + let r = new Rank(redisKey, { serverId, activityId: data.activityId }); + r.setIsInit(true); + for (let rank of ranks) { + if(r.infoKey == REDIS_KEY.USER_INFO) { + await r.setRankWithRoleInfo(rank.roleId, rank.score, rank.time||0, rank.role); + } else if(r.infoKey == REDIS_KEY.GUILD_INFO) { + await r.setRankWithGuildInfo(rank.guildCode, rank.score, rank.time||0, rank.guild); + } + } + } + } +} + +/** + * 初始化某一个排行榜,如定时器内 + * @param key redis内的key + */ +export async function initSingleRank(key: string) { + + await delKeys(key); + + if(key == REDIS_KEY.PVP_RANK) { + await setRankRedisFromDb(key, {}); + } else { + const serverList = await ServerlistModel.findByEnv(pinus.app.get('env')); + for(let { id } of serverList) { + await setRankRedisFromDb(key, { serverId: id }); + } + } +} + +/** + * debug接口使用,直接删除排行榜数据 + * @param params serverId => guildCodes + */ +export async function delGuildActivityRank(aid: number) { + if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + await delKeys(REDIS_KEY.USER_GATE_ACTIVITY); + await delKeys(REDIS_KEY.GATE_ACTIVITY); + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + await delKeys(REDIS_KEY.USER_CITY_ACTIVITY); + await delKeys(REDIS_KEY.CITY_ACTIVITY); + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + await delKeys(REDIS_KEY.RACE_ACTIVITY); + } +} + +export async function delKeys(key: string) { + let keys = await redisClient().keysAsync(`${key}*`); + for(let key of keys) { + await redisClient().delAsync(key); + } + return keys +} + +export async function setUserInfo(key: string, roleId: string, params: RankParam|GuildRankParam|LineupParam[]) { + let value = JSON.stringify(params); + return await redisClient().hsetAsync(key, roleId, value); +} + +export async function updateUserInfo(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader|LeagueLeader)}>) { + let params = await redisClient().hgetAsync(key, roleId); + if(params) { + let obj = JSON.parse(params); + for(let {field, value} of arr) { + obj[field] = value; + } + return await redisClient().hsetAsync(key, roleId, JSON.stringify(obj)); + } +} + +export async function findKeys(key: string) { + let keys = await redisClient().keysAsync(`${key}*`); + return keys +} + + +/********排行榜结束 */ + + +/**************** 寻宝相关 start */ + +/** + * @description 拼接匹配分组的 key + * @param {number} lv 藏宝图品阶 + */ +function getComTeamKey(lv: number) { + return `${REDIS_KEY.COM_TEAM_SEARCH_PRE}:${lv}`; +} + +/** + * @description 拼接匹配分组中 member 的值 + * @param {string} roleId + * @param {string} sid connector serverId + * @returns + */ +function getComTeamValue(roleId: string, sid: string) { + return `${roleId}:${sid}`; +} + +/** + * @description 把寻宝的玩家信息存入 redis + * @export + * @param {string} roleId + * @param {string} sid + * @param {Array} qualityArr + * @param {number} lvRange + * @returns + */ +export async function setTeamSearchReq(roleId: string, sid: string, lvs: number[]) { + let cmds = []; + lvs.forEach(lv => { + if (lv) { + cmds.push(['sadd', getComTeamKey(lv), getComTeamValue(roleId, sid)]); + } + }); + const res = await redisClient().multi(cmds).execAsync(); + + return res; +} + +/** + * @description 从匹配队列中删除某个用户 + * @export + * @param {string} roleId + * @param {string} sid + * @param {number} lv 如果不填表示所有品阶 + */ +export async function rmRoleFromQueue(roleId: string, sid: string, lvs?: number[]) { + + let cmds = []; + if (lvs) { + for(let lv of lvs) { + cmds.push(['srem', getComTeamKey(lv), getComTeamValue(roleId, sid)]); + } + } else { + for (let range of comBtlRanges()) { + cmds.push(['srem', getComTeamKey(range), getComTeamValue(roleId, sid)]); + } + } + await redisClient().multi(cmds).execAsync(); +} + +function getComCreateTeamKey(lv: number) { + return `${REDIS_KEY.COM_TEAM_CREATED_TEAM}:${lv}`; +} + +export async function setCreatedTeamToRedis(teamCode: string, lv: number) { + let sid = pinus.app.getCurServer().id; + await redisClient().hsetAsync(getComCreateTeamKey(lv), teamCode, sid); +} + +export async function rmCreatedTeamFromRedis(teamCode: string, lv: number) { + await redisClient().hdelAsync(getComCreateTeamKey(lv), teamCode); +} + +/** + * @description 在寻宝匹配队列中随机两个玩家 + * @export + * @param {number} quality 队伍品质 + * @param {number} lvRange 等级范围 + * @returns + */ +export async function getTeamSearchByLv(lv: number) { + // TODO: 操作不具有原子性 + const userInfos = await redisClient().srandmemberAsync(getComTeamKey(lv), 2); + console.log('getTeamSearchByLv: ' + userInfos); + if (!userInfos || !userInfos.length) return null; + + let res = []; + for (let userInfo of userInfos) { + const decodeData = `${userInfo}`.split(':'); + if (decodeData.length !== 2) return null; + res.push({roleId: decodeData[0], sid: decodeData[1]}); + } + console.log('getTeamSearchByLv res: ', res); + return res; +} + +export async function getCreatedTeamByLv(lvs: number[]) { + let team: {lv: number, teamCode: string}[] = []; + for(let lv of lvs) { + let teams = await redisClient().hkeysAsync(getComCreateTeamKey(lv)); + team.push(...teams.map(teamCode => ({ lv, teamCode }))); + } + return team; +} + +export async function getComTeamSidByCode(lv: number, teamCode: string) { + let sid = await redisClient().hgetAsync(getComCreateTeamKey(lv), teamCode); + return sid +} + +/** + * @description 检查玩家是否在某个队列中等待寻宝匹配 + * @export + * @param {string} roleId + * @param {string} sid + * @param {number} lv + * @returns + */ +export async function checkRoleInQueue(roleId: string, sid: string, lvs: number[]) { + for (let lv of lvs) { + let res = await redisClient().sismemberAsync(getComTeamKey(lv), `${roleId}:${sid}`); + if (res) { + return true; + } + }; + + return false; +} + +/** + * @description 清除所有的寻宝匹配队列 + * @export + */ +export async function clearComBtlQueue() { + await delKeys(REDIS_KEY.COM_TEAM_SEARCH_PRE); + await delKeys(REDIS_KEY.COM_TEAM_CREATED_TEAM); +} + +export function setRedis(key: string, data: string) { + redisClient().setAsync(key, data); +} + +export async function getRedis(key: string) { + const str = await redisClient().getAsync(key); + return str; +} + +export async function delRedis(key: string) { + await redisClient().delAsync(key); +} + +export function redisSidKey(roleId: string) { + return `login_roleId_${roleId}`; +} + +export async function redisChannelServer(roomId: string) { + const sid = await redisClient().hgetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId); + return sid; +} + +export async function addRedisChannel(roomId: string, sid: string) { + const result = await redisClient().hsetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId, sid); + return result; +} + +export async function clearChannelServers() { + const result = await redisClient().delAsync(REDIS_KEY.CHANNEL_SERVERS); + return result; +} + +/** + * 玩家上线 + * @param roleId role表id + * @param userCode user表唯一字符串标识 + * @param sid connector服的那个sid + */ +export async function roleLogin(roleId: string, userCode: string, sid: string, createTime: number, serverId: number, lv: number, topLineupCe: number) { + await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, 1); + await redisClient().hsetAsync(REDIS_KEY.USER_CODE, userCode, roleId); + return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${userCode}|${sid}|${createTime}|${serverId}|${lv}|${topLineupCe}`); +} + +export async function updateRoleOnlineInfo(roleId: string, updateData: {lv?: number, topLineupCe?: number}) { + let info = await getRoleOnlineInfo(roleId); + if(info.isOnline) { + return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, `${info.userCode}|${info.sid}|${info.createtime}|${info.serverId}|${updateData?.lv??info.lv}|${updateData?.topLineupCe??info.topLineupCe}`); + } +} + +/** + * 玩家下线 + * @param roleId role表id + */ +export async function roleLeave(roleId: string) { + let role = await getRoleOnlineInfo(roleId); + let count = await redisClient().hincrbyAsync(REDIS_KEY.ONLINE_CNT, roleId, -1); + if(count <= 0) { + await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId); + await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId); + if(role) await redisClient().hdelAsync(REDIS_KEY.USER_CODE, role.userCode); + await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId); + } + return role; +} + +/** + * 判断玩家是否在线 + * @param roleId role表id + */ +export async function isRoleOnline(roleId: string) { + let result = await redisClient().hexistsAsync(REDIS_KEY.ONLINE_USERS, roleId); + return !!result; +} + +export async function getOnlineRoleByUserCode(userCode: string) { + let roleId = await redisClient().hgetAsync(REDIS_KEY.USER_CODE, userCode); + return roleId; +} + +/** + * 获得在线玩家userCode和sid + * @param roleId + */ +export async function getRoleOnlineInfo(roleId: string) { + let str = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roleId); + if(str) { + try { + let result = str.split('|'); + let [userCode, sid, createTime, serverId, lv, topLineupCe] = result; + + return { + isOnline: true, userCode, sid, + createtime: parseInt(createTime), + serverId: parseInt(serverId), + lv: parseInt(lv), + topLineupCe: parseInt(topLineupCe) + } + } catch(e) { + return { isOnline: false } + } + } else { + return { isOnline: false } + } +} + +export async function getRoleCreateTime(roleId: string, role?: RoleType) { + if(role && role.createTime) return role.createTime; + + let onlineInfo = await getRoleOnlineInfo(roleId); + if(onlineInfo.isOnline) { + return onlineInfo.createtime; + } else { + let role = await RoleModel.findByRoleId(roleId); + return role?.createTime||0; + } +} + +/** + * 获得所有在线的玩家 + */ +export async function getAllOnlineRoles() { + let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS); + let result = new Array<{roleId: string, userCode: string, sid: string, serverId: number, lv: number, topLineupCe: number}>(); + for(let roleId in allRoles) { + try{ + let param = allRoles[roleId].split('|'); + let [userCode, sid, _createTime, serverId, lv, topLineupCe] = param; + + result.push({ roleId, userCode, sid, serverId: parseInt(serverId), lv: parseInt(lv), topLineupCe: parseInt(topLineupCe) }); + + } catch(e) { + continue; + } + } + return result; +} + +/** + * 将玩家登录时间记录到 + * @param userCode 玩家user表里的userCode + * @param isToday 累计记录还是当日记录 + * @returns 分钟 + */ +export async function incOnlineTime(userCode: string, isToday: boolean, incTime: number) { + moment.locale('zh-cn'); + let today = moment().format('YYYYMMDD'); + let key = isToday? `${REDIS_KEY.ONLINE_TIME}:${today}`: REDIS_KEY.ONLINE_TIME; + if(isToday) { + let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).unix(); + let result = await redisClient().hincrbyAsync(key, userCode, incTime); + let result2 = await redisClient().expireatAsync(key, tomorrow); + // console.log(result2) + return result; + } else { + return await redisClient().hincrbyAsync(key, userCode, incTime); + } +} + +export async function setOnlineTime(userCode: string, isToday: boolean, setTime: number) { + moment.locale('zh-cn'); + let today = moment().format('YYYYMMDD'); + let key = isToday? REDIS_KEY.ONLINE_TIME: `${REDIS_KEY.ONLINE_TIME}:${today}`; + if(isToday) { + let tomorrow = moment().add(1, 'days').hours(0).minutes(0).seconds(0).format('x'); + await redisClient().expireatAsync(key, parseInt(tomorrow)); + } + return await redisClient().hsetAsync(key, userCode, setTime); +} + + +// 排行榜是否存在 +export async function smembersAsync(key: string) { + const result = await redisClient().smembersAsync(key); + return result; +} + +export async function saddAsync(key: string, values: Array) { + const result = await redisClient().saddAsync(key, values); + return result; +} + +export async function sismemberAsync(key: string, value: string) { + const result = await redisClient().sismemberAsync(key, value); + return result; +} + +export async function delAsync(key:string) { + await redisClient().delAsync(key); +} + +export async function sremAsync(key:string, member:string) { + await redisClient().sremAsync(key, member); +} +/**************** 寻宝相关 end */ + +/**************** 数据库表存入缓存 */ + +export async function readDataBase() { + await setServerList(); +} + +async function setServerList() { + const serverList = await ServerlistModel.getAllServerList(); + await redisClient().delAsync(REDIS_KEY.SERVER); + await redisClient().delAsync(REDIS_KEY.SERVER_OPEN_TIME); + + for(let { id, serverId, name, openTime, env } of serverList) { + if(env == pinus.app.get('env')) { + // console.log(roleId); + await redisClient().hsetAsync(REDIS_KEY.SERVER, `${id}`, `${name}`); + await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${id}`, `${openTime}`); + } + } +} + +export async function getAllServers() { + let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER); + let serverlist = new Array(); + for(let serverStr in servers) { + let serverId = parseInt(serverStr); + + if(!isNaN(serverId) && !serverlist.includes(serverId)) { + serverlist.push(serverId); + } + } + return serverlist; +} + +export async function getAllServerName(): Promise<{[serverId: string]: string}> { + let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER); + return servers; +} + +export async function getServerName(serverId: number) { + let name = await redisClient().hgetAsync(REDIS_KEY.SERVER, `${serverId}`); + return name||'常山少年' +} + +export async function getServerCreateTime(serverId: number) { + let time = await redisClient().hgetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${serverId}`); + return parseInt(time); +} + +export async function getAllServerCreateTime() { + let servers = await redisClient().hgetallAsync(REDIS_KEY.SERVER_OPEN_TIME); + return servers; +} + +export function redisClient() { + const client: Redis.RedisClient = pinus.app.get('redis'); + return client; +} + +export async function hasKey(key: string) { + return await redisClient().existsAsync(key); +} + +/**************** 数据库表end */ + +/**************** 名将擂台防守战力 */ +export async function saveLadderDefCeByData(roleId: string, ladderMatch?: LadderMatchType) { + if(!ladderMatch) { + ladderMatch = await LadderMatchModel.findByRoleId(roleId); + if(!ladderMatch) return; + } + let heroes = ladderMatch.defense?.heroes||[]; + let defCe = heroes.reduce((pre, cur) => pre + cur.ce, 0); + await saveLadderDefCe(roleId, defCe); +} + +export async function saveLadderDefCe(roleId: string, defCe: number) { + await redisClient().hsetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`, defCe); +} + +export async function getLadderDefCe(roleId: string) { + let defCe = await redisClient().hgetAsync(REDIS_KEY.LADDER_DEFCE, `${roleId}`); + return defCe||0; +} + +/**************** 名将擂台防守战力end */ + +/*************** 将connector服插入redis *******/ + +export async function setConnectors(servers: ServerInfo[]) { + for(let server of servers) { + if(server.serverType == 'connector' && server.id != 'connector-server-gm') { + let { serverType, clientHost, clientPort, id } = server; + await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, server.id, JSON.stringify({ serverType, clientHost, clientPort, id })); + } + } +} + +export async function removeConnectors(servers: string[]) { + for(let server of servers) { + let hasServer = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, server); + if(!!hasServer) await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, server); + } +} + +export async function checkConnectors() { + let servers = pinus.app.getServersByType('connector'); + let redisServers = await redisClient().hgetallAsync(REDIS_KEY.SYS_SERVER); + for(let id in redisServers) { + let server = servers.find(cur => cur.id == id); + if(!server || server.id == 'connector-server-gm') { + await redisClient().hdelAsync(REDIS_KEY.SYS_SERVER, id); + } + } +} + +export async function incConnectorNum(sid: string, inc: number) { + let server = await redisClient().hgetAsync(REDIS_KEY.SYS_SERVER, sid); + let json = JSON.parse(server); + let { id, serverType, clientHost, clientPort, num = 0 } = json; + let newNum = num + inc; + if(newNum < 0) newNum = 0; + await redisClient().hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: newNum })); +} + +/*************** 将connector服插入redis *******/ + + +/*************** 订阅短链接redis *******/ + +export function redisClientPub() { + const client: Redis.RedisClient = pinus.app.get('redisPub'); + return client; +} + +export async function redisSubScribe() { + let env = pinus.app.get('env'); + if(env == 'development') env = 'local'; // 本地处理 + let payChannel = getRedisSubChannel(REDIS_KEY.PAY_CHANNEL, env); + let refundChannel = getRedisSubChannel(REDIS_KEY.REFUND_CHANNEL, env); + let treatRoleChannel = getRedisSubChannel(REDIS_KEY.TREAT_ROLE_CHANNEL, env); + let treatGuildChannel = getRedisSubChannel(REDIS_KEY.TREAT_GUILD_CHANNEL, env); + let surveyChannel = getRedisSubChannel(REDIS_KEY.SURVEY_CHANNEL, env); + let userChannel = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, env); + let publicAccountChannel = getRedisSubChannel(REDIS_KEY.PUBLIC_ACCOUNT_GIFT, env); + let sendGiftCodeChannel = getRedisSubChannel(REDIS_KEY.SEND_GIFT_CODE, env); + await redisClientPub().subscribeAsync(payChannel, treatRoleChannel, treatGuildChannel, refundChannel, surveyChannel, userChannel, publicAccountChannel, sendGiftCodeChannel); + redisClientPub().on('message', (channel, message) => { + console.log('**********redisSubScribe*******') + console.log('channel: ', channel, payChannel); + + if(channel == payChannel) { + let servers = pinus.app.getServersByType('order'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.order.orderRemote.settleOrderFromRedisPub.toServer(server.id, message); + } else if (channel == treatRoleChannel) { + let servers = pinus.app.getServersByType('role'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.role.roleRemote.treatRoleName.toServer(server.id, message); + } else if (channel == treatGuildChannel) { + let servers = pinus.app.getServersByType('guild'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.guild.guildRemote.treatGuildName.toServer(server.id, message); + } else if (channel == refundChannel) { + let servers = pinus.app.getServersByType('order'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.order.orderRemote.refundOrderFromRedisPub.toServer(server.id, message); + } else if (channel == surveyChannel) { + let servers = pinus.app.getServersByType('role'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.role.roleRemote.sendSurveyMail.toServer(server.id, message); + } else if(channel == userChannel) { + let [sid, roleId] = (message||'').split('|'); + if(!!sid && !!roleId) pinus.app.rpc.connector.connectorRemote.remoteLogin.toServer(sid, roleId); + } else if (channel == publicAccountChannel) { + let servers = pinus.app.getServersByType('activity'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.activity.activityRemote.sendPublicAccountGift.toServer(server.id, message); + } else if (channel == sendGiftCodeChannel) { + let servers = pinus.app.getServersByType('role'); + let server = getRandSingleEelm(servers); + pinus.app.rpc.role.roleRemote.sendGiftCodeMail.toServer(server.id, message); + + } + }); +} +/*************** 订阅短链接redis *******/ + +/***诸侯混战 */ +export async function getHistoryCity(roleId: string) { + return await redisClient().hgetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`); +} + +export async function setHistoryCity(roleId: string, cityId: number) { + await redisClient().hsetAsync(REDIS_KEY.GA_HISTORY_CITY, `${roleId}`, cityId); +} + +// gvg激战期玩家之前所处的区域,用于退出的时候查询 +export async function getGVGHistoryAreas(roleId: string) { + let areaIds = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId); + if(!areaIds) return [] + return areaIds.split('&'); +} + +export async function addGVGHistoryAreas(roleId: string, groupKey: string, areaIds: number[]) { + let key = areaIds.map(areaId => `${groupKey}_${areaId}`).join('&'); + const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId, key); + return result; +} + +export async function delGVGHistoryAreas(roleId: string) { + const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA, roleId); + return result; +} + +export async function clearGVGHistoryAreas() { + const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA); + return result; +} + + +export async function getGVGHistoryAreaTeam(roleId: string) { + let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId); + return channelName +} + +export async function addGVGHistoryAreaTeam(roleId: string, groupKey: string, areaId: number) { + const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId, `${groupKey}_${areaId}`); + return result; +} + +export async function delGVGHistoryAreaTeam(roleId: string) { + const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM, roleId); + return result; +} + +export async function clearGVGHistoryAreaTeam() { + const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_AREA_TEAM); + return result; +} + + +export async function getGVGHistoryCityTeam(roleId: string) { + let channelName = await redisClient().hgetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId); + return channelName +} + +export async function addGVGHistoryCityTeam(roleId: string, groupKey: string, cityId: number) { + const result = await redisClient().hsetAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId, `${groupKey}_${cityId}`); + return result; +} + +export async function delGVGHistoryCityTeam(roleId: string) { + const result = await redisClient().hdelAsync(REDIS_KEY.GVG_HISTORY_CITY, roleId); + return result; +} + +export async function clearGVGHistoryCityTeam() { + const result = await redisClient().delAsync(REDIS_KEY.GVG_HISTORY_CITY); + return result; +} + +// 设置最大同时在线人数 +export async function resetMaxOnlineUsers() { + const res = await redisClient().setAsync(REDIS_KEY.MAX_ONLINE_USERS, `${MAX_ONLINE_USER_COUNT}`); + return res; +} + +export async function checkRecalJewelOpen() { + // 设置redis开关 + let isCheckBlock = await redisClient().getAsync(REDIS_KEY.RE_CAL_JEWEL); + if (!isCheckBlock || isCheckBlock == undefined) { + //首次写入 默认是关 + await redisClient().setAsync(REDIS_KEY.RE_CAL_JEWEL, 'false'); + return false + } + return isCheckBlock == 'true' +} diff --git a/game-server/app/services/redlockCacheService.ts b/game-server/app/services/redlockCacheService.ts index 51c85bd67..a6635af22 100644 --- a/game-server/app/services/redlockCacheService.ts +++ b/game-server/app/services/redlockCacheService.ts @@ -1,46 +1,46 @@ -import { fromCallback } from 'bluebird'; -import { scheduleJob } from 'node-schedule'; -import { nowSeconds } from '../pubUtils/timeUtil'; -import { RedlockService } from '../services/redLockService'; -interface UserCache { - time: number; - lock: any; -} -var userCacheMap = new Map(); - -export function init() { - scheduleJob('clearDirtyData', "0/5 * * * * *", clearDirtyData);//每个5秒钟,释放redis锁 -} -/** - * 释放锁 - */ -export function clearDirtyData() { - userCacheMap.forEach(function(userCache, key) { - if(nowSeconds() > userCache.time + 10){ - console.log('show lock =' + JSON.stringify(userCache.lock)); - releaseLock(key); - } - }) -} -/** - * 根据key解锁 - * @param lockKey - */ -export function releaseLock(lockKey: string) { - var userCache = userCacheMap.get(lockKey); - if (!!userCache && userCache.lock){ - // unlock your resource when you are done - userCache.lock.unlock(); - } - userCacheMap.delete(lockKey); -} - - -export function setLock(lockKey: string, lock: any){ - userCacheMap.set(lockKey, {lock, time: nowSeconds()}) -}; - -export function getLock(lockKey: string) { - var userCache = userCacheMap.get(lockKey); - return !!userCache && !!userCache.lock -} \ No newline at end of file +import { fromCallback } from 'bluebird'; +import { scheduleJob } from 'node-schedule'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { RedlockService } from '../services/redLockService'; +interface UserCache { + time: number; + lock: any; +} +var userCacheMap = new Map(); + +export function init() { + scheduleJob('clearDirtyData', "0/5 * * * * *", clearDirtyData);//每个5秒钟,释放redis锁 +} +/** + * 释放锁 + */ +export function clearDirtyData() { + userCacheMap.forEach(function(userCache, key) { + if(nowSeconds() > userCache.time + 10){ + console.log('show lock =' + JSON.stringify(userCache.lock)); + releaseLock(key); + } + }) +} +/** + * 根据key解锁 + * @param lockKey + */ +export function releaseLock(lockKey: string) { + var userCache = userCacheMap.get(lockKey); + if (!!userCache && userCache.lock){ + // unlock your resource when you are done + userCache.lock.unlock(); + } + userCacheMap.delete(lockKey); +} + + +export function setLock(lockKey: string, lock: any){ + userCacheMap.set(lockKey, {lock, time: nowSeconds()}) +}; + +export function getLock(lockKey: string) { + var userCache = userCacheMap.get(lockKey); + return !!userCache && !!userCache.lock +} diff --git a/game-server/app/services/refreshService.ts b/game-server/app/services/refreshService.ts index e979a4f8f..0e37617b4 100644 --- a/game-server/app/services/refreshService.ts +++ b/game-server/app/services/refreshService.ts @@ -1,54 +1,54 @@ -import { FrontendOrBackendSession, pinus } from "pinus"; -import { shouldRefresh, shouldRefreshWeek } from '../pubUtils/util'; -import { nowSeconds } from "../pubUtils/timeUtil"; -import { refDailyTask, refDailyTaskBox } from './task/taskService' -import { dispatch } from "../pubUtils/dispatcher"; -import { sendMessageToUserWithSuc } from "./pushService"; -import { PUSH_ROUTE } from "../consts"; -import { isDebugTime } from "../pubUtils/sdkUtil"; -import { redisClient } from "./redisService"; - -/** - * 刷新 - * @param session - */ -export async function refresh(session: FrontendOrBackendSession) { - const roleId = session.get('roleId')||'test'; - const sid = session.get('sid'); - - if(!isDebugTime()) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: Date.now() }, sid); - } else { - let guilds = pinus.app.getServersByType('guild'); - let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); - let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: currentTime }, sid); - } - await refreshDaily(session); - // await startEvent(session); -} - -/** - * 每日刷新 - * @param session - */ -export async function refreshDaily(session: FrontendOrBackendSession) { - - if(session.get('roleId')) { - let refDaily: number = session.get('refDaily'); // 10位时间戳,每天每人更新一次 - let refWeekly: number = session.get('refWeekly'); // 10位时间戳,每天每人更新一次 - if(!refDaily || shouldRefresh(new Date(refDaily * 1000), new Date())) { - refDaily = nowSeconds(); - session.set('refDaily', refDaily); - session.push('refDaily', () => {}); - await refDailyTask(session.get('roleId'), session.get('sid')); - } - - if(!refWeekly || shouldRefreshWeek(new Date(refWeekly * 1000), new Date())) { - refWeekly = nowSeconds(); - session.set('refWeekly', refWeekly); - session.push('refWeekly', () => {}); - await refDailyTaskBox(session.get('roleId'), session.get('sid')); - } - } -} \ No newline at end of file +import { FrontendOrBackendSession, pinus } from "pinus"; +import { shouldRefresh, shouldRefreshWeek } from '@pubUtils/util'; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { refDailyTask, refDailyTaskBox } from './task/taskService' +import { dispatch } from "@pubUtils/dispatcher"; +import { sendMessageToUserWithSuc } from "./pushService"; +import { PUSH_ROUTE } from "@consts"; +import { isDebugTime } from "@pubUtils/sdkUtil"; +import { redisClient } from "./redisService"; + +/** + * 刷新 + * @param session + */ +export async function refresh(session: FrontendOrBackendSession) { + const roleId = session.get('roleId')||'test'; + const sid = session.get('sid'); + + if(!isDebugTime()) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: Date.now() }, sid); + } else { + let guilds = pinus.app.getServersByType('guild'); + let guild = await dispatch(redisClient(), roleId, guilds, 'guild'); + let currentTime = await pinus.app.rpc.guild.guildActivityRemote.getCurrentTime.toServer(guild.id); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PUSH_CURRENT_TIME, { time: currentTime }, sid); + } + await refreshDaily(session); + // await startEvent(session); +} + +/** + * 每日刷新 + * @param session + */ +export async function refreshDaily(session: FrontendOrBackendSession) { + + if(session.get('roleId')) { + let refDaily: number = session.get('refDaily'); // 10位时间戳,每天每人更新一次 + let refWeekly: number = session.get('refWeekly'); // 10位时间戳,每天每人更新一次 + if(!refDaily || shouldRefresh(new Date(refDaily * 1000), new Date())) { + refDaily = nowSeconds(); + session.set('refDaily', refDaily); + session.push('refDaily', () => {}); + await refDailyTask(session.get('roleId'), session.get('sid')); + } + + if(!refWeekly || shouldRefreshWeek(new Date(refWeekly * 1000), new Date())) { + refWeekly = nowSeconds(); + session.set('refWeekly', refWeekly); + session.push('refWeekly', () => {}); + await refDailyTaskBox(session.get('roleId'), session.get('sid')); + } + } +} diff --git a/game-server/app/services/role/calCe.ts b/game-server/app/services/role/calCe.ts index 6b3313492..42b2fc15d 100644 --- a/game-server/app/services/role/calCe.ts +++ b/game-server/app/services/role/calCe.ts @@ -1,1508 +1,1508 @@ -import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, LINEUP_NUM, SEID_TYPE, TALENT_RELATION_TYPE } from "../../consts"; -import { ArtifactModelType } from "../../db/Artifact"; -import { AuthorBookType } from "../../db/AuthorBook"; -import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Stone, Talent } from "../../db/Hero"; -import { JewelType } from "../../db/Jewel"; -import { ResonanceType } from "../../db/Resonance"; -import { RoleUpdate, Teraph } from "../../db/Role"; -import { AttrCell, Attribute, EquipAttr, HeroAttr, RoleCeType, SchoolAttr, ScrollAttr } from "../../db/RoleCe"; -import { TopHero } from "../../domain/dbGeneral"; -import { AttributeCal } from "../../domain/roleField/attribute"; -import { gameData, getDicArtifactLvByPlanId, getDicAuthorBookSub, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "../../pubUtils/data"; -import { DicRandomEffectPool } from "../../pubUtils/dictionary/DicRandomEffectPool"; -import { DicSe } from "../../pubUtils/dictionary/DicSe"; -import { addToMap, deepCopy } from "../../pubUtils/util"; -export class CalCe { - roleId: string; - originCes: Map = new Map(); // hid => ce - resultCes: Map = new Map(); // hid => ce - data: CalCeData; - attrsByHid: Map = new Map(); - originTopHeroCe: number; - - constructor(roleId: string) { - this.roleId = roleId; - } - - public setRoleCe(roleCe: RoleCeType) { - this.data = new CalCeData(roleCe) - this.originCes = this.calHeroCe(); - this.originTopHeroCe = this.getTopLineup().topLineupCe; - } - - public clearRoleCe() { - this.data = new CalCeData(null); - } - - public getRoleCeTable() { - let attributes: Attribute[] = []; - for(let [hid, attrs] of this.attrsByHid) { - attributes.push({ hid, attrs }) - } - return this.data.getRoleCeTable(this.roleId, attributes); - } - - public calHeroCe() { - let attrs = new Map(); // hid => [{attrId, val}] - for(let [hid ] of this.data.heroAttrsByHid) { - let lv = this.data.heroLv.get(hid)||1; - for(let attrId = ABI_TYPE.ABI_HP; attrId < ABI_TYPE.ABI_MAX; attrId++) { - if(!this.data.heroAttrs.has(`${hid}_${attrId}`) && !this.data.globalAttrs.has(attrId)) continue; - let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0, artifactLv = 0, artifactQuality = 0, artifactSeid = 0, jewelBase = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{}; - let { school = 0, teraph = 0, title = 0, scroll = 0, skin = 0, authorBook = 0 } = this.data.getGlobalAttrById(attrId)||{}; - let val = 0, ceVal = 0, str = '', ceStr = ''; - if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { - // {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11 + hp14 - val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality + jewelBase + authorBook; - ceVal = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality + jewelBase + authorBook; - str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}+${jewelBase}+${authorBook}`; - ceStr += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}+${jewelBase}+${authorBook}`; - } else { - // attr1 + attr2 + attr4 + attr5 + attr6 + attr7 + attr9 + attr10 - val = subBase + job + teraph + school + title + jewel + equipStar + authorBook; - ceVal = job + teraph + school + title + jewel + equipStar + authorBook; - str += `${subBase}+${job}+${teraph}+${school}+${title}+${jewel}+${equipStar}+${authorBook}`; - ceStr += `${job}+${teraph}+${school}+${title}+${jewel}+${equipStar}+${authorBook}`; - } - if(!attrs.has(hid)) attrs.set(hid, []); - attrs.get(hid).push({ id: attrId, val, ceVal, str, ceStr }); - } - } - let result = new Map(); - for(let [hid, arr] of attrs) { - let lv = this.data.heroLv.get(hid)||1; - let obj = new AttributeCal(); - obj.setLv(lv); - obj.setByCeArr(arr); - let ce = obj.calCe(); - this.resultCes.set(hid, ce); - result.set(hid, ce); - this.attrsByHid.set(hid, arr); - } - return result; - } - - public calSingleGlobalPartCe(hid: number, field: 'teraph'|'scroll') { - let arr: { id: number, val: number }[] = []; - for(let [attrId, globalAttr] of this.data.globalAttrs) { - arr.push({ id: attrId, val: globalAttr[field]||0 }); - } - let lv = this.data.heroLv.get(hid)||1; - let obj = new AttributeCal(); - obj.setLv(lv); - obj.setByWarJson(hid, arr); - return obj.calCe(); - } - - public getCeInc() { - let ceResult = this.calHeroCe(); - // console.log('##### ceResult', ceResult, 'originCes', this.originCes) - let heroCe = new Map(); - let roleInc = 0; - for(let [hid, ce] of ceResult) { - let originCe = this.originCes.get(hid)||0; - if(ce != originCe) { - heroCe.set(hid, { inc: ce - originCe, origin: originCe, ce }); - roleInc += ce - originCe; - this.data.setHistoryCe(hid, ce); - } - } - return { heroCe, roleInc } - } - - public setResultHero(hero: HeroType) { - this.data.setResultHero(hero); - } - - public getResultCeArr() { - let arr: { hid: number, ce: number }[] = []; - for(let [ hid, ce ] of this.resultCes) { - arr.push({ hid, ce }); - } - arr.sort((a, b) => b.ce - a.ce); - return arr; - } - - public getTopLineup() { - let topLineup: TopHero[] = [], topLineupCe = 0; - let arr = this.getResultCeArr(); - for(let i = 0; i < LINEUP_NUM; i++) { - if(arr[i]) { - let { hid, ce } = arr[i]; - topLineup.push({ - hid, ce, hero: this.data.heroObjectId.get(hid) - }); - topLineupCe += ce; - } - } - return { topLineup, topLineupCe, hasTopCeChange: topLineupCe == this.originTopHeroCe }; - } - - public getTopLineupNew(dbResonanceMap: Map) { - let topLineup: TopHero[] = [], topLineupCe = 0; - let arr = this.getResultCeArr(); - for (let obj of arr) { - if (topLineup.length >= LINEUP_NUM) break; - let { hid, ce } = obj; - if (dbResonanceMap.has(hid)) continue; - topLineup.push({ - hid, ce, hero: this.data.heroObjectId.get(hid) - }); - topLineupCe += ce; - } - - return { topLineup, topLineupCe, hasTopCeChange: topLineupCe == this.originTopHeroCe }; - } - - - // 玩家等级 - public setRoleLv(lv: number) { - this.data.roleLv = lv; - } - - // 武将基础&成长 - public setHeroBase(hid: number, skinId: number) { - this.data.clearHeroAttrByHid(hid, 'mainBase'); - this.data.clearHeroAttrByHid(hid, 'mainBaseUp'); - let dicHero = gameData.hero.get(skinId); - - for(let [attrId, value] of dicHero.baseAbilityArr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.mainBase = value; - } - for(let [attrId, value] of dicHero.baseAbilityUpArr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.mainBaseUp = value; - } - } - - // 武将等级 - public setHeroLv(hid: number, lv: number) { - this.data.heroLv.set(hid, lv); - } - - // 星级相关 - public setHeroStar(hid: number, job: number, quality: number, star: number, starStage: number, colorStar: number, colorStarStage: number) { - this.data.clearHeroAttrByHid(hid, 'starUp'); - let dicHero = gameData.hero.get(hid); - let dicJob = gameData.job.get(job); - let jobClass = dicJob.job_class; - const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1 - const dicStar = isWake ? getHeroWakeByQuality(jobClass, dicHero.quality, colorStar) : getHeroStarByQuality(jobClass, quality, star); // 星级表 - const dicPreStar = isWake? getHeroWakeByQuality(jobClass, dicHero.quality, colorStar - 1): getHeroStarByQuality(jobClass, quality, star - 1); - let curStage = isWake? colorStarStage: starStage; - - for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) { - let attrId = ABI_STAGE_TO_TYPE.get(stage); - let value = 0; // 星级成长 - if(curStage >= stage) { - value = dicStar?.ceAttr.get(stage)||0; - } else { - value = dicPreStar?.ceAttr.get(stage)||0; - } - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.starUp = value; - }; - } - - // 职业基础 - public setJob(hid: number, job: number, jobStage: number) { - this.data.clearHeroAttrByHid(hid, 'job'); - const dicJob = gameData.job.get(job); - let ceAttr = dicJob.ceAttr.get(jobStage)||[]; - for(let { id, attr } of ceAttr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.job = attr; - } - for(let { id, val } of dicJob.baseSubAttr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.subBase = val; - } - } - - // 羁绊 - public setConnection(hid: number, connections: Connect[]) { - this.data.clearHeroAttrByHid(hid, 'connect'); - let map = new Map(); // attrId => val; - for(let { shipId, level = 0 } of connections) { - let currentShip = getFriendShipByIdAndLv(hid, shipId, level); - if (currentShip) { - for (let { id, number: val } of currentShip.attributes) { - if(!map.has(id)) { - map.set(id, val); - } else { - map.set(id, map.get(id) + val); - } - } - } - } - for(let [id, val] of map) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.connect = val; - } - } - - // 第一次获得皮肤 - public setAddSkin(skinId: number) { - let addSkin = gameData.fashion.get(skinId); - for (let { id, number: val } of addSkin.globalAttr) { - let globalAttr = this.data.getGlobalAttrById(id); - globalAttr.skin += val; - } - } - - // 天赋 - public setTalent(hid: number, skins: HeroSkin[]) { - this.data.clearHeroAttrByHid(hid, 'talent'); - let skin = skins.find(cur => cur.enable); - let seids = this.getTalentSeid(skin.talent); - let { ratioUp } = this.addSeidEffect(seids); - for(let [attrId, val] of ratioUp) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.talent = val; - } - } - - public getTalentSeid(talent: Talent[]) { - let seids = new Map(); // id, seids - for(let { id, level } of talent) { - let dicHeroTalent = gameData.heroTalent.get(id); - for(let { type, ids} of dicHeroTalent.relation) { - if(type == TALENT_RELATION_TYPE.REPLACE) { - for(let id of ids) { - seids.delete(id); - } - } - } - for(let { lv, seid } of dicHeroTalent.level) { - if(level == lv) { - if(!seids.has(id)) seids.set(id, []); - seids.get(id).push(seid, 0); - } - } - } - let result: number[] = []; - for(let [_, ids] of seids) { - result.push(...ids); - } - return result; - } - - // 装备升品 - public setEquipQuality(hid: number, eplaceId: number, equipId: number, quality: number, qualityStage: number) { - this.data.clearHeroAttrByHid(hid, 'equipQuality'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipQuality'); - let dicEquipQuality = getEquipQualityIdByEquipIdAndPoint(equipId, quality, qualityStage); - let map = new Map(); // attrId => val - for(let { id, num } of dicEquipQuality.attribute) { - if(!map.has(id)) { - map.set(id, num); - } else { - map.set(id, map.get(id) + num); - } - } - for(let [id, val] of map) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.equipQuality = val; - } - let equips = this.data.getEquipAttrsByHid(hid); - for(let { hid, attrId, equipQuality } of equips) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.equipQuality += equipQuality; - } - - } - - public clearEquip(hid: number) { - this.data.clearHeroAttrByHid(hid, 'equipQuality'); - this.data.clearEquipAttrByHid(hid, 'equipQuality'); - this.data.clearHeroAttrByHid(hid, 'equipStrength'); - this.data.clearEquipAttrByHid(hid, 'equipStrength'); - this.data.clearHeroAttrByHid(hid, 'equipStar'); - this.data.clearEquipAttrByHid(hid, 'equipStar'); - this.data.clearHeroAttrByHid(hid, 'jewel'); - this.data.clearHeroAttrByHid(hid, 'jewelBase'); - this.data.clearEquipAttrByHid(hid, 'jewel'); - this.data.clearEquipAttrByHid(hid, 'jewelBase'); - this.data.clearHeroAttrByHid(hid, 'stone'); - this.data.clearEquipAttrByHid(hid, 'stone'); - } - - // 装备强化 - public setEquipStrength(hid: number, eplaceId: number, equipId: number, lv: number) { - this.data.clearHeroAttrByHid(hid, 'equipStrength'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipStrength'); - let dicEquipStrenth = getEquipStrenthenAttr(equipId, lv); - let map = new Map(); // attrId => val - for(let { id, num } of dicEquipStrenth.attr) { - if(!map.has(id)) { - map.set(id, num); - } else { - map.set(id, map.get(id) + num); - } - } - for(let [id, val] of map) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.equipStrength = val; - } - let equips = this.data.getEquipAttrsByHid(hid); - for(let { hid, attrId, equipStrength } of equips) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.equipStrength += equipStrength; - } - } - - // 装备精炼(升星) - public setEquipStar(hid: number, eplaceId: number, equipId: number, star: number, starStage: number) { - this.data.clearHeroAttrByHid(hid, 'equipStar'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipStar'); - let dicEquipStar = getEquipStarAttrByStage(equipId, star, starStage); - if(dicEquipStar) { - let { mainAttr, subAttr } = dicEquipStar; - let map = new Map(); // attrId => val - for(let { id, num } of [...mainAttr, ...subAttr]) { - if(!map.has(id)) { - map.set(id, num); - } else { - map.set(id, map.get(id) + num); - } - } - for(let [id, val] of map) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.equipStar = val; - } - let equips = this.data.getEquipAttrsByHid(hid); - for(let { hid, attrId, equipStar } of equips) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.equipStar += equipStar; - } - } - } - - // 装备套装 - public setEquipSuit(hid: number, skinId: number, ePlace: EPlace[]) { - this.data.clearHeroAttrByHid(hid, 'equipSuit'); - let dicEquipSuit = getEquipSuitByHero(skinId); - let suitStars: number[] = []; - for(let equipId of dicEquipSuit.equips) { - let equip = ePlace.find(cur => cur.equipId == equipId); - suitStars.push(equip? equip.star: 0); - } - let minStar = Math.min(...suitStars); - - for(let { star, id, val } of dicEquipSuit.effect) { - if(minStar >= star) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.equipSuit = val; - } - } - } - - // 天晶 - public setJewel(hid: number, eplaceId: number, stones: Stone[], jewel: JewelType) { - this.data.clearHeroAttrByHid(hid, 'jewel'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'jewel'); - this.data.clearHeroAttrByHid(hid, 'jewelBase'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'jewelBase'); - let seids: number[] = []; - if(jewel) { - for(let { id, seid, rand } of jewel.randSe) { - if(this.isRandSeUnLock(jewel.id, id, stones)) { - seids.push(seid, rand); - } - } - for(let { seid, rand } of jewel.rareSe) { - seids.push(seid, rand); - } - let dicJewel = gameData.jewel.get(jewel.id); - if(dicJewel) { - let attrBaseValues = dicJewel.rareEffectBaseAttr||[]; - for(let { id, num } of attrBaseValues) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.jewelBase = num; - } - } - } - let { ratioUp } = this.addSeidEffect(seids); - let map = new Map(); // attrId => val - for(let [id, num] of ratioUp) { - if(!map.has(id)) { - map.set(id, num); - } else { - map.set(id, map.get(id) + num); - } - } - for(let [id, val] of map) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.jewel = val; - } - let equips = this.data.getEquipAttrsByHid(hid); - for(let { hid, attrId, jewel, jewelBase } of equips) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.jewel += jewel; - heroAttr.jewelBase += jewelBase; - } - } - - public isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[]) { - let dicJewel = gameData.jewel.get(jewelId); - let dicJewelCondition = getJewelConditionByLvAndSeId(dicJewel.lv, randSeId); - let stoneCnt = 0, stoneLv = 0; - for(let { stone } of stones) { - let dicStone = gameData.stone.get(stone); - if(dicStone) { - stoneCnt++; - stoneLv += dicStone.lv; - } - } - return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv; - } - - // 地玉 - public setStone(hid: number, eplaceId: number, stones: Stone[]) { - this.data.clearHeroAttrByHid(hid, 'stone'); - this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'stone'); - let map = new Map(); // attrId => val - for(let { stone } of stones) { - let dicStone = gameData.stone.get(stone); - if(dicStone) { - for(let { id, num } of dicStone.attribute) { - if(!map.has(id)) { - map.set(id, num); - } else { - map.set(id, map.get(id) + num); - } - } - } - } - for(let [id, val] of map) { - let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); - equipAttr.stone = val; - } - let equips = this.data.getEquipAttrsByHid(hid); - for(let { hid, attrId, stone } of equips) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.stone += stone; - } - } - - - // 爵位 - public setTitle(title: number) { - this.data.clearRoleAttr('title'); - let dicTitle = gameData.title.get(title)||{ mainAttrValue: new Map(), assiAttrValue: new Map() }; - for(let [attrId, value] of dicTitle.mainAttrValue) { - let globalAttr = this.data.getGlobalAttrById(attrId); - globalAttr.title = value; - } - for(let [attrId, value] of dicTitle.assiAttrValue) { - let globalAttr = this.data.getGlobalAttrById(attrId); - globalAttr.title = value; - } - } - - // 神像相关 - public setTeraph(teraphs: Teraph[]) { - - this.data.clearRoleAttr('teraph'); - let teraphOfAttrId = new Map(); - for(let teraph of teraphs) { - let dicTeraph = getTeraph(teraph.id, teraph.grade); - for(let [attrId, value] of teraph.attr) { // 主属性 - let basic = dicTeraph.basicAttrValue.get(attrId)||0; - addToMap(teraphOfAttrId, attrId, value + basic); - } - for(let [attrId, value] of dicTeraph.assiAttrValue) { // 次属性 - addToMap(teraphOfAttrId, attrId, value); - } - } - for(let [attrId, value] of teraphOfAttrId) { - let globalAttr = this.data.getGlobalAttrById(attrId); - globalAttr.teraph = value; - } - } - - // 名将谱 - public setScroll(hid: number, scrollStar: number, scrollQuality: number, scrollColorStar: number) { - this.data.clearScrollAttr(hid); - let dicHero =gameData.hero.get(hid); - let dicHeroScroll = getScollByStar(dicHero.quality, scrollStar, scrollQuality, scrollColorStar); - - if(dicHeroScroll) { - for(let [attrId, value] of dicHeroScroll.ceAttr) { - this.data.setScrollAttrs(hid, attrId, value); - this.data.calScrollAttrsToGlobal(attrId); - } - } - } - - // 百家学宫 - public setSchool(isPutOn: boolean, hid: number, schoolId: number, star: number, colorStar: number, quality: number) { - this.data.clearSchoolAttr(hid); - let dicSchool = gameData.school.get(schoolId); - let dicSchoolRate = getSchoolRateByStar(star, colorStar, quality); - - for (let attrId of dicSchool.upAttribute) { - if(ABI_TYPE_MAIN.includes(attrId)) { // 主属性 - this.data.setSchoolAttrs(hid, attrId, isPutOn?dicSchoolRate.mainAttrAPerent: 0); - } else { - this.data.setSchoolAttrs(hid, attrId, isPutOn?dicSchoolRate.assiAttrAddValue: 0); - } - this.data.calSchoolAttrsToGlobal(attrId); - } - } - - // 卸下宝物 - public setPutOffArtifact(hid: number) { - this.data.clearHeroAttrByHid(hid, 'artifactLv'); - this.data.clearHeroAttrByHid(hid, 'artifactQuality'); - this.data.clearHeroAttrByHid(hid, 'artifactSeid'); - } - - // 装备宝物 - public setPutArtifact(hid: number, skinId: number, job: number, artifact: ArtifactModelType) { - this.data.clearHeroAttrByHid(hid, 'artifactLv'); - this.data.clearHeroAttrByHid(hid, 'artifactQuality'); - this.data.clearHeroAttrByHid(hid, 'artifactSeid'); - - if(artifact) { - this.setArtifactLv(hid, artifact.artifactId, artifact.lv); - this.setArtifactQuality(hid, artifact.artifactId); - this.setArtifactSeid(hid, skinId, job, artifact.artifactId); - } - } - - // 宝物等级 - public setArtifactLv(hid: number, artifactId: number, lv: number) { - this.data.clearHeroAttrByHid(hid, 'artifactLv'); - let dicArtifact = gameData.artifact.get(artifactId); - if(!dicArtifact) return; - - let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); - if(!dicArtifactLv) return; - - let ceAttr = dicArtifactLv.attr||[]; - for(let { id, attr } of ceAttr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.artifactLv = attr; - } - } - - // 诸子列传属性 - public setAuthorBooks(authorBooks: AuthorBookType[]) { - - this.data.clearRoleAttr('authorBook'); - let attrResult = new Map(); - for(let { bookId, progress, authors } of authorBooks) { - // 升星的属性 - for(let { subId, star } of authors) { - let dicAuthorBook = getDicAuthorBookSub(bookId, subId, star); - if(dicAuthorBook) { - for(let {id, val} of dicAuthorBook.attr) addToMap(attrResult, id, val); - } - } - - let dicPoints = gameData.authorBookPoint.get(bookId)||[]; - for(let { value, attr } of dicPoints) { - if(progress >= value) { - for(let { id, val } of attr) addToMap(attrResult, id, val); - } - } - } - - for(let [attrId, value] of attrResult) { - let globalAttr = this.data.getGlobalAttrById(attrId); - globalAttr.authorBook = value; - } - } - - // 宝物品质 - public setArtifactQuality(hid: number, artifactId: number) { - this.data.clearHeroAttrByHid(hid, 'artifactQuality'); - - let dicArtifact = gameData.artifact.get(artifactId); - if(!dicArtifact) return; - - // 基础属性 - let dicArtifactQualityPlan = gameData.artifactQualityPlan.get(dicArtifact.qualityAttrPlan); - if(!dicArtifactQualityPlan) return; - - let ceAttr = dicArtifactQualityPlan.attr||[]; - for(let { id, attr } of ceAttr) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); - heroAttr.artifactQuality = attr; - } - } - - // 宝物词条 - public setArtifactSeid(hid: number, skinId: number, job: number, artifactId: number) { - this.data.clearHeroAttrByHid(hid, 'artifactSeid'); - - let dicArtifact = gameData.artifact.get(artifactId); - if(!dicArtifact) return; - let dicJob = gameData.job.get(job); - if(!dicJob) return; - - let seids: number[] = []; // id, seids - for(let seid of dicArtifact.seids) { - let dicArtifactSeid = gameData.artifactSeid.get(seid); - if(!dicArtifactSeid) continue; - if(dicArtifactSeid.jobClass != 0 && dicArtifactSeid.jobClass != dicJob.job_class) continue; - if(dicArtifactSeid.hids.length > 0 && dicArtifactSeid.hids.indexOf(skinId) == -1) continue; - if(dicArtifactSeid.quality > dicArtifact.quality) continue; - for(let seid of dicArtifactSeid.seids) { - seids.push(seid, 0); - } - } - - let { ratioUp } = this.addSeidEffect(seids); - for(let [attrId, val] of ratioUp) { - let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); - heroAttr.artifactSeid = val; - } - } - - // 添加技能增加的被动属性 - private addSeidEffect(seidList: number[]) { - let fixUp = new Map(), ratioUp = new Map(); - let effectList: DicSe[] = []; // any: dic_zyz_se表内容 - - for (let ii = 0; ii < seidList.length; ii += 2) { - let seid = seidList[ii]; - let rand = seidList[ii + 1] || 0; - let dicSeid: DicSe | DicRandomEffectPool = gameData.se.get(seid); - if (!dicSeid) dicSeid = gameData.randomEffectPool.get(seid); - if (dicSeid && dicSeid.id > 0) { - this.addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr) - } - } - - // console.log('effectList', JSON.stringify(effectList)); - for (let { type, id, gainValueArr: [ability, value] } of effectList) { - // console.log('##### addToMap type', type, 'id', id, 'ability', ability, 'value', value) - if (type == SEID_TYPE.FIX) { // 加值 - addToMap(fixUp, ability, value); - } else if (type == SEID_TYPE.MAIN_RATIO||type == SEID_TYPE.MAIN_RATIO_2) { // 主属性加百分比 - if(ABI_TYPE_MAIN.includes(ability)) { - addToMap(ratioUp, ability, value); - } - } else if (type == SEID_TYPE.SUB_RATIO||type == SEID_TYPE.SUB_RATIO_2) { // 次级属性加百分比 - if(!ABI_TYPE_MAIN.includes(ability)) { - addToMap(ratioUp, ability, value); - } - } - - } - return { fixUp, ratioUp }; - } - - // 获取dic_zyz_se内容 - private addSeid(effectList: (DicSe | DicRandomEffectPool)[], seidId: number, rand: number, seidValue: number[] = []) { - let curSeid: DicSe | DicRandomEffectPool = gameData.se.get(seidId); - if (!curSeid) curSeid = gameData.randomEffectPool.get(seidId); - if (!curSeid) { console.log("seidId not found:" + seidId); return; } - if (!seidValue) seidValue = curSeid.gainValueArr; - - if (curSeid.type === SEID_TYPE.MIX) { - for (let i = 0; i < seidValue.length; i++) { - this.addSeid(effectList, seidValue[i], rand); - } - return; - } - let seid: DicSe | DicRandomEffectPool = deepCopy(curSeid); - if (curSeid.index > 0) { - seid.gainValueArr[curSeid.index - 1] = rand; - } - effectList.push(seid); - } -} - -class CalCeData { - roleLv: number = 1; // 玩家等级 - // 全局 - globalAttrs: Map = new Map(); // attrId => GlobalAttr - // 武将 - heroAttrs: Map = new Map(); // hid+attrId => HeroAttr - heroAttrsByHid: Map = new Map(); // hid => [hid+attrId] - heroLv: Map = new Map(); - heroHistoryCe: Map = new Map(); - heroObjectId: Map = new Map(); - // 装备 - equipAttrs: Map = new Map(); // hid+eplaceId+attrId => EquipAttr - equipAttrsByHid: Map = new Map(); // hid => [hid+eplaceId+attrId] - equipAttrsByHidAndEplace: Map = new Map(); // hid+eplaceId =>[hid+eplaceId+attrId] - equipAttrsByHidAndAttrId: Map = new Map(); // hid+attrId =>[hid+eplaceId+attrId] - equipLv: Map = new Map(); // hid+eplaceId => lv - // 百家学宫 - schoolAttrs: Map = new Map(); // hid + attr => ratio - schoolAttrsByAttrId: Map = new Map(); // attrId => hid + attr - schoolAttrsByHid: Map = new Map(); // hid => hid + attr - // 名将谱 - scrollAttrs: Map = new Map(); // hid + attr => ratio - scrollAttrsByAttrId: Map = new Map(); // attrId => hid + attr - scrollAttrsByHid: Map = new Map(); // hid => hid + attr - - constructor(roleCe: RoleCeType) { - if(roleCe) { - this.roleLv = roleCe.roleLv; - for(let globalAttr of roleCe.globalAttrs) { - let obj = this.getGlobalAttrById(globalAttr.attrId); - obj.setByRoleCe(globalAttr); - } - for(let {hid, lv, attrs, historyCe, objectId } of roleCe.heroAttrs) { - this.heroLv.set(hid, lv); - this.heroHistoryCe.set(hid, historyCe); - this.heroObjectId.set(hid, objectId); - for(let cell of attrs) { - let obj = this.getHeroAttrByHidAndId(hid, cell.attrId); - obj.setByRoleCe(cell); - } - } - for(let { hid, eplaceId, lv, attrs } of roleCe.equipAttrs) { - this.equipLv.set(`${hid}_${eplaceId}`, lv); - for(let cell of attrs) { - let obj = this.getEquipAttrByHidAndId(hid, eplaceId, cell.attrId); - obj.setByRoleCe(cell); - } - } - for(let { hid, attrId, value } of roleCe.schoolAttrs) { - this.setSchoolAttrs(hid, attrId, value); - } - for(let { hid, attrId, value } of roleCe.scrollAttrs) { - this.setScrollAttrs(hid, attrId, value); - } - } - } - - public getGlobalAttrById(attrId: number) { - if(!this.globalAttrs.has(attrId)) { - if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { - let obj = new GlobalMainAttr(attrId); - this.globalAttrs.set(attrId, obj); - } else { - let obj = new GlobalSubAttr(attrId); - this.globalAttrs.set(attrId, obj); - } - } - return this.globalAttrs.get(attrId); - } - - public clearRoleAttr(field: string) { - for(let [_attrId, globalAttr] of this.globalAttrs) { - globalAttr[field] = 0; - } - } - - public getHeroAttrsByHid(hid: number) { - let keys = this.heroAttrsByHid.get(hid)||[]; - return keys.map(key => this.heroAttrs.get(key)); - } - - public getHeroAttrByHidAndId(hid: number, attrId: number) { - let key = `${hid}_${attrId}`; - if(!this.heroAttrs.has(key)) { - if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { - let obj = new HeroMainAttr(hid, attrId); - this.heroAttrs.set(key, obj); - } else { - let obj = new HeroSubAttr(hid, attrId); - this.heroAttrs.set(key, obj); - } - - if(!this.heroAttrsByHid.has(hid)) { - this.heroAttrsByHid.set(hid, []); - } - this.heroAttrsByHid.get(hid).push(key); - } - return this.heroAttrs.get(key); - } - - public clearHeroAttrByHid(hid: number, field: string) { - let heroAttrs = this.getHeroAttrsByHid(hid)||[]; - for(let heroAttr of heroAttrs) { - heroAttr[field] = 0; - } - } - - public getEquipAttrByHidAndId(hid: number, eplaceId: number, attrId: number) { - let key = `${hid}_${eplaceId}_${attrId}`; - if(!this.equipAttrs.has(key)) { - if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { - let obj = new EquipMainAttr(hid, attrId); - this.equipAttrs.set(key, obj); - } else { - let obj = new EquipSubAttr(hid, attrId); - this.equipAttrs.set(key, obj); - } - - if(!this.equipAttrsByHid.has(hid)) { - this.equipAttrsByHid.set(hid, []); - } - this.equipAttrsByHid.get(hid).push(key); - let key2 = `${hid}_${eplaceId}`; - if(!this.equipAttrsByHidAndEplace.has(key2)) { - this.equipAttrsByHidAndEplace.set(key2, { hid, eplaceId, keys: []}); - } - this.equipAttrsByHidAndEplace.get(key2).keys.push(key); - } - return this.equipAttrs.get(key); - } - - public getEquipAttrsByHid(hid: number) { - let keys = this.equipAttrsByHid.get(hid)||[]; - return keys.map(key => this.equipAttrs.get(key)); - } - - public getEquipAttrsByHidAndEplace(hid: number, eplaceId: number) { - let key2 = `${hid}_${eplaceId}`; - if(!this.equipAttrsByHidAndEplace.has(key2)) return [] - let { keys } = this.equipAttrsByHidAndEplace.get(key2); - return keys.map(key => this.equipAttrs.get(key)); - } - - public clearEquipAttrByHidAndEplace(hid: number, eplaceId: number, field: string) { - let equipAttrs = this.getEquipAttrsByHidAndEplace(hid, eplaceId); - for(let equipAttr of equipAttrs) { - equipAttr[field] = 0; - } - } - - public clearEquipAttrByHid(hid: number, field: string) { - let equipAttrs = this.getEquipAttrsByHid(hid); - for(let equipAttr of equipAttrs) { - equipAttr[field] = 0; - } - } - - public setSchoolAttrs(hid: number, attrId: number, value: number) { - let key = `${hid}_${attrId}`; - if(!this.schoolAttrs.has(key)) { - this.schoolAttrs.set(key, { hid, attrId, ce: value }); - if(!this.schoolAttrsByAttrId.has(attrId)) { - this.schoolAttrsByAttrId.set(attrId, []); - } - this.schoolAttrsByAttrId.get(attrId).push(key); - if(!this.schoolAttrsByHid.has(hid)) { - this.schoolAttrsByHid.set(hid, []); - } - this.schoolAttrsByHid.get(hid).push(key); - } else { - this.schoolAttrs.get(key).ce = value; - } - } - - public getSchoolAttrsByHid(hid: number) { - let keys = this.schoolAttrsByHid.get(hid)||[]; - return keys.map(key => this.schoolAttrs.get(key)); - } - - public calSchoolAttrsToGlobal(attrId: number) { - let keys = this.schoolAttrsByAttrId.get(attrId)||[]; - let schoolResult = 0; - for(let key of keys) { - let { ce } = this.schoolAttrs.get(key); - schoolResult += ce; - } - let globalAttr = this.getGlobalAttrById(attrId); - globalAttr.school = schoolResult; - } - - public clearSchoolAttr(hid: number) { - let schoolAttrs = this.getSchoolAttrsByHid(hid)||[]; - for(let schoolAttr of schoolAttrs) { - schoolAttr.ce = 0; - this.calSchoolAttrsToGlobal(schoolAttr.attrId); - } - } - - public setScrollAttrs(hid: number, attrId: number, value: number) { - let key = `${hid}_${attrId}`; - if(!this.scrollAttrs.has(key)) { - this.scrollAttrs.set(key, { hid, attrId, ce: value }); - if(!this.scrollAttrsByAttrId.has(attrId)) { - this.scrollAttrsByAttrId.set(attrId, []); - } - this.scrollAttrsByAttrId.get(attrId).push(key); - if(!this.scrollAttrsByHid.has(hid)) { - this.scrollAttrsByHid.set(hid, []); - } - this.scrollAttrsByHid.get(hid).push(key); - } else { - this.scrollAttrs.get(key).ce = value; - } - } - - public calScrollAttrsToGlobal(attrId: number) { - let keys = this.scrollAttrsByAttrId.get(attrId)||[]; - let result = 0; - for(let key of keys) { - let { ce } = this.scrollAttrs.get(key); - result += ce; - } - let globalAttr = this.getGlobalAttrById(attrId); - globalAttr.scroll = result; - } - - public clearScrollAttr(hid: number) { - let scrollAttrs = this.getScrollAttrsByHid(hid); - for(let scrollAttr of scrollAttrs) { - scrollAttr.ce = 0; - this.calScrollAttrsToGlobal(scrollAttr.attrId); - } - } - - public getScrollAttrsByHid(hid: number) { - let keys = this.scrollAttrsByHid.get(hid)||[]; - return keys.map(key => this.scrollAttrs.get(key)); - } - - public setHistoryCe(hid: number, ce: number) { - let historyCe = this.heroHistoryCe.get(hid)||0; - if(ce > historyCe) { - this.heroHistoryCe.set(hid, ce); - } - } - - public setResultHero(hero: HeroType) { - this.heroObjectId.set(hero.hid, hero._id); - } - - public getRoleCeTable(roleId: string, attributes: Attribute[]) { - let globalAttrs: AttrCell[] = []; - for(let [_, globalAttr] of this.globalAttrs) { - globalAttrs.push(globalAttr.getGlobalAttr()); - } - let heroAttrs: HeroAttr[] = []; - for(let [hid, keys] of this.heroAttrsByHid) { - let lv = this.heroLv.get(hid); - let historyCe = this.heroHistoryCe.get(hid)||0; - let objectId = this.heroObjectId.get(hid); - let attrs: AttrCell[] = []; - for(let key of keys) { - let heroAttr = this.heroAttrs.get(key); - attrs.push(heroAttr.getHeroAttrCell()); - } - heroAttrs.push({ - hid, lv, attrs, historyCe, objectId - }); - } - let equipAttrs: EquipAttr[] = []; - for(let [key2, { hid, eplaceId, keys }] of this.equipAttrsByHidAndEplace) { - let lv = this.equipLv.get(key2); - let attrs: AttrCell[] = []; - for(let key of keys) { - let equipAttr = this.equipAttrs.get(key); - attrs.push(equipAttr.getEquipAttrCell()); - } - equipAttrs.push({ - hid, eplaceId, lv, attrs - }); - } - let schoolAttrs: SchoolAttr[] = []; - for(let [_, { hid, attrId, ce }] of this.schoolAttrs) { - schoolAttrs.push({ hid, attrId, value: ce }); - } - let scrollAttrs: ScrollAttr[] = []; - for(let [_, { hid, attrId, ce }] of this.scrollAttrs) { - scrollAttrs.push({ hid, attrId, value: ce }); - } - return { - roleLv: this.roleLv, roleId, globalAttrs, heroAttrs, equipAttrs, schoolAttrs, scrollAttrs, attributes - } - } -} - -abstract class GlobalAllAttr { - attrId: number; - school: number = 0; - teraph: number = 0; - title: number = 0; - scroll: number = 0; - skin: number = 0; - authorBook: number = 0; - - constructor(attrId: number) { - this.attrId = attrId; - } - - abstract setByRoleCe(data: AttrCell): void; - abstract getValues(): number[]; - - public getGlobalAttr() { - let values = this.getValues().map(cur => (cur||0)); - return { - attrId: this.attrId, - values - } - } -} - -class GlobalMainAttr extends GlobalAllAttr { - - public setByRoleCe(globalAttr: AttrCell) { - for(let i = 0; i < globalAttr.values.length; i++) { - let value = globalAttr.values[i]; - if(value != undefined) { - switch(i) { - case GLOBAL_MAIN_ATTR_INDEX.SCHOOL: - this.school = value; break; - case GLOBAL_MAIN_ATTR_INDEX.TERAPH: - this.teraph = value; break; - case GLOBAL_MAIN_ATTR_INDEX.TITLE: - this.title = value; break; - case GLOBAL_MAIN_ATTR_INDEX.SCROLL: - this.scroll = value; break; - case GLOBAL_MAIN_ATTR_INDEX.SKIN: - this.skin = value; break; - case GLOBAL_MAIN_ATTR_INDEX.AUTH_BOOK: - this.authorBook = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = GLOBAL_MAIN_ATTR_INDEX.START; i < GLOBAL_MAIN_ATTR_INDEX.END; i++) { - switch(i) { - case GLOBAL_MAIN_ATTR_INDEX.SCHOOL: - values.push(this.school); - break; - case GLOBAL_MAIN_ATTR_INDEX.TERAPH: - values.push(this.teraph); - break; - case GLOBAL_MAIN_ATTR_INDEX.TITLE: - values.push(this.title); - break; - case GLOBAL_MAIN_ATTR_INDEX.SCROLL: - values.push(this.scroll); - break; - case GLOBAL_MAIN_ATTR_INDEX.SKIN: - values.push(this.skin); - break; - case GLOBAL_MAIN_ATTR_INDEX.AUTH_BOOK: - values.push(this.authorBook); - break; - } - } - return values; - } -} - -class GlobalSubAttr extends GlobalAllAttr { - - public setByRoleCe(globalAttr: AttrCell) { - for(let i = 0; i < globalAttr.values.length; i++) { - let value = globalAttr.values[i]; - if(value != undefined) { - switch(i) { - case GLOBAL_SUB_ATTR_INDEX.SCHOOL: - this.school = value; break; - case GLOBAL_SUB_ATTR_INDEX.TERAPH: - this.teraph = value; break; - case GLOBAL_SUB_ATTR_INDEX.TITLE: - this.title = value; break; - case GLOBAL_SUB_ATTR_INDEX.SKIN: - this.skin = value; break; - case GLOBAL_SUB_ATTR_INDEX.AUTH_BOOK: - this.authorBook = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = GLOBAL_SUB_ATTR_INDEX.START; i < GLOBAL_SUB_ATTR_INDEX.END; i++) { - switch(i) { - case GLOBAL_SUB_ATTR_INDEX.SCHOOL: - values.push(this.school); - break; - case GLOBAL_SUB_ATTR_INDEX.TERAPH: - values.push(this.teraph); - break; - case GLOBAL_SUB_ATTR_INDEX.TITLE: - values.push(this.title); - break; - case GLOBAL_SUB_ATTR_INDEX.SKIN: - values.push(this.skin); - break; - case GLOBAL_SUB_ATTR_INDEX.AUTH_BOOK: - values.push(this.authorBook); - break; - } - } - return values; - } -} - -abstract class HeroAllAttr { - hid: number; - attrId: number; - mainBase: number = 0; // hp1,武将基础属性(dic_zyz_hero的hp) - subBase: number = 0; // attr1,职业基础(dic_zyz_job的baseSubAttr字段) - job: number = 0; // hp1 & attr2, 职业属性(dic_zyz_job的attr) - starUp: number = 0; // hp2, 角色升星成长(dic_zyz_hero_star的hp或dic_zyz_hero_wake的hp) - connect: number = 0; // hp3, 角色羁绊固定值(dic_zyz_friend_ship的attribute) - favour: number = 0; // 删除-hp4, 声望加成(dic_zyz_friend_ship_level的add) - talent: number = 0; // hp5 & attr3, 天赋树百分比加成(dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) - equipQuality: number = 0; // hp6, 装备品质基础值(dic_zyz_equipQuality的attribute) - equipStrength: number = 0; // hp7, 装备强化值(dic_zyz_equipStrenthAttr的attr) - equipStar: number = 0; // hp8 & attr9,装备升星(dic_zyz_equipStar的mainAttr和subAttr) - equipSuit: number = 0; // hp8,套装(dic_zyz_equipSuit的effect,然后对应dic_zyz_se) - jewel: number = 0; // hp9 & attr7,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool) - stone: number = 0; // hp10, 地玉增加的固定值(dic_zyz_stone的attribute) - mainBaseUp: number = 0; // hp2, 基础成长(dic_zyz_hero的hp_up) - artifactLv: number = 0; // hp14 宝物等级(dic_zyz_artifactLvPlan的attr) - artifactQuality: number = 0; // hp14 宝物品质(dic_zyz_artifactQualityPlan的attr) - artifactSeid: number = 0; // hp9 宝物词条(dic_zyz_artifactSeid算出来的) - jewelBase: number = 0; // hp15 天晶固定属性值(jewel的基础属性) - - constructor(hid: number, attrId: number, ) { - this.hid = hid; - this.attrId = attrId; - - } - - abstract setByRoleCe(data: AttrCell): void; - abstract getValues(): number[]; - - public getHeroAttrCell() { - return { - attrId: this.attrId, - values: this.getValues() - } - } -} - -class HeroMainAttr extends HeroAllAttr { - public setByRoleCe(heroAttr: AttrCell) { - for(let i = 0; i < heroAttr.values.length; i++) { - let value = heroAttr.values[i]; - if(value != undefined) { - switch(i) { - case HERO_MAIN_ATTR_INDEX.BASE: - this.mainBase = value; break; - case HERO_MAIN_ATTR_INDEX.JOB: - this.job = value; break; - case HERO_MAIN_ATTR_INDEX.STAR_UP: - this.starUp = value; break; - case HERO_MAIN_ATTR_INDEX.CONNECT: - this.connect = value; break; - case HERO_MAIN_ATTR_INDEX.FAVOUR: - this.favour = value; break; - case HERO_MAIN_ATTR_INDEX.TALENT: - this.talent = value; break; - case HERO_MAIN_ATTR_INDEX.EQUIP_QUALITY: - this.equipQuality = value; break; - case HERO_MAIN_ATTR_INDEX.EQUIP_STRENGTH: - this.equipStrength = value; break; - case HERO_MAIN_ATTR_INDEX.EQUIP_STAR: - this.equipStar = value; break; - case HERO_MAIN_ATTR_INDEX.EQUIP_SUIT: - this.equipSuit = value; break; - case HERO_MAIN_ATTR_INDEX.JEWEL: - this.jewel = value; break; - case HERO_MAIN_ATTR_INDEX.STONE: - this.stone = value; break; - case HERO_MAIN_ATTR_INDEX.BASE_UP: - this.mainBaseUp = value; break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV: - this.artifactLv = value; break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY: - this.artifactQuality = value; break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID: - this.artifactSeid = value; break; - case HERO_MAIN_ATTR_INDEX.JEWEL_BASE: - this.jewelBase = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = HERO_MAIN_ATTR_INDEX.START; i < HERO_MAIN_ATTR_INDEX.END; i++) { - switch(i) { - case HERO_MAIN_ATTR_INDEX.BASE: - values.push(this.mainBase); - break; - case HERO_MAIN_ATTR_INDEX.JOB: - values.push(this.job); - break; - case HERO_MAIN_ATTR_INDEX.STAR_UP: - values.push(this.starUp); - break; - case HERO_MAIN_ATTR_INDEX.CONNECT: - values.push(this.connect); - break; - case HERO_MAIN_ATTR_INDEX.FAVOUR: - values.push(this.favour); - break; - case HERO_MAIN_ATTR_INDEX.TALENT: - values.push(this.talent); - break; - case HERO_MAIN_ATTR_INDEX.EQUIP_QUALITY: - values.push(this.equipQuality); - break; - case HERO_MAIN_ATTR_INDEX.EQUIP_STRENGTH: - values.push(this.equipStrength); - break; - case HERO_MAIN_ATTR_INDEX.EQUIP_STAR: - values.push(this.equipStar); - break; - case HERO_MAIN_ATTR_INDEX.EQUIP_SUIT: - values.push(this.equipSuit); - break; - case HERO_MAIN_ATTR_INDEX.JEWEL: - values.push(this.jewel); - break; - case HERO_MAIN_ATTR_INDEX.STONE: - values.push(this.stone); - break; - case HERO_MAIN_ATTR_INDEX.BASE_UP: - values.push(this.mainBaseUp); - break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV: - values.push(this.artifactLv); - break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY: - values.push(this.artifactQuality); - break; - case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID: - values.push(this.artifactSeid); - break; - case HERO_MAIN_ATTR_INDEX.JEWEL_BASE: - values.push(this.jewelBase); - break; - } - } - return values; - } -} - -class HeroSubAttr extends HeroAllAttr { - public setByRoleCe(heroAttr: AttrCell) { - for(let i = 0; i < heroAttr.values.length; i++) { - let value = heroAttr.values[i]; - if(value != undefined) { - switch(i) { - case HERO_SUB_ATTR_INDEX.BASE: - this.subBase = value; break; - case HERO_SUB_ATTR_INDEX.JOB: - this.job = value; break; - case HERO_SUB_ATTR_INDEX.TALENT: - this.talent = value; break; - case HERO_SUB_ATTR_INDEX.JEWEL: - this.jewel = value; break; - case HERO_SUB_ATTR_INDEX.EQUIP_STAR: - this.equipStar = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = HERO_SUB_ATTR_INDEX.START; i < HERO_SUB_ATTR_INDEX.END; i++) { - switch(i) { - case HERO_SUB_ATTR_INDEX.BASE: - values.push(this.subBase); - break; - case HERO_SUB_ATTR_INDEX.JOB: - values.push(this.job); - break; - case HERO_SUB_ATTR_INDEX.TALENT: - values.push(this.talent); - break; - case HERO_SUB_ATTR_INDEX.JEWEL: - values.push(this.jewel); - break; - case HERO_SUB_ATTR_INDEX.EQUIP_STAR: - values.push(this.equipStar); - break; - } - } - return values; - } -} - -abstract class EquipAllAttr { - hid: number; - eplaceId: number; - attrId: number; - equipQuality: number = 0; - equipStrength: number = 0; - equipStar: number = 0; - jewel: number = 0; - stone: number = 0; - jewelBase: number = 0; - - constructor(hid: number, attrId: number) { - this.hid = hid; - this.attrId = attrId; - } - - abstract setByRoleCe(data: AttrCell): void; - abstract getValues(): number[]; - - public getEquipAttrCell() { - return { - attrId: this.attrId, - values: this.getValues() - } - } -} - -class EquipMainAttr extends EquipAllAttr { - public setByRoleCe(equipAttr: AttrCell) { - for(let i = 0; i < equipAttr.values.length; i++) { - let value = equipAttr.values[i]; - if(value != undefined) { - switch(i) { - case EQUIP_MAIN_ATTR_INDEX.EQUIP_QUALITY: - this.equipQuality = value; break; - case EQUIP_MAIN_ATTR_INDEX.EQUIP_STRENGTH: - this.equipStrength = value; break; - case EQUIP_MAIN_ATTR_INDEX.EQUIP_STAR: - this.equipStar = value; break; - case EQUIP_MAIN_ATTR_INDEX.JEWEL: - this.jewel = value; break; - case EQUIP_MAIN_ATTR_INDEX.STONE: - this.stone = value; break; - case EQUIP_MAIN_ATTR_INDEX.JEWEL_BASE: - this.jewelBase = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = EQUIP_MAIN_ATTR_INDEX.START; i < EQUIP_MAIN_ATTR_INDEX.END; i++) { - switch(i) { - case EQUIP_MAIN_ATTR_INDEX.EQUIP_QUALITY: - values.push(this.equipQuality); - break; - case EQUIP_MAIN_ATTR_INDEX.EQUIP_STRENGTH: - values.push(this.equipStrength); - break; - case EQUIP_MAIN_ATTR_INDEX.EQUIP_STAR: - values.push(this.equipStar); - break; - case EQUIP_MAIN_ATTR_INDEX.JEWEL: - values.push(this.jewel); - break; - case EQUIP_MAIN_ATTR_INDEX.STONE: - values.push(this.stone); - break; - case EQUIP_MAIN_ATTR_INDEX.JEWEL_BASE: - values.push(this.jewelBase); - break; - } - } - return values; - } -} - -class EquipSubAttr extends EquipAllAttr { - public setByRoleCe(equipAttr: AttrCell) { - for(let i = 0; i < equipAttr.values.length; i++) { - let value = equipAttr.values[i]; - if(value != undefined) { - switch(i) { - case EQUIP_SUB_ATTR_INDEX.EQUIP_STAR: - this.equipStar = value; break; - case EQUIP_SUB_ATTR_INDEX.JEWEL: - this.jewel = value; break; - } - } - } - } - - public getValues() { - let values: number[] = []; - for(let i = EQUIP_SUB_ATTR_INDEX.START; i < EQUIP_SUB_ATTR_INDEX.END; i++) { - switch(i) { - case EQUIP_SUB_ATTR_INDEX.EQUIP_STAR: - values.push(this.equipStar); - break; - case EQUIP_SUB_ATTR_INDEX.JEWEL: - values.push(this.jewel); - break; - } - } - return values; - } -} - -enum GLOBAL_MAIN_ATTR_INDEX { - START, - SCHOOL = 0, // hp5,百家学宫百分比加成(dic_zyz_schoolRate的mainAttrApercent) - TERAPH = 1, // hp11, 神像加成(直接读数据库teraph字段的值) - TITLE = 2, // hp11, 爵位加成(dic_zyz_title的hp) - SCROLL = 3, // hp11,名将谱加成(dic_zyz_heroScroll的hp) - SKIN = 4, // hp12, 皮肤加成(dic_zyz_fashion的actorAttr) - AUTH_BOOK = 5, // hp16,诸子列传 - END -} - -enum GLOBAL_SUB_ATTR_INDEX { - START, - SCHOOL = 0, // attr5, 百家学宫(根据dic_zyz_school中的upAttribute决定书院加的是那些次级属性,具体值读取dic_zyz_schoolRate中的assiAttrAddValue一列) - TERAPH = 1, // attr4, 神像加成(dic_zyz_teraph中的assistAttrValue) - TITLE = 2, // attr6, 爵位(dic_zyz_title中的pdi、mdi) - SKIN = 3, // attr8, 皮肤 - AUTH_BOOK = 4, // attr10,诸子列传 - END -} - -enum HERO_MAIN_ATTR_INDEX { - START, - BASE = 0, // hp1, 角色基础属性(dic_zyz_hero的hp) - JOB = 1, // hp1, 职业属性(dic_zyz_job的attr) - STAR_UP = 2, // hp2, 角色升星成长(dic_zyz_hero_star的hp或dic_zyz_hero_wake的hp) - CONNECT = 3, // hp3, 角色羁绊固定值(dic_zyz_friend_ship的attribute) - FAVOUR = 4, // hp4, 声望加成(dic_zyz_friend_ship_level的add) - TALENT = 5, // hp5, 天赋树百分比加成(dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) - EQUIP_QUALITY = 6, // hp6, 装备品质基础值(dic_zyz_equipQuality的attribute) - EQUIP_STRENGTH = 7, // hp7, 装备强化值(dic_zyz_equipStrenthAttr的attr) - EQUIP_STAR = 8, // hp8,装备升星(dic_zyz_equipStar的mainAttr) - EQUIP_SUIT = 9, // hp8,套装(dic_zyz_equipSuit的effect,然后对应dic_zyz_se) - JEWEL = 10, // hp9,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool) - STONE = 11, // hp10, 地玉增加的固定值(dic_zyz_stone的attribute) - BASE_UP = 12, // hp2, 角色基础属性成长(dic_zyz_hero的hp_up) - ARTIFACT_LV = 13, // hp14, 宝物等级 - ARTIFACT_QUALITY = 14, // hp14, 宝物品质 - ARTIFACT_SEID = 15, // hp9,宝物词条 - JEWEL_BASE = 16, // hp15, 天晶基础属性(dic_zyz_jewel的rareEffectBaseAttr) - END -} - -enum HERO_SUB_ATTR_INDEX { - START, - BASE = 0, // attr1,系统参数表中所有人 - JOB = 1, // attr2, 职业的attr - TALENT = 2, // attr3, 天赋树百分比加成 (dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) - JEWEL = 3, // attr7, 天晶随机属性(随机出来的值在dic_zyz_randomEffectPool中读最终值) - EQUIP_STAR = 4, // attr9, 精炼次级属性(dic_zyz_equipStar的subAttr) - END -} - -enum EQUIP_MAIN_ATTR_INDEX { - START, - EQUIP_QUALITY = 0, // hp6, 装备升品基础值加成(dic_zyz_equipQuality) - EQUIP_STRENGTH = 1,// hp7, 装备强化值(需改表,改为键值对) - EQUIP_STAR = 2, // hp8, 装备(dic_zyz_equipStar) - JEWEL = 3, // hp9, 天晶洗练出的主属性百分比加成,equipAttr加起来 - STONE = 4, // hp10,地玉石增加的固定值,equipAttr加起来 - JEWEL_BASE = 5, // hp15, 天晶基础属性(dic_zyz_jewel的rareEffectBaseAttr) - END -} - -enum EQUIP_SUB_ATTR_INDEX { - START, - JEWEL = 0, // attr7, 天晶随机属性(随机出来的值在dic_zyz_randomEffectPool中读最终值) - EQUIP_STAR = 1, // attr9, 精炼次级属性(dic_zyz_equipStar的subAttr) - END -} \ No newline at end of file +import { ABI_STAGE, ABI_STAGE_TO_TYPE, ABI_TYPE, ABI_TYPE_MAIN, LINEUP_NUM, SEID_TYPE, TALENT_RELATION_TYPE } from "@consts"; +import { ArtifactModelType } from "@db/Artifact"; +import { AuthorBookType } from "@db/AuthorBook"; +import { Connect, EPlace, HeroSkin, HeroType, HeroUpdate, Stone, Talent } from "@db/Hero"; +import { JewelType } from "@db/Jewel"; +import { ResonanceType } from "@db/Resonance"; +import { RoleUpdate, Teraph } from "@db/Role"; +import { AttrCell, Attribute, EquipAttr, HeroAttr, RoleCeType, SchoolAttr, ScrollAttr } from "@db/RoleCe"; +import { TopHero } from "@domain/dbGeneral"; +import { AttributeCal } from "@domain/roleField/attribute"; +import { gameData, getDicArtifactLvByPlanId, getDicAuthorBookSub, getEquipQualityIdByEquipIdAndPoint, getEquipStarAttrByStage, getEquipStrenthenAttr, getEquipSuitByHero, getFriendShipByIdAndLv, getHeroStarByQuality, getHeroWakeByQuality, getJewelConditionByLvAndSeId, getJobByGradeAndClass, getSchoolRateByStar, getScollByStar, getTeraph } from "@pubUtils/data"; +import { DicRandomEffectPool } from "@pubUtils/dictionary/DicRandomEffectPool"; +import { DicSe } from "@pubUtils/dictionary/DicSe"; +import { addToMap, deepCopy } from "@pubUtils/util"; +export class CalCe { + roleId: string; + originCes: Map = new Map(); // hid => ce + resultCes: Map = new Map(); // hid => ce + data: CalCeData; + attrsByHid: Map = new Map(); + originTopHeroCe: number; + + constructor(roleId: string) { + this.roleId = roleId; + } + + public setRoleCe(roleCe: RoleCeType) { + this.data = new CalCeData(roleCe) + this.originCes = this.calHeroCe(); + this.originTopHeroCe = this.getTopLineup().topLineupCe; + } + + public clearRoleCe() { + this.data = new CalCeData(null); + } + + public getRoleCeTable() { + let attributes: Attribute[] = []; + for(let [hid, attrs] of this.attrsByHid) { + attributes.push({ hid, attrs }) + } + return this.data.getRoleCeTable(this.roleId, attributes); + } + + public calHeroCe() { + let attrs = new Map(); // hid => [{attrId, val}] + for(let [hid ] of this.data.heroAttrsByHid) { + let lv = this.data.heroLv.get(hid)||1; + for(let attrId = ABI_TYPE.ABI_HP; attrId < ABI_TYPE.ABI_MAX; attrId++) { + if(!this.data.heroAttrs.has(`${hid}_${attrId}`) && !this.data.globalAttrs.has(attrId)) continue; + let { mainBase = 0, mainBaseUp = 0, subBase = 0, job = 0, starUp = 0, connect = 0, talent = 0, equipQuality = 0, equipStrength = 0, equipStar = 0, equipSuit = 0, jewel = 0, stone = 0, artifactLv = 0, artifactQuality = 0, artifactSeid = 0, jewelBase = 0 } = this.data.heroAttrs.get(`${hid}_${attrId}`)||{}; + let { school = 0, teraph = 0, title = 0, scroll = 0, skin = 0, authorBook = 0 } = this.data.getGlobalAttrById(attrId)||{}; + let val = 0, ceVal = 0, str = '', ceStr = ''; + if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { + // {[ hp1 + lv * hp2 ] * ( 1 + hp5 ) + [( hp6 + hp7 ) * ( 1 + hp8 )]} * ( 1 + hp9 ) + hp10 + hp11 + hp14 + val = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality + jewelBase + authorBook; + ceVal = (( mainBase + job + lv * ( starUp + mainBaseUp ) ) * ( 1 + connect/100 ) + (( equipQuality + equipStrength ) * ( 1 + ( equipStar/100 + equipSuit/100 )))) * ( 1 + jewel/100 + school/100 + talent/100 + skin/100 + artifactSeid/100) + stone + teraph + title + scroll + artifactLv + artifactQuality + jewelBase + authorBook; + str += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}+${jewelBase}+${authorBook}`; + ceStr += `{[${mainBase}+${job}+${lv}*(${starUp}+${mainBaseUp})]* ( 1 + ${connect}/100) + [(${equipQuality}+${equipStrength}) * ( 1 + ${equipStar}/100+${equipSuit}/100)]} * (1+${jewel}/100+${school}/100+${talent}/100+${skin}/100+${artifactSeid}/100)+${stone}+${teraph}+${title}+${scroll}+${artifactLv}+${artifactQuality}+${jewelBase}+${authorBook}`; + } else { + // attr1 + attr2 + attr4 + attr5 + attr6 + attr7 + attr9 + attr10 + val = subBase + job + teraph + school + title + jewel + equipStar + authorBook; + ceVal = job + teraph + school + title + jewel + equipStar + authorBook; + str += `${subBase}+${job}+${teraph}+${school}+${title}+${jewel}+${equipStar}+${authorBook}`; + ceStr += `${job}+${teraph}+${school}+${title}+${jewel}+${equipStar}+${authorBook}`; + } + if(!attrs.has(hid)) attrs.set(hid, []); + attrs.get(hid).push({ id: attrId, val, ceVal, str, ceStr }); + } + } + let result = new Map(); + for(let [hid, arr] of attrs) { + let lv = this.data.heroLv.get(hid)||1; + let obj = new AttributeCal(); + obj.setLv(lv); + obj.setByCeArr(arr); + let ce = obj.calCe(); + this.resultCes.set(hid, ce); + result.set(hid, ce); + this.attrsByHid.set(hid, arr); + } + return result; + } + + public calSingleGlobalPartCe(hid: number, field: 'teraph'|'scroll') { + let arr: { id: number, val: number }[] = []; + for(let [attrId, globalAttr] of this.data.globalAttrs) { + arr.push({ id: attrId, val: globalAttr[field]||0 }); + } + let lv = this.data.heroLv.get(hid)||1; + let obj = new AttributeCal(); + obj.setLv(lv); + obj.setByWarJson(hid, arr); + return obj.calCe(); + } + + public getCeInc() { + let ceResult = this.calHeroCe(); + // console.log('##### ceResult', ceResult, 'originCes', this.originCes) + let heroCe = new Map(); + let roleInc = 0; + for(let [hid, ce] of ceResult) { + let originCe = this.originCes.get(hid)||0; + if(ce != originCe) { + heroCe.set(hid, { inc: ce - originCe, origin: originCe, ce }); + roleInc += ce - originCe; + this.data.setHistoryCe(hid, ce); + } + } + return { heroCe, roleInc } + } + + public setResultHero(hero: HeroType) { + this.data.setResultHero(hero); + } + + public getResultCeArr() { + let arr: { hid: number, ce: number }[] = []; + for(let [ hid, ce ] of this.resultCes) { + arr.push({ hid, ce }); + } + arr.sort((a, b) => b.ce - a.ce); + return arr; + } + + public getTopLineup() { + let topLineup: TopHero[] = [], topLineupCe = 0; + let arr = this.getResultCeArr(); + for(let i = 0; i < LINEUP_NUM; i++) { + if(arr[i]) { + let { hid, ce } = arr[i]; + topLineup.push({ + hid, ce, hero: this.data.heroObjectId.get(hid) + }); + topLineupCe += ce; + } + } + return { topLineup, topLineupCe, hasTopCeChange: topLineupCe == this.originTopHeroCe }; + } + + public getTopLineupNew(dbResonanceMap: Map) { + let topLineup: TopHero[] = [], topLineupCe = 0; + let arr = this.getResultCeArr(); + for (let obj of arr) { + if (topLineup.length >= LINEUP_NUM) break; + let { hid, ce } = obj; + if (dbResonanceMap.has(hid)) continue; + topLineup.push({ + hid, ce, hero: this.data.heroObjectId.get(hid) + }); + topLineupCe += ce; + } + + return { topLineup, topLineupCe, hasTopCeChange: topLineupCe == this.originTopHeroCe }; + } + + + // 玩家等级 + public setRoleLv(lv: number) { + this.data.roleLv = lv; + } + + // 武将基础&成长 + public setHeroBase(hid: number, skinId: number) { + this.data.clearHeroAttrByHid(hid, 'mainBase'); + this.data.clearHeroAttrByHid(hid, 'mainBaseUp'); + let dicHero = gameData.hero.get(skinId); + + for(let [attrId, value] of dicHero.baseAbilityArr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.mainBase = value; + } + for(let [attrId, value] of dicHero.baseAbilityUpArr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.mainBaseUp = value; + } + } + + // 武将等级 + public setHeroLv(hid: number, lv: number) { + this.data.heroLv.set(hid, lv); + } + + // 星级相关 + public setHeroStar(hid: number, job: number, quality: number, star: number, starStage: number, colorStar: number, colorStarStage: number) { + this.data.clearHeroAttrByHid(hid, 'starUp'); + let dicHero = gameData.hero.get(hid); + let dicJob = gameData.job.get(job); + let jobClass = dicJob.job_class; + const isWake = colorStar > 0; // 是否觉醒,只要激活了觉醒,彩星就会 > 1 + const dicStar = isWake ? getHeroWakeByQuality(jobClass, dicHero.quality, colorStar) : getHeroStarByQuality(jobClass, quality, star); // 星级表 + const dicPreStar = isWake? getHeroWakeByQuality(jobClass, dicHero.quality, colorStar - 1): getHeroStarByQuality(jobClass, quality, star - 1); + let curStage = isWake? colorStarStage: starStage; + + for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) { + let attrId = ABI_STAGE_TO_TYPE.get(stage); + let value = 0; // 星级成长 + if(curStage >= stage) { + value = dicStar?.ceAttr.get(stage)||0; + } else { + value = dicPreStar?.ceAttr.get(stage)||0; + } + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.starUp = value; + }; + } + + // 职业基础 + public setJob(hid: number, job: number, jobStage: number) { + this.data.clearHeroAttrByHid(hid, 'job'); + const dicJob = gameData.job.get(job); + let ceAttr = dicJob.ceAttr.get(jobStage)||[]; + for(let { id, attr } of ceAttr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.job = attr; + } + for(let { id, val } of dicJob.baseSubAttr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.subBase = val; + } + } + + // 羁绊 + public setConnection(hid: number, connections: Connect[]) { + this.data.clearHeroAttrByHid(hid, 'connect'); + let map = new Map(); // attrId => val; + for(let { shipId, level = 0 } of connections) { + let currentShip = getFriendShipByIdAndLv(hid, shipId, level); + if (currentShip) { + for (let { id, number: val } of currentShip.attributes) { + if(!map.has(id)) { + map.set(id, val); + } else { + map.set(id, map.get(id) + val); + } + } + } + } + for(let [id, val] of map) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.connect = val; + } + } + + // 第一次获得皮肤 + public setAddSkin(skinId: number) { + let addSkin = gameData.fashion.get(skinId); + for (let { id, number: val } of addSkin.globalAttr) { + let globalAttr = this.data.getGlobalAttrById(id); + globalAttr.skin += val; + } + } + + // 天赋 + public setTalent(hid: number, skins: HeroSkin[]) { + this.data.clearHeroAttrByHid(hid, 'talent'); + let skin = skins.find(cur => cur.enable); + let seids = this.getTalentSeid(skin.talent); + let { ratioUp } = this.addSeidEffect(seids); + for(let [attrId, val] of ratioUp) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.talent = val; + } + } + + public getTalentSeid(talent: Talent[]) { + let seids = new Map(); // id, seids + for(let { id, level } of talent) { + let dicHeroTalent = gameData.heroTalent.get(id); + for(let { type, ids} of dicHeroTalent.relation) { + if(type == TALENT_RELATION_TYPE.REPLACE) { + for(let id of ids) { + seids.delete(id); + } + } + } + for(let { lv, seid } of dicHeroTalent.level) { + if(level == lv) { + if(!seids.has(id)) seids.set(id, []); + seids.get(id).push(seid, 0); + } + } + } + let result: number[] = []; + for(let [_, ids] of seids) { + result.push(...ids); + } + return result; + } + + // 装备升品 + public setEquipQuality(hid: number, eplaceId: number, equipId: number, quality: number, qualityStage: number) { + this.data.clearHeroAttrByHid(hid, 'equipQuality'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipQuality'); + let dicEquipQuality = getEquipQualityIdByEquipIdAndPoint(equipId, quality, qualityStage); + let map = new Map(); // attrId => val + for(let { id, num } of dicEquipQuality.attribute) { + if(!map.has(id)) { + map.set(id, num); + } else { + map.set(id, map.get(id) + num); + } + } + for(let [id, val] of map) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.equipQuality = val; + } + let equips = this.data.getEquipAttrsByHid(hid); + for(let { hid, attrId, equipQuality } of equips) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.equipQuality += equipQuality; + } + + } + + public clearEquip(hid: number) { + this.data.clearHeroAttrByHid(hid, 'equipQuality'); + this.data.clearEquipAttrByHid(hid, 'equipQuality'); + this.data.clearHeroAttrByHid(hid, 'equipStrength'); + this.data.clearEquipAttrByHid(hid, 'equipStrength'); + this.data.clearHeroAttrByHid(hid, 'equipStar'); + this.data.clearEquipAttrByHid(hid, 'equipStar'); + this.data.clearHeroAttrByHid(hid, 'jewel'); + this.data.clearHeroAttrByHid(hid, 'jewelBase'); + this.data.clearEquipAttrByHid(hid, 'jewel'); + this.data.clearEquipAttrByHid(hid, 'jewelBase'); + this.data.clearHeroAttrByHid(hid, 'stone'); + this.data.clearEquipAttrByHid(hid, 'stone'); + } + + // 装备强化 + public setEquipStrength(hid: number, eplaceId: number, equipId: number, lv: number) { + this.data.clearHeroAttrByHid(hid, 'equipStrength'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipStrength'); + let dicEquipStrenth = getEquipStrenthenAttr(equipId, lv); + let map = new Map(); // attrId => val + for(let { id, num } of dicEquipStrenth.attr) { + if(!map.has(id)) { + map.set(id, num); + } else { + map.set(id, map.get(id) + num); + } + } + for(let [id, val] of map) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.equipStrength = val; + } + let equips = this.data.getEquipAttrsByHid(hid); + for(let { hid, attrId, equipStrength } of equips) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.equipStrength += equipStrength; + } + } + + // 装备精炼(升星) + public setEquipStar(hid: number, eplaceId: number, equipId: number, star: number, starStage: number) { + this.data.clearHeroAttrByHid(hid, 'equipStar'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'equipStar'); + let dicEquipStar = getEquipStarAttrByStage(equipId, star, starStage); + if(dicEquipStar) { + let { mainAttr, subAttr } = dicEquipStar; + let map = new Map(); // attrId => val + for(let { id, num } of [...mainAttr, ...subAttr]) { + if(!map.has(id)) { + map.set(id, num); + } else { + map.set(id, map.get(id) + num); + } + } + for(let [id, val] of map) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.equipStar = val; + } + let equips = this.data.getEquipAttrsByHid(hid); + for(let { hid, attrId, equipStar } of equips) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.equipStar += equipStar; + } + } + } + + // 装备套装 + public setEquipSuit(hid: number, skinId: number, ePlace: EPlace[]) { + this.data.clearHeroAttrByHid(hid, 'equipSuit'); + let dicEquipSuit = getEquipSuitByHero(skinId); + let suitStars: number[] = []; + for(let equipId of dicEquipSuit.equips) { + let equip = ePlace.find(cur => cur.equipId == equipId); + suitStars.push(equip? equip.star: 0); + } + let minStar = Math.min(...suitStars); + + for(let { star, id, val } of dicEquipSuit.effect) { + if(minStar >= star) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.equipSuit = val; + } + } + } + + // 天晶 + public setJewel(hid: number, eplaceId: number, stones: Stone[], jewel: JewelType) { + this.data.clearHeroAttrByHid(hid, 'jewel'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'jewel'); + this.data.clearHeroAttrByHid(hid, 'jewelBase'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'jewelBase'); + let seids: number[] = []; + if(jewel) { + for(let { id, seid, rand } of jewel.randSe) { + if(this.isRandSeUnLock(jewel.id, id, stones)) { + seids.push(seid, rand); + } + } + for(let { seid, rand } of jewel.rareSe) { + seids.push(seid, rand); + } + let dicJewel = gameData.jewel.get(jewel.id); + if(dicJewel) { + let attrBaseValues = dicJewel.rareEffectBaseAttr||[]; + for(let { id, num } of attrBaseValues) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.jewelBase = num; + } + } + } + let { ratioUp } = this.addSeidEffect(seids); + let map = new Map(); // attrId => val + for(let [id, num] of ratioUp) { + if(!map.has(id)) { + map.set(id, num); + } else { + map.set(id, map.get(id) + num); + } + } + for(let [id, val] of map) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.jewel = val; + } + let equips = this.data.getEquipAttrsByHid(hid); + for(let { hid, attrId, jewel, jewelBase } of equips) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.jewel += jewel; + heroAttr.jewelBase += jewelBase; + } + } + + public isRandSeUnLock(jewelId: number, randSeId: number, stones: Stone[]) { + let dicJewel = gameData.jewel.get(jewelId); + let dicJewelCondition = getJewelConditionByLvAndSeId(dicJewel.lv, randSeId); + let stoneCnt = 0, stoneLv = 0; + for(let { stone } of stones) { + let dicStone = gameData.stone.get(stone); + if(dicStone) { + stoneCnt++; + stoneLv += dicStone.lv; + } + } + return stoneCnt >= dicJewelCondition.stoneCnt && stoneLv >= dicJewelCondition.stoneLv; + } + + // 地玉 + public setStone(hid: number, eplaceId: number, stones: Stone[]) { + this.data.clearHeroAttrByHid(hid, 'stone'); + this.data.clearEquipAttrByHidAndEplace(hid, eplaceId, 'stone'); + let map = new Map(); // attrId => val + for(let { stone } of stones) { + let dicStone = gameData.stone.get(stone); + if(dicStone) { + for(let { id, num } of dicStone.attribute) { + if(!map.has(id)) { + map.set(id, num); + } else { + map.set(id, map.get(id) + num); + } + } + } + } + for(let [id, val] of map) { + let equipAttr = this.data.getEquipAttrByHidAndId(hid, eplaceId, id); + equipAttr.stone = val; + } + let equips = this.data.getEquipAttrsByHid(hid); + for(let { hid, attrId, stone } of equips) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.stone += stone; + } + } + + + // 爵位 + public setTitle(title: number) { + this.data.clearRoleAttr('title'); + let dicTitle = gameData.title.get(title)||{ mainAttrValue: new Map(), assiAttrValue: new Map() }; + for(let [attrId, value] of dicTitle.mainAttrValue) { + let globalAttr = this.data.getGlobalAttrById(attrId); + globalAttr.title = value; + } + for(let [attrId, value] of dicTitle.assiAttrValue) { + let globalAttr = this.data.getGlobalAttrById(attrId); + globalAttr.title = value; + } + } + + // 神像相关 + public setTeraph(teraphs: Teraph[]) { + + this.data.clearRoleAttr('teraph'); + let teraphOfAttrId = new Map(); + for(let teraph of teraphs) { + let dicTeraph = getTeraph(teraph.id, teraph.grade); + for(let [attrId, value] of teraph.attr) { // 主属性 + let basic = dicTeraph.basicAttrValue.get(attrId)||0; + addToMap(teraphOfAttrId, attrId, value + basic); + } + for(let [attrId, value] of dicTeraph.assiAttrValue) { // 次属性 + addToMap(teraphOfAttrId, attrId, value); + } + } + for(let [attrId, value] of teraphOfAttrId) { + let globalAttr = this.data.getGlobalAttrById(attrId); + globalAttr.teraph = value; + } + } + + // 名将谱 + public setScroll(hid: number, scrollStar: number, scrollQuality: number, scrollColorStar: number) { + this.data.clearScrollAttr(hid); + let dicHero =gameData.hero.get(hid); + let dicHeroScroll = getScollByStar(dicHero.quality, scrollStar, scrollQuality, scrollColorStar); + + if(dicHeroScroll) { + for(let [attrId, value] of dicHeroScroll.ceAttr) { + this.data.setScrollAttrs(hid, attrId, value); + this.data.calScrollAttrsToGlobal(attrId); + } + } + } + + // 百家学宫 + public setSchool(isPutOn: boolean, hid: number, schoolId: number, star: number, colorStar: number, quality: number) { + this.data.clearSchoolAttr(hid); + let dicSchool = gameData.school.get(schoolId); + let dicSchoolRate = getSchoolRateByStar(star, colorStar, quality); + + for (let attrId of dicSchool.upAttribute) { + if(ABI_TYPE_MAIN.includes(attrId)) { // 主属性 + this.data.setSchoolAttrs(hid, attrId, isPutOn?dicSchoolRate.mainAttrAPerent: 0); + } else { + this.data.setSchoolAttrs(hid, attrId, isPutOn?dicSchoolRate.assiAttrAddValue: 0); + } + this.data.calSchoolAttrsToGlobal(attrId); + } + } + + // 卸下宝物 + public setPutOffArtifact(hid: number) { + this.data.clearHeroAttrByHid(hid, 'artifactLv'); + this.data.clearHeroAttrByHid(hid, 'artifactQuality'); + this.data.clearHeroAttrByHid(hid, 'artifactSeid'); + } + + // 装备宝物 + public setPutArtifact(hid: number, skinId: number, job: number, artifact: ArtifactModelType) { + this.data.clearHeroAttrByHid(hid, 'artifactLv'); + this.data.clearHeroAttrByHid(hid, 'artifactQuality'); + this.data.clearHeroAttrByHid(hid, 'artifactSeid'); + + if(artifact) { + this.setArtifactLv(hid, artifact.artifactId, artifact.lv); + this.setArtifactQuality(hid, artifact.artifactId); + this.setArtifactSeid(hid, skinId, job, artifact.artifactId); + } + } + + // 宝物等级 + public setArtifactLv(hid: number, artifactId: number, lv: number) { + this.data.clearHeroAttrByHid(hid, 'artifactLv'); + let dicArtifact = gameData.artifact.get(artifactId); + if(!dicArtifact) return; + + let dicArtifactLv = getDicArtifactLvByPlanId(dicArtifact.lvAttrPlan, lv); + if(!dicArtifactLv) return; + + let ceAttr = dicArtifactLv.attr||[]; + for(let { id, attr } of ceAttr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.artifactLv = attr; + } + } + + // 诸子列传属性 + public setAuthorBooks(authorBooks: AuthorBookType[]) { + + this.data.clearRoleAttr('authorBook'); + let attrResult = new Map(); + for(let { bookId, progress, authors } of authorBooks) { + // 升星的属性 + for(let { subId, star } of authors) { + let dicAuthorBook = getDicAuthorBookSub(bookId, subId, star); + if(dicAuthorBook) { + for(let {id, val} of dicAuthorBook.attr) addToMap(attrResult, id, val); + } + } + + let dicPoints = gameData.authorBookPoint.get(bookId)||[]; + for(let { value, attr } of dicPoints) { + if(progress >= value) { + for(let { id, val } of attr) addToMap(attrResult, id, val); + } + } + } + + for(let [attrId, value] of attrResult) { + let globalAttr = this.data.getGlobalAttrById(attrId); + globalAttr.authorBook = value; + } + } + + // 宝物品质 + public setArtifactQuality(hid: number, artifactId: number) { + this.data.clearHeroAttrByHid(hid, 'artifactQuality'); + + let dicArtifact = gameData.artifact.get(artifactId); + if(!dicArtifact) return; + + // 基础属性 + let dicArtifactQualityPlan = gameData.artifactQualityPlan.get(dicArtifact.qualityAttrPlan); + if(!dicArtifactQualityPlan) return; + + let ceAttr = dicArtifactQualityPlan.attr||[]; + for(let { id, attr } of ceAttr) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, id); + heroAttr.artifactQuality = attr; + } + } + + // 宝物词条 + public setArtifactSeid(hid: number, skinId: number, job: number, artifactId: number) { + this.data.clearHeroAttrByHid(hid, 'artifactSeid'); + + let dicArtifact = gameData.artifact.get(artifactId); + if(!dicArtifact) return; + let dicJob = gameData.job.get(job); + if(!dicJob) return; + + let seids: number[] = []; // id, seids + for(let seid of dicArtifact.seids) { + let dicArtifactSeid = gameData.artifactSeid.get(seid); + if(!dicArtifactSeid) continue; + if(dicArtifactSeid.jobClass != 0 && dicArtifactSeid.jobClass != dicJob.job_class) continue; + if(dicArtifactSeid.hids.length > 0 && dicArtifactSeid.hids.indexOf(skinId) == -1) continue; + if(dicArtifactSeid.quality > dicArtifact.quality) continue; + for(let seid of dicArtifactSeid.seids) { + seids.push(seid, 0); + } + } + + let { ratioUp } = this.addSeidEffect(seids); + for(let [attrId, val] of ratioUp) { + let heroAttr = this.data.getHeroAttrByHidAndId(hid, attrId); + heroAttr.artifactSeid = val; + } + } + + // 添加技能增加的被动属性 + private addSeidEffect(seidList: number[]) { + let fixUp = new Map(), ratioUp = new Map(); + let effectList: DicSe[] = []; // any: dic_zyz_se表内容 + + for (let ii = 0; ii < seidList.length; ii += 2) { + let seid = seidList[ii]; + let rand = seidList[ii + 1] || 0; + let dicSeid: DicSe | DicRandomEffectPool = gameData.se.get(seid); + if (!dicSeid) dicSeid = gameData.randomEffectPool.get(seid); + if (dicSeid && dicSeid.id > 0) { + this.addSeid(effectList, dicSeid.id, rand, dicSeid.gainValueArr) + } + } + + // console.log('effectList', JSON.stringify(effectList)); + for (let { type, id, gainValueArr: [ability, value] } of effectList) { + // console.log('##### addToMap type', type, 'id', id, 'ability', ability, 'value', value) + if (type == SEID_TYPE.FIX) { // 加值 + addToMap(fixUp, ability, value); + } else if (type == SEID_TYPE.MAIN_RATIO||type == SEID_TYPE.MAIN_RATIO_2) { // 主属性加百分比 + if(ABI_TYPE_MAIN.includes(ability)) { + addToMap(ratioUp, ability, value); + } + } else if (type == SEID_TYPE.SUB_RATIO||type == SEID_TYPE.SUB_RATIO_2) { // 次级属性加百分比 + if(!ABI_TYPE_MAIN.includes(ability)) { + addToMap(ratioUp, ability, value); + } + } + + } + return { fixUp, ratioUp }; + } + + // 获取dic_zyz_se内容 + private addSeid(effectList: (DicSe | DicRandomEffectPool)[], seidId: number, rand: number, seidValue: number[] = []) { + let curSeid: DicSe | DicRandomEffectPool = gameData.se.get(seidId); + if (!curSeid) curSeid = gameData.randomEffectPool.get(seidId); + if (!curSeid) { console.log("seidId not found:" + seidId); return; } + if (!seidValue) seidValue = curSeid.gainValueArr; + + if (curSeid.type === SEID_TYPE.MIX) { + for (let i = 0; i < seidValue.length; i++) { + this.addSeid(effectList, seidValue[i], rand); + } + return; + } + let seid: DicSe | DicRandomEffectPool = deepCopy(curSeid); + if (curSeid.index > 0) { + seid.gainValueArr[curSeid.index - 1] = rand; + } + effectList.push(seid); + } +} + +class CalCeData { + roleLv: number = 1; // 玩家等级 + // 全局 + globalAttrs: Map = new Map(); // attrId => GlobalAttr + // 武将 + heroAttrs: Map = new Map(); // hid+attrId => HeroAttr + heroAttrsByHid: Map = new Map(); // hid => [hid+attrId] + heroLv: Map = new Map(); + heroHistoryCe: Map = new Map(); + heroObjectId: Map = new Map(); + // 装备 + equipAttrs: Map = new Map(); // hid+eplaceId+attrId => EquipAttr + equipAttrsByHid: Map = new Map(); // hid => [hid+eplaceId+attrId] + equipAttrsByHidAndEplace: Map = new Map(); // hid+eplaceId =>[hid+eplaceId+attrId] + equipAttrsByHidAndAttrId: Map = new Map(); // hid+attrId =>[hid+eplaceId+attrId] + equipLv: Map = new Map(); // hid+eplaceId => lv + // 百家学宫 + schoolAttrs: Map = new Map(); // hid + attr => ratio + schoolAttrsByAttrId: Map = new Map(); // attrId => hid + attr + schoolAttrsByHid: Map = new Map(); // hid => hid + attr + // 名将谱 + scrollAttrs: Map = new Map(); // hid + attr => ratio + scrollAttrsByAttrId: Map = new Map(); // attrId => hid + attr + scrollAttrsByHid: Map = new Map(); // hid => hid + attr + + constructor(roleCe: RoleCeType) { + if(roleCe) { + this.roleLv = roleCe.roleLv; + for(let globalAttr of roleCe.globalAttrs) { + let obj = this.getGlobalAttrById(globalAttr.attrId); + obj.setByRoleCe(globalAttr); + } + for(let {hid, lv, attrs, historyCe, objectId } of roleCe.heroAttrs) { + this.heroLv.set(hid, lv); + this.heroHistoryCe.set(hid, historyCe); + this.heroObjectId.set(hid, objectId); + for(let cell of attrs) { + let obj = this.getHeroAttrByHidAndId(hid, cell.attrId); + obj.setByRoleCe(cell); + } + } + for(let { hid, eplaceId, lv, attrs } of roleCe.equipAttrs) { + this.equipLv.set(`${hid}_${eplaceId}`, lv); + for(let cell of attrs) { + let obj = this.getEquipAttrByHidAndId(hid, eplaceId, cell.attrId); + obj.setByRoleCe(cell); + } + } + for(let { hid, attrId, value } of roleCe.schoolAttrs) { + this.setSchoolAttrs(hid, attrId, value); + } + for(let { hid, attrId, value } of roleCe.scrollAttrs) { + this.setScrollAttrs(hid, attrId, value); + } + } + } + + public getGlobalAttrById(attrId: number) { + if(!this.globalAttrs.has(attrId)) { + if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { + let obj = new GlobalMainAttr(attrId); + this.globalAttrs.set(attrId, obj); + } else { + let obj = new GlobalSubAttr(attrId); + this.globalAttrs.set(attrId, obj); + } + } + return this.globalAttrs.get(attrId); + } + + public clearRoleAttr(field: string) { + for(let [_attrId, globalAttr] of this.globalAttrs) { + globalAttr[field] = 0; + } + } + + public getHeroAttrsByHid(hid: number) { + let keys = this.heroAttrsByHid.get(hid)||[]; + return keys.map(key => this.heroAttrs.get(key)); + } + + public getHeroAttrByHidAndId(hid: number, attrId: number) { + let key = `${hid}_${attrId}`; + if(!this.heroAttrs.has(key)) { + if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { + let obj = new HeroMainAttr(hid, attrId); + this.heroAttrs.set(key, obj); + } else { + let obj = new HeroSubAttr(hid, attrId); + this.heroAttrs.set(key, obj); + } + + if(!this.heroAttrsByHid.has(hid)) { + this.heroAttrsByHid.set(hid, []); + } + this.heroAttrsByHid.get(hid).push(key); + } + return this.heroAttrs.get(key); + } + + public clearHeroAttrByHid(hid: number, field: string) { + let heroAttrs = this.getHeroAttrsByHid(hid)||[]; + for(let heroAttr of heroAttrs) { + heroAttr[field] = 0; + } + } + + public getEquipAttrByHidAndId(hid: number, eplaceId: number, attrId: number) { + let key = `${hid}_${eplaceId}_${attrId}`; + if(!this.equipAttrs.has(key)) { + if(ABI_TYPE_MAIN.indexOf(attrId) != -1) { + let obj = new EquipMainAttr(hid, attrId); + this.equipAttrs.set(key, obj); + } else { + let obj = new EquipSubAttr(hid, attrId); + this.equipAttrs.set(key, obj); + } + + if(!this.equipAttrsByHid.has(hid)) { + this.equipAttrsByHid.set(hid, []); + } + this.equipAttrsByHid.get(hid).push(key); + let key2 = `${hid}_${eplaceId}`; + if(!this.equipAttrsByHidAndEplace.has(key2)) { + this.equipAttrsByHidAndEplace.set(key2, { hid, eplaceId, keys: []}); + } + this.equipAttrsByHidAndEplace.get(key2).keys.push(key); + } + return this.equipAttrs.get(key); + } + + public getEquipAttrsByHid(hid: number) { + let keys = this.equipAttrsByHid.get(hid)||[]; + return keys.map(key => this.equipAttrs.get(key)); + } + + public getEquipAttrsByHidAndEplace(hid: number, eplaceId: number) { + let key2 = `${hid}_${eplaceId}`; + if(!this.equipAttrsByHidAndEplace.has(key2)) return [] + let { keys } = this.equipAttrsByHidAndEplace.get(key2); + return keys.map(key => this.equipAttrs.get(key)); + } + + public clearEquipAttrByHidAndEplace(hid: number, eplaceId: number, field: string) { + let equipAttrs = this.getEquipAttrsByHidAndEplace(hid, eplaceId); + for(let equipAttr of equipAttrs) { + equipAttr[field] = 0; + } + } + + public clearEquipAttrByHid(hid: number, field: string) { + let equipAttrs = this.getEquipAttrsByHid(hid); + for(let equipAttr of equipAttrs) { + equipAttr[field] = 0; + } + } + + public setSchoolAttrs(hid: number, attrId: number, value: number) { + let key = `${hid}_${attrId}`; + if(!this.schoolAttrs.has(key)) { + this.schoolAttrs.set(key, { hid, attrId, ce: value }); + if(!this.schoolAttrsByAttrId.has(attrId)) { + this.schoolAttrsByAttrId.set(attrId, []); + } + this.schoolAttrsByAttrId.get(attrId).push(key); + if(!this.schoolAttrsByHid.has(hid)) { + this.schoolAttrsByHid.set(hid, []); + } + this.schoolAttrsByHid.get(hid).push(key); + } else { + this.schoolAttrs.get(key).ce = value; + } + } + + public getSchoolAttrsByHid(hid: number) { + let keys = this.schoolAttrsByHid.get(hid)||[]; + return keys.map(key => this.schoolAttrs.get(key)); + } + + public calSchoolAttrsToGlobal(attrId: number) { + let keys = this.schoolAttrsByAttrId.get(attrId)||[]; + let schoolResult = 0; + for(let key of keys) { + let { ce } = this.schoolAttrs.get(key); + schoolResult += ce; + } + let globalAttr = this.getGlobalAttrById(attrId); + globalAttr.school = schoolResult; + } + + public clearSchoolAttr(hid: number) { + let schoolAttrs = this.getSchoolAttrsByHid(hid)||[]; + for(let schoolAttr of schoolAttrs) { + schoolAttr.ce = 0; + this.calSchoolAttrsToGlobal(schoolAttr.attrId); + } + } + + public setScrollAttrs(hid: number, attrId: number, value: number) { + let key = `${hid}_${attrId}`; + if(!this.scrollAttrs.has(key)) { + this.scrollAttrs.set(key, { hid, attrId, ce: value }); + if(!this.scrollAttrsByAttrId.has(attrId)) { + this.scrollAttrsByAttrId.set(attrId, []); + } + this.scrollAttrsByAttrId.get(attrId).push(key); + if(!this.scrollAttrsByHid.has(hid)) { + this.scrollAttrsByHid.set(hid, []); + } + this.scrollAttrsByHid.get(hid).push(key); + } else { + this.scrollAttrs.get(key).ce = value; + } + } + + public calScrollAttrsToGlobal(attrId: number) { + let keys = this.scrollAttrsByAttrId.get(attrId)||[]; + let result = 0; + for(let key of keys) { + let { ce } = this.scrollAttrs.get(key); + result += ce; + } + let globalAttr = this.getGlobalAttrById(attrId); + globalAttr.scroll = result; + } + + public clearScrollAttr(hid: number) { + let scrollAttrs = this.getScrollAttrsByHid(hid); + for(let scrollAttr of scrollAttrs) { + scrollAttr.ce = 0; + this.calScrollAttrsToGlobal(scrollAttr.attrId); + } + } + + public getScrollAttrsByHid(hid: number) { + let keys = this.scrollAttrsByHid.get(hid)||[]; + return keys.map(key => this.scrollAttrs.get(key)); + } + + public setHistoryCe(hid: number, ce: number) { + let historyCe = this.heroHistoryCe.get(hid)||0; + if(ce > historyCe) { + this.heroHistoryCe.set(hid, ce); + } + } + + public setResultHero(hero: HeroType) { + this.heroObjectId.set(hero.hid, hero._id); + } + + public getRoleCeTable(roleId: string, attributes: Attribute[]) { + let globalAttrs: AttrCell[] = []; + for(let [_, globalAttr] of this.globalAttrs) { + globalAttrs.push(globalAttr.getGlobalAttr()); + } + let heroAttrs: HeroAttr[] = []; + for(let [hid, keys] of this.heroAttrsByHid) { + let lv = this.heroLv.get(hid); + let historyCe = this.heroHistoryCe.get(hid)||0; + let objectId = this.heroObjectId.get(hid); + let attrs: AttrCell[] = []; + for(let key of keys) { + let heroAttr = this.heroAttrs.get(key); + attrs.push(heroAttr.getHeroAttrCell()); + } + heroAttrs.push({ + hid, lv, attrs, historyCe, objectId + }); + } + let equipAttrs: EquipAttr[] = []; + for(let [key2, { hid, eplaceId, keys }] of this.equipAttrsByHidAndEplace) { + let lv = this.equipLv.get(key2); + let attrs: AttrCell[] = []; + for(let key of keys) { + let equipAttr = this.equipAttrs.get(key); + attrs.push(equipAttr.getEquipAttrCell()); + } + equipAttrs.push({ + hid, eplaceId, lv, attrs + }); + } + let schoolAttrs: SchoolAttr[] = []; + for(let [_, { hid, attrId, ce }] of this.schoolAttrs) { + schoolAttrs.push({ hid, attrId, value: ce }); + } + let scrollAttrs: ScrollAttr[] = []; + for(let [_, { hid, attrId, ce }] of this.scrollAttrs) { + scrollAttrs.push({ hid, attrId, value: ce }); + } + return { + roleLv: this.roleLv, roleId, globalAttrs, heroAttrs, equipAttrs, schoolAttrs, scrollAttrs, attributes + } + } +} + +abstract class GlobalAllAttr { + attrId: number; + school: number = 0; + teraph: number = 0; + title: number = 0; + scroll: number = 0; + skin: number = 0; + authorBook: number = 0; + + constructor(attrId: number) { + this.attrId = attrId; + } + + abstract setByRoleCe(data: AttrCell): void; + abstract getValues(): number[]; + + public getGlobalAttr() { + let values = this.getValues().map(cur => (cur||0)); + return { + attrId: this.attrId, + values + } + } +} + +class GlobalMainAttr extends GlobalAllAttr { + + public setByRoleCe(globalAttr: AttrCell) { + for(let i = 0; i < globalAttr.values.length; i++) { + let value = globalAttr.values[i]; + if(value != undefined) { + switch(i) { + case GLOBAL_MAIN_ATTR_INDEX.SCHOOL: + this.school = value; break; + case GLOBAL_MAIN_ATTR_INDEX.TERAPH: + this.teraph = value; break; + case GLOBAL_MAIN_ATTR_INDEX.TITLE: + this.title = value; break; + case GLOBAL_MAIN_ATTR_INDEX.SCROLL: + this.scroll = value; break; + case GLOBAL_MAIN_ATTR_INDEX.SKIN: + this.skin = value; break; + case GLOBAL_MAIN_ATTR_INDEX.AUTH_BOOK: + this.authorBook = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = GLOBAL_MAIN_ATTR_INDEX.START; i < GLOBAL_MAIN_ATTR_INDEX.END; i++) { + switch(i) { + case GLOBAL_MAIN_ATTR_INDEX.SCHOOL: + values.push(this.school); + break; + case GLOBAL_MAIN_ATTR_INDEX.TERAPH: + values.push(this.teraph); + break; + case GLOBAL_MAIN_ATTR_INDEX.TITLE: + values.push(this.title); + break; + case GLOBAL_MAIN_ATTR_INDEX.SCROLL: + values.push(this.scroll); + break; + case GLOBAL_MAIN_ATTR_INDEX.SKIN: + values.push(this.skin); + break; + case GLOBAL_MAIN_ATTR_INDEX.AUTH_BOOK: + values.push(this.authorBook); + break; + } + } + return values; + } +} + +class GlobalSubAttr extends GlobalAllAttr { + + public setByRoleCe(globalAttr: AttrCell) { + for(let i = 0; i < globalAttr.values.length; i++) { + let value = globalAttr.values[i]; + if(value != undefined) { + switch(i) { + case GLOBAL_SUB_ATTR_INDEX.SCHOOL: + this.school = value; break; + case GLOBAL_SUB_ATTR_INDEX.TERAPH: + this.teraph = value; break; + case GLOBAL_SUB_ATTR_INDEX.TITLE: + this.title = value; break; + case GLOBAL_SUB_ATTR_INDEX.SKIN: + this.skin = value; break; + case GLOBAL_SUB_ATTR_INDEX.AUTH_BOOK: + this.authorBook = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = GLOBAL_SUB_ATTR_INDEX.START; i < GLOBAL_SUB_ATTR_INDEX.END; i++) { + switch(i) { + case GLOBAL_SUB_ATTR_INDEX.SCHOOL: + values.push(this.school); + break; + case GLOBAL_SUB_ATTR_INDEX.TERAPH: + values.push(this.teraph); + break; + case GLOBAL_SUB_ATTR_INDEX.TITLE: + values.push(this.title); + break; + case GLOBAL_SUB_ATTR_INDEX.SKIN: + values.push(this.skin); + break; + case GLOBAL_SUB_ATTR_INDEX.AUTH_BOOK: + values.push(this.authorBook); + break; + } + } + return values; + } +} + +abstract class HeroAllAttr { + hid: number; + attrId: number; + mainBase: number = 0; // hp1,武将基础属性(dic_zyz_hero的hp) + subBase: number = 0; // attr1,职业基础(dic_zyz_job的baseSubAttr字段) + job: number = 0; // hp1 & attr2, 职业属性(dic_zyz_job的attr) + starUp: number = 0; // hp2, 角色升星成长(dic_zyz_hero_star的hp或dic_zyz_hero_wake的hp) + connect: number = 0; // hp3, 角色羁绊固定值(dic_zyz_friend_ship的attribute) + favour: number = 0; // 删除-hp4, 声望加成(dic_zyz_friend_ship_level的add) + talent: number = 0; // hp5 & attr3, 天赋树百分比加成(dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) + equipQuality: number = 0; // hp6, 装备品质基础值(dic_zyz_equipQuality的attribute) + equipStrength: number = 0; // hp7, 装备强化值(dic_zyz_equipStrenthAttr的attr) + equipStar: number = 0; // hp8 & attr9,装备升星(dic_zyz_equipStar的mainAttr和subAttr) + equipSuit: number = 0; // hp8,套装(dic_zyz_equipSuit的effect,然后对应dic_zyz_se) + jewel: number = 0; // hp9 & attr7,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool) + stone: number = 0; // hp10, 地玉增加的固定值(dic_zyz_stone的attribute) + mainBaseUp: number = 0; // hp2, 基础成长(dic_zyz_hero的hp_up) + artifactLv: number = 0; // hp14 宝物等级(dic_zyz_artifactLvPlan的attr) + artifactQuality: number = 0; // hp14 宝物品质(dic_zyz_artifactQualityPlan的attr) + artifactSeid: number = 0; // hp9 宝物词条(dic_zyz_artifactSeid算出来的) + jewelBase: number = 0; // hp15 天晶固定属性值(jewel的基础属性) + + constructor(hid: number, attrId: number, ) { + this.hid = hid; + this.attrId = attrId; + + } + + abstract setByRoleCe(data: AttrCell): void; + abstract getValues(): number[]; + + public getHeroAttrCell() { + return { + attrId: this.attrId, + values: this.getValues() + } + } +} + +class HeroMainAttr extends HeroAllAttr { + public setByRoleCe(heroAttr: AttrCell) { + for(let i = 0; i < heroAttr.values.length; i++) { + let value = heroAttr.values[i]; + if(value != undefined) { + switch(i) { + case HERO_MAIN_ATTR_INDEX.BASE: + this.mainBase = value; break; + case HERO_MAIN_ATTR_INDEX.JOB: + this.job = value; break; + case HERO_MAIN_ATTR_INDEX.STAR_UP: + this.starUp = value; break; + case HERO_MAIN_ATTR_INDEX.CONNECT: + this.connect = value; break; + case HERO_MAIN_ATTR_INDEX.FAVOUR: + this.favour = value; break; + case HERO_MAIN_ATTR_INDEX.TALENT: + this.talent = value; break; + case HERO_MAIN_ATTR_INDEX.EQUIP_QUALITY: + this.equipQuality = value; break; + case HERO_MAIN_ATTR_INDEX.EQUIP_STRENGTH: + this.equipStrength = value; break; + case HERO_MAIN_ATTR_INDEX.EQUIP_STAR: + this.equipStar = value; break; + case HERO_MAIN_ATTR_INDEX.EQUIP_SUIT: + this.equipSuit = value; break; + case HERO_MAIN_ATTR_INDEX.JEWEL: + this.jewel = value; break; + case HERO_MAIN_ATTR_INDEX.STONE: + this.stone = value; break; + case HERO_MAIN_ATTR_INDEX.BASE_UP: + this.mainBaseUp = value; break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV: + this.artifactLv = value; break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY: + this.artifactQuality = value; break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID: + this.artifactSeid = value; break; + case HERO_MAIN_ATTR_INDEX.JEWEL_BASE: + this.jewelBase = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = HERO_MAIN_ATTR_INDEX.START; i < HERO_MAIN_ATTR_INDEX.END; i++) { + switch(i) { + case HERO_MAIN_ATTR_INDEX.BASE: + values.push(this.mainBase); + break; + case HERO_MAIN_ATTR_INDEX.JOB: + values.push(this.job); + break; + case HERO_MAIN_ATTR_INDEX.STAR_UP: + values.push(this.starUp); + break; + case HERO_MAIN_ATTR_INDEX.CONNECT: + values.push(this.connect); + break; + case HERO_MAIN_ATTR_INDEX.FAVOUR: + values.push(this.favour); + break; + case HERO_MAIN_ATTR_INDEX.TALENT: + values.push(this.talent); + break; + case HERO_MAIN_ATTR_INDEX.EQUIP_QUALITY: + values.push(this.equipQuality); + break; + case HERO_MAIN_ATTR_INDEX.EQUIP_STRENGTH: + values.push(this.equipStrength); + break; + case HERO_MAIN_ATTR_INDEX.EQUIP_STAR: + values.push(this.equipStar); + break; + case HERO_MAIN_ATTR_INDEX.EQUIP_SUIT: + values.push(this.equipSuit); + break; + case HERO_MAIN_ATTR_INDEX.JEWEL: + values.push(this.jewel); + break; + case HERO_MAIN_ATTR_INDEX.STONE: + values.push(this.stone); + break; + case HERO_MAIN_ATTR_INDEX.BASE_UP: + values.push(this.mainBaseUp); + break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_LV: + values.push(this.artifactLv); + break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_QUALITY: + values.push(this.artifactQuality); + break; + case HERO_MAIN_ATTR_INDEX.ARTIFACT_SEID: + values.push(this.artifactSeid); + break; + case HERO_MAIN_ATTR_INDEX.JEWEL_BASE: + values.push(this.jewelBase); + break; + } + } + return values; + } +} + +class HeroSubAttr extends HeroAllAttr { + public setByRoleCe(heroAttr: AttrCell) { + for(let i = 0; i < heroAttr.values.length; i++) { + let value = heroAttr.values[i]; + if(value != undefined) { + switch(i) { + case HERO_SUB_ATTR_INDEX.BASE: + this.subBase = value; break; + case HERO_SUB_ATTR_INDEX.JOB: + this.job = value; break; + case HERO_SUB_ATTR_INDEX.TALENT: + this.talent = value; break; + case HERO_SUB_ATTR_INDEX.JEWEL: + this.jewel = value; break; + case HERO_SUB_ATTR_INDEX.EQUIP_STAR: + this.equipStar = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = HERO_SUB_ATTR_INDEX.START; i < HERO_SUB_ATTR_INDEX.END; i++) { + switch(i) { + case HERO_SUB_ATTR_INDEX.BASE: + values.push(this.subBase); + break; + case HERO_SUB_ATTR_INDEX.JOB: + values.push(this.job); + break; + case HERO_SUB_ATTR_INDEX.TALENT: + values.push(this.talent); + break; + case HERO_SUB_ATTR_INDEX.JEWEL: + values.push(this.jewel); + break; + case HERO_SUB_ATTR_INDEX.EQUIP_STAR: + values.push(this.equipStar); + break; + } + } + return values; + } +} + +abstract class EquipAllAttr { + hid: number; + eplaceId: number; + attrId: number; + equipQuality: number = 0; + equipStrength: number = 0; + equipStar: number = 0; + jewel: number = 0; + stone: number = 0; + jewelBase: number = 0; + + constructor(hid: number, attrId: number) { + this.hid = hid; + this.attrId = attrId; + } + + abstract setByRoleCe(data: AttrCell): void; + abstract getValues(): number[]; + + public getEquipAttrCell() { + return { + attrId: this.attrId, + values: this.getValues() + } + } +} + +class EquipMainAttr extends EquipAllAttr { + public setByRoleCe(equipAttr: AttrCell) { + for(let i = 0; i < equipAttr.values.length; i++) { + let value = equipAttr.values[i]; + if(value != undefined) { + switch(i) { + case EQUIP_MAIN_ATTR_INDEX.EQUIP_QUALITY: + this.equipQuality = value; break; + case EQUIP_MAIN_ATTR_INDEX.EQUIP_STRENGTH: + this.equipStrength = value; break; + case EQUIP_MAIN_ATTR_INDEX.EQUIP_STAR: + this.equipStar = value; break; + case EQUIP_MAIN_ATTR_INDEX.JEWEL: + this.jewel = value; break; + case EQUIP_MAIN_ATTR_INDEX.STONE: + this.stone = value; break; + case EQUIP_MAIN_ATTR_INDEX.JEWEL_BASE: + this.jewelBase = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = EQUIP_MAIN_ATTR_INDEX.START; i < EQUIP_MAIN_ATTR_INDEX.END; i++) { + switch(i) { + case EQUIP_MAIN_ATTR_INDEX.EQUIP_QUALITY: + values.push(this.equipQuality); + break; + case EQUIP_MAIN_ATTR_INDEX.EQUIP_STRENGTH: + values.push(this.equipStrength); + break; + case EQUIP_MAIN_ATTR_INDEX.EQUIP_STAR: + values.push(this.equipStar); + break; + case EQUIP_MAIN_ATTR_INDEX.JEWEL: + values.push(this.jewel); + break; + case EQUIP_MAIN_ATTR_INDEX.STONE: + values.push(this.stone); + break; + case EQUIP_MAIN_ATTR_INDEX.JEWEL_BASE: + values.push(this.jewelBase); + break; + } + } + return values; + } +} + +class EquipSubAttr extends EquipAllAttr { + public setByRoleCe(equipAttr: AttrCell) { + for(let i = 0; i < equipAttr.values.length; i++) { + let value = equipAttr.values[i]; + if(value != undefined) { + switch(i) { + case EQUIP_SUB_ATTR_INDEX.EQUIP_STAR: + this.equipStar = value; break; + case EQUIP_SUB_ATTR_INDEX.JEWEL: + this.jewel = value; break; + } + } + } + } + + public getValues() { + let values: number[] = []; + for(let i = EQUIP_SUB_ATTR_INDEX.START; i < EQUIP_SUB_ATTR_INDEX.END; i++) { + switch(i) { + case EQUIP_SUB_ATTR_INDEX.EQUIP_STAR: + values.push(this.equipStar); + break; + case EQUIP_SUB_ATTR_INDEX.JEWEL: + values.push(this.jewel); + break; + } + } + return values; + } +} + +enum GLOBAL_MAIN_ATTR_INDEX { + START, + SCHOOL = 0, // hp5,百家学宫百分比加成(dic_zyz_schoolRate的mainAttrApercent) + TERAPH = 1, // hp11, 神像加成(直接读数据库teraph字段的值) + TITLE = 2, // hp11, 爵位加成(dic_zyz_title的hp) + SCROLL = 3, // hp11,名将谱加成(dic_zyz_heroScroll的hp) + SKIN = 4, // hp12, 皮肤加成(dic_zyz_fashion的actorAttr) + AUTH_BOOK = 5, // hp16,诸子列传 + END +} + +enum GLOBAL_SUB_ATTR_INDEX { + START, + SCHOOL = 0, // attr5, 百家学宫(根据dic_zyz_school中的upAttribute决定书院加的是那些次级属性,具体值读取dic_zyz_schoolRate中的assiAttrAddValue一列) + TERAPH = 1, // attr4, 神像加成(dic_zyz_teraph中的assistAttrValue) + TITLE = 2, // attr6, 爵位(dic_zyz_title中的pdi、mdi) + SKIN = 3, // attr8, 皮肤 + AUTH_BOOK = 4, // attr10,诸子列传 + END +} + +enum HERO_MAIN_ATTR_INDEX { + START, + BASE = 0, // hp1, 角色基础属性(dic_zyz_hero的hp) + JOB = 1, // hp1, 职业属性(dic_zyz_job的attr) + STAR_UP = 2, // hp2, 角色升星成长(dic_zyz_hero_star的hp或dic_zyz_hero_wake的hp) + CONNECT = 3, // hp3, 角色羁绊固定值(dic_zyz_friend_ship的attribute) + FAVOUR = 4, // hp4, 声望加成(dic_zyz_friend_ship_level的add) + TALENT = 5, // hp5, 天赋树百分比加成(dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) + EQUIP_QUALITY = 6, // hp6, 装备品质基础值(dic_zyz_equipQuality的attribute) + EQUIP_STRENGTH = 7, // hp7, 装备强化值(dic_zyz_equipStrenthAttr的attr) + EQUIP_STAR = 8, // hp8,装备升星(dic_zyz_equipStar的mainAttr) + EQUIP_SUIT = 9, // hp8,套装(dic_zyz_equipSuit的effect,然后对应dic_zyz_se) + JEWEL = 10, // hp9,天晶随机属性值(jewel的ranSe,对应dic_zyz_randomEffectPool) + STONE = 11, // hp10, 地玉增加的固定值(dic_zyz_stone的attribute) + BASE_UP = 12, // hp2, 角色基础属性成长(dic_zyz_hero的hp_up) + ARTIFACT_LV = 13, // hp14, 宝物等级 + ARTIFACT_QUALITY = 14, // hp14, 宝物品质 + ARTIFACT_SEID = 15, // hp9,宝物词条 + JEWEL_BASE = 16, // hp15, 天晶基础属性(dic_zyz_jewel的rareEffectBaseAttr) + END +} + +enum HERO_SUB_ATTR_INDEX { + START, + BASE = 0, // attr1,系统参数表中所有人 + JOB = 1, // attr2, 职业的attr + TALENT = 2, // attr3, 天赋树百分比加成 (dic_zyz_hero_talent的levelSeid,然后对应到dic_zyz_se) + JEWEL = 3, // attr7, 天晶随机属性(随机出来的值在dic_zyz_randomEffectPool中读最终值) + EQUIP_STAR = 4, // attr9, 精炼次级属性(dic_zyz_equipStar的subAttr) + END +} + +enum EQUIP_MAIN_ATTR_INDEX { + START, + EQUIP_QUALITY = 0, // hp6, 装备升品基础值加成(dic_zyz_equipQuality) + EQUIP_STRENGTH = 1,// hp7, 装备强化值(需改表,改为键值对) + EQUIP_STAR = 2, // hp8, 装备(dic_zyz_equipStar) + JEWEL = 3, // hp9, 天晶洗练出的主属性百分比加成,equipAttr加起来 + STONE = 4, // hp10,地玉石增加的固定值,equipAttr加起来 + JEWEL_BASE = 5, // hp15, 天晶基础属性(dic_zyz_jewel的rareEffectBaseAttr) + END +} + +enum EQUIP_SUB_ATTR_INDEX { + START, + JEWEL = 0, // attr7, 天晶随机属性(随机出来的值在dic_zyz_randomEffectPool中读最终值) + EQUIP_STAR = 1, // attr9, 精炼次级属性(dic_zyz_equipStar的subAttr) + END +} diff --git a/game-server/app/services/role/checkMaterial.ts b/game-server/app/services/role/checkMaterial.ts index 53db59292..61b669446 100644 --- a/game-server/app/services/role/checkMaterial.ts +++ b/game-server/app/services/role/checkMaterial.ts @@ -1,423 +1,423 @@ -import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE, CONSUME_TYPE, ITID_STONE_LIMIT, HERO_GROW_MAX, ABI_STAGE } from '../../consts'; -import { RoleModel, RoleType } from '../../db/Role'; -import { ItemModel, ItemType } from '../../db/Item'; -import { ItemInter, RewardInter, } from '../../pubUtils/interface'; -import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from '../../pubUtils/data'; -import { sortItems } from './util'; -import { HeroType } from '../../db/Hero'; - - -export class CheckMeterial { - private roleId: string; - private itemsIndb: Map = new Map(); // 玩家已有的东西 - private notEnoughItems: Map = new Map(); // 缺少的数量 - private consumes: ItemInter[] = []; // 消耗,正向数 - private canReplace: boolean = false; // 是否可以被通用的啥代替代替 - private tempConsumes: ItemInter[] = []; - - private goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); - private coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); - - constructor(roleId: string, role?: RoleType, items?: ItemType[]) { - this.roleId = roleId; - if (role) { - this.itemsIndb.set(this.goldId, role.gold); - this.itemsIndb.set(this.coinId, role.coin); - } - if (items && items.length) { - for (let { id, count } of items) { - this.itemsIndb.set(id, count); - } - } - } - - private pushToNotEnoughItems(id: number, count: number) { - if (!this.notEnoughItems.has(id)) { - this.notEnoughItems.set(id, 0); - } - this.notEnoughItems.set(id, this.notEnoughItems.get(id) + count); - } - - public getNotEnoughItems() { - let map = new Map(); - for (let [id, count] of this.notEnoughItems) { - map.set(id, count); - } - return map; - } - - public async decrease(goods: { id: number, count: number }[]) { - this.tempConsumes.splice(0, this.tempConsumes.length); - this.notEnoughItems.clear(); - let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST); - for (let { id, count } of items) { - let notEnoughCount = await this.decreaseItem(id, count); - if (notEnoughCount > 0) { - let isEnough = await this.checkReplaceItem(id, notEnoughCount); - if (isEnough) { - this.tempConsumes.push({ id, count: count - notEnoughCount }); - } else { - return false; - } - } - } - - if (gold.length > 0) { - let isEnough = await this.decreaseGold(gold); - if (!isEnough) return false; - } - if (coin.length > 0) { - let isEnough = await this.decreaseCoin(coin); - if (!isEnough) return false; - } - this.consumes.push(...this.tempConsumes); - return true; - } - - // 当消耗不足的时候,不提前返回,也不去算元宝和铜币 - public async decreaseItemsContinue(goods: { id: number, count: number }[]) { - this.tempConsumes.splice(0, this.tempConsumes.length); - this.notEnoughItems.clear(); - let { items } = sortItems(goods, HANDLE_REWARD_TYPE.COST); - let itemIsEnough = true; - for (let { id, count } of items) { - let notEnoughCount = await this.decreaseItem(id, count); - if (notEnoughCount > 0) { - let isEnough = await this.checkReplaceItem(id, notEnoughCount); - if (isEnough) { - this.tempConsumes.push({ id, count: count - notEnoughCount }); - } else { - itemIsEnough = false; - } - } - } - this.consumes.push(...this.tempConsumes); - return itemIsEnough; - } - - public setCanReplace(canReplace: boolean) { - this.canReplace = canReplace; - } - - private async decreaseItem(id: number, count: number) { - if (!this.itemsIndb.has(id)) { - let item = await ItemModel.findbyRoleAndGid(this.roleId, id); - if (!item) { - this.pushToNotEnoughItems(id, count); - return count; - } - this.itemsIndb.set(id, item.count); - } - if (this.itemsIndb.get(id) < count) { - let notEnoughCount = count - this.itemsIndb.get(id); - this.pushToNotEnoughItems(id, notEnoughCount); - this.itemsIndb.set(id, 0); - return notEnoughCount; - } else { - this.itemsIndb.set(id, this.itemsIndb.get(id) - count); - this.tempConsumes.push({ id, count }); - return 0 - } - } - - private async checkReplaceItem(id: number, count: number) { - if (!this.canReplace) return false; - - let relationGoodId = gameData.relationGoods.get(id); - if (!relationGoodId) return false; - - if (relationGoodId == this.goldId) { - return await this.decreaseGold([{ count }]); - } else if (relationGoodId == this.coinId) { - return await this.decreaseCoin([count]); - } else { - let cnt = await this.decreaseItem(relationGoodId, count); - return cnt == 0 - } - } - - private async decreaseGold(gold: { count: number }[]) { - - if (!this.itemsIndb.has(this.goldId)) { - let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); - this.itemsIndb.set(this.goldId, role.gold); - this.itemsIndb.set(this.coinId, role.coin); - } - let goldCost = gold.reduce((pre, cur) => { return pre + cur.count }, 0); - if (this.itemsIndb.get(this.goldId) < goldCost) { - this.pushToNotEnoughItems(this.goldId, goldCost - this.itemsIndb.get(this.goldId)); - this.itemsIndb.set(this.goldId, 0); - return false; - } - this.itemsIndb.set(this.goldId, this.itemsIndb.get(this.goldId) - goldCost); - this.tempConsumes.push({ id: this.goldId, count: goldCost }); - return true - } - - private async decreaseCoin(coin: number[]) { - - if (!this.itemsIndb.has(this.coinId)) { - let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); - this.itemsIndb.set(this.goldId, role.gold); - this.itemsIndb.set(this.coinId, role.coin); - } - let coinCost = coin.reduce((pre, cur) => pre + cur, 0); - if (this.itemsIndb.get(this.coinId) < coinCost) { - this.pushToNotEnoughItems(this.coinId, coinCost - this.itemsIndb.get(this.coinId)); - this.itemsIndb.set(this.coinId, 0); - return false; - } - this.itemsIndb.set(this.coinId, this.itemsIndb.get(this.coinId) - coinCost); - this.tempConsumes.push({ id: this.coinId, count: coinCost }); - return true; - } - - private getMaterialEnough(materials: RewardInter[], notEnoughItems: Map) { - let newMaterials: RewardInter[] = []; - for (let { id, count } of materials) { - if (notEnoughItems.has(id)) { - newMaterials.push({ id, count: count - notEnoughItems.get(id) }); - } else { - newMaterials.push({ id, count }); - } - } - return newMaterials; - } - - // 检查地玉石是否可以合成 - public async composeStone(id: number, count: number) { - let dicStone = gameData.stone.get(id); - if (!dicStone || dicStone.composeMaterial.length <= 0) return false; // 1阶石头不能再从下合成返回不行 - let materials = dicStone.composeMaterial.map(cur => ({ ...cur, count: cur.count * count })); - let isEnough = await this.decrease(materials); - if (!isEnough) { - let notEnoughItems = this.getNotEnoughItems(); - let newMaterials = this.getMaterialEnough(materials, notEnoughItems); - let isEnough = await this.decrease(newMaterials); // 消耗掉除了不足的部分以外的其他部分 - if (!isEnough) return false; - - let isAllOK = true; // 如果有石头不足,向下补充,isAllOK标识不足的都能补充上 - for (let [id, count] of notEnoughItems) { - let isEnough = await this.composeStone(id, count); - if (!isEnough) { - isAllOK = false; break; - } - } - return isAllOK; - } else { - return true; - } - } - - public getConsume() { - return this.consumes; - } -}; - -/** - * 获取升品所需消耗 - * @param id - * @returns - */ -export async function getComposeStoneNeedCost(id: number) { - let dicStone = gameData.stone.get(id); - if (!dicStone || dicStone.composeMaterial.length <= 0) return false; - return dicStone.composeMaterial; -} - -/** - * 获取当前类型6品以下玉石升级相关道具 - * @param {string} roleId - * @param {number} itId - * @returns - */ -export async function getCurItem(roleId: string, itId: number) { - let curItem = new Map(); - let stoneItId = gameData.stoneItId.get(itId); - let goodIds = []; - for (const { good_id, lv } of stoneItId) { - if (lv > ITID_STONE_LIMIT) continue; - let nextLvMaterial = await getComposeStoneNeedCost(good_id); - if (!nextLvMaterial) continue; - for (let material of nextLvMaterial) { - goodIds.push(material.id); - } - } - - let items = await ItemModel.find({ roleId, id: { $in: goodIds } }); - if (!items || items.length == 0) return curItem; - for (let { id, count } of items) { - if (count == 0) continue; - curItem.set(id, count); - } - return curItem; -} - -/** - * 计算玉石一键升品总产出与消耗 - * @param initialJewel - * @param curItem - * @returns - */ -export async function getComposeStoneCostAndAdd(curItem, itId) { - let allAddItem = new Map(); - let allCostItem = new Map(); - - //计算升品所需消耗 - for (let lv = ITID_STONE_LIMIT - 1; lv >= 1; lv--) { - for (let indexLv = lv; indexLv < ITID_STONE_LIMIT; indexLv++) { - let id = gameData.stoneItIdLv.get(`${itId}_${indexLv}`); - let tempItem1 = curItem.get(id) || 0; - let tempItem2 = allAddItem.get(id) || 0 - let count = tempItem1 + tempItem2; - if (count == 0) continue;//当前品没有,无法进行升下一品 - - let nextLvId = gameData.stoneItIdLv.get(`${itId}_${indexLv + 1}`); - if (!nextLvId) continue; //不存在下一品 - - //计算升到下一阶消耗 - let nextLvMaterial = await getComposeStoneNeedCost(nextLvId); - if (!nextLvMaterial || nextLvMaterial.length == 0) { - //升下一品不存在消耗 - //产出 - let addCount = allAddItem.get(nextLvId) || 0 - allAddItem.set(nextLvId, addCount + count); - continue; - } - - // 计算能升品的下一品新增数量 - //设置初始数量 - let initial = nextLvMaterial[0]; - if (!initial.count || initial.count == 0) { - console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId); - continue; - } - let val1 = curItem.get(initial.id) || 0; - let val2 = allAddItem.get(initial.id) || 0; - let nextLvCount = Math.floor((val1 + val2) / initial.count);//设置初始值 - - for (let material of nextLvMaterial) { - if (!material.count || material.count == 0) { - nextLvCount = 0; - console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId); - continue; - } - let tempCount1 = curItem.get(material.id) || 0; - let tempCount2 = allAddItem.get(material.id) || 0; - nextLvCount = Math.min(nextLvCount, Math.floor((tempCount1 + tempCount2) / material.count)); - } - - if (nextLvCount == 0) { - // console.log('---------------- curItem', curItem); - // console.log('---------------- indexLv', indexLv); - // console.log('---------------- nextLvCount', nextLvCount); - // console.log('---------------- allCostItem', allCostItem); - // console.log('---------------- allAddItem', allAddItem); - continue;// 不能升品 - } - - // 消耗 - for (let material of nextLvMaterial) { - let needCostCount = nextLvCount * material.count; //需要消耗数量 - let tempCount1 = curItem.get(material.id) || 0; // 当前item中已有的数量 - let tempCount2 = allAddItem.get(material.id) || 0; // 当前总产出中已有的数量 - let tempCostCount = allCostItem.get(material.id) || 0; // 当前总消耗中已有的数量 - - let diff = tempCount1 - needCostCount; - if (diff > 0) {// 先消耗item中的 - curItem.set(material.id, diff); - allCostItem.set(material.id, tempCostCount + needCostCount); //记录入总消耗(仅item中,allAddItem消耗会在其中减掉) - continue; - } - - curItem.delete(material.id); - if (tempCount1 != 0) allCostItem.set(material.id, tempCostCount + tempCount1);//记录入总消耗(0不记录) - - - if (tempCount2 - Math.abs(diff) < 0) return;//异常 - - allAddItem.set(material.id, (tempCount2 - Math.abs(diff))); - } - - // 产出 - let addCount = allAddItem.get(nextLvId) || 0 - allAddItem.set(nextLvId, addCount + nextLvCount); - } - } - - // console.log('---------------- allCostItem', allCostItem); - // console.log('---------------- allAddItem', allAddItem); - - return { allCostItem, allAddItem }; -} - - - -/** - * 计算升到6彩后剩余碎片 - * @param roleId - * @param hid - * @returns - */ -export async function calUpSixColorsResidueFragment(roleId: string, hero: HeroType, hid: number, count?: number) { - let needFragment = 0; - - let dicHero = gameData.hero.get(hid); - if (!dicHero) return; - let { pieceId, jobid } = dicHero; - - let dicJob = gameData.job.get(jobid); - if (!dicJob) return; - - let curItemCount = count; - if (!count) { - let item = await ItemModel.findbyRoleAndGid(roleId, pieceId); - curItemCount = item?.count || 0; - } - if (curItemCount < 0) return; - - let { star: oldStar, starStage: oldStarStage, quality: oldQuality, colorStar: oldColorStar, colorStarStage: oldColorStarStage, } = hero; - - // 计算升星 - if (oldStar < HERO_GROW_MAX.STAR) { - for (let starIndex = oldStar; starIndex < HERO_GROW_MAX.STAR; starIndex++) { - const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, oldQuality, starIndex); - if (starIndex == oldStar) { - needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * (ABI_STAGE.END - oldStarStage); - continue; - } - needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * ABI_STAGE.END; - } - } - if (curItemCount < needFragment) return; - - // 计算升品 - if (oldQuality < HERO_GROW_MAX.QUALITY) { - for (let qualityIndex = oldQuality; qualityIndex < HERO_GROW_MAX.QUALITY; qualityIndex++) { - const curDicHeroQualityUp = gameData.heroQualityUp.get(qualityIndex); - needFragment += curDicHeroQualityUp?.fragmentNum || 0; - } - } - if (curItemCount < needFragment) return; - - // 计算觉醒升6彩 - if (oldColorStar < HERO_GROW_MAX.COLORSTAR) { - for (let colorStarIndex = oldColorStar; colorStarIndex < 6; colorStarIndex++) { - const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, colorStarIndex) - if (colorStarIndex == 0) { - needFragment += curDicHeroStar?.fragmentNum || 0; - continue; - } - if (colorStarIndex == oldColorStar) { - needFragment += (curDicHeroStar?.fragmentNum || 0) * (ABI_STAGE.END - oldColorStarStage); - continue; - } - needFragment += (curDicHeroStar?.fragmentNum || 0) * ABI_STAGE.END; - - } - } - if (curItemCount < needFragment) return; - - - return curItemCount - needFragment; -} \ No newline at end of file +import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE, CONSUME_TYPE, ITID_STONE_LIMIT, HERO_GROW_MAX, ABI_STAGE } from '@consts'; +import { RoleModel, RoleType } from '@db/Role'; +import { ItemModel, ItemType } from '@db/Item'; +import { ItemInter, RewardInter, } from '@pubUtils/interface'; +import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from '@pubUtils/data'; +import { sortItems } from './util'; +import { HeroType } from '@db/Hero'; + + +export class CheckMeterial { + private roleId: string; + private itemsIndb: Map = new Map(); // 玩家已有的东西 + private notEnoughItems: Map = new Map(); // 缺少的数量 + private consumes: ItemInter[] = []; // 消耗,正向数 + private canReplace: boolean = false; // 是否可以被通用的啥代替代替 + private tempConsumes: ItemInter[] = []; + + private goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); + private coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); + + constructor(roleId: string, role?: RoleType, items?: ItemType[]) { + this.roleId = roleId; + if (role) { + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + if (items && items.length) { + for (let { id, count } of items) { + this.itemsIndb.set(id, count); + } + } + } + + private pushToNotEnoughItems(id: number, count: number) { + if (!this.notEnoughItems.has(id)) { + this.notEnoughItems.set(id, 0); + } + this.notEnoughItems.set(id, this.notEnoughItems.get(id) + count); + } + + public getNotEnoughItems() { + let map = new Map(); + for (let [id, count] of this.notEnoughItems) { + map.set(id, count); + } + return map; + } + + public async decrease(goods: { id: number, count: number }[]) { + this.tempConsumes.splice(0, this.tempConsumes.length); + this.notEnoughItems.clear(); + let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST); + for (let { id, count } of items) { + let notEnoughCount = await this.decreaseItem(id, count); + if (notEnoughCount > 0) { + let isEnough = await this.checkReplaceItem(id, notEnoughCount); + if (isEnough) { + this.tempConsumes.push({ id, count: count - notEnoughCount }); + } else { + return false; + } + } + } + + if (gold.length > 0) { + let isEnough = await this.decreaseGold(gold); + if (!isEnough) return false; + } + if (coin.length > 0) { + let isEnough = await this.decreaseCoin(coin); + if (!isEnough) return false; + } + this.consumes.push(...this.tempConsumes); + return true; + } + + // 当消耗不足的时候,不提前返回,也不去算元宝和铜币 + public async decreaseItemsContinue(goods: { id: number, count: number }[]) { + this.tempConsumes.splice(0, this.tempConsumes.length); + this.notEnoughItems.clear(); + let { items } = sortItems(goods, HANDLE_REWARD_TYPE.COST); + let itemIsEnough = true; + for (let { id, count } of items) { + let notEnoughCount = await this.decreaseItem(id, count); + if (notEnoughCount > 0) { + let isEnough = await this.checkReplaceItem(id, notEnoughCount); + if (isEnough) { + this.tempConsumes.push({ id, count: count - notEnoughCount }); + } else { + itemIsEnough = false; + } + } + } + this.consumes.push(...this.tempConsumes); + return itemIsEnough; + } + + public setCanReplace(canReplace: boolean) { + this.canReplace = canReplace; + } + + private async decreaseItem(id: number, count: number) { + if (!this.itemsIndb.has(id)) { + let item = await ItemModel.findbyRoleAndGid(this.roleId, id); + if (!item) { + this.pushToNotEnoughItems(id, count); + return count; + } + this.itemsIndb.set(id, item.count); + } + if (this.itemsIndb.get(id) < count) { + let notEnoughCount = count - this.itemsIndb.get(id); + this.pushToNotEnoughItems(id, notEnoughCount); + this.itemsIndb.set(id, 0); + return notEnoughCount; + } else { + this.itemsIndb.set(id, this.itemsIndb.get(id) - count); + this.tempConsumes.push({ id, count }); + return 0 + } + } + + private async checkReplaceItem(id: number, count: number) { + if (!this.canReplace) return false; + + let relationGoodId = gameData.relationGoods.get(id); + if (!relationGoodId) return false; + + if (relationGoodId == this.goldId) { + return await this.decreaseGold([{ count }]); + } else if (relationGoodId == this.coinId) { + return await this.decreaseCoin([count]); + } else { + let cnt = await this.decreaseItem(relationGoodId, count); + return cnt == 0 + } + } + + private async decreaseGold(gold: { count: number }[]) { + + if (!this.itemsIndb.has(this.goldId)) { + let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + let goldCost = gold.reduce((pre, cur) => { return pre + cur.count }, 0); + if (this.itemsIndb.get(this.goldId) < goldCost) { + this.pushToNotEnoughItems(this.goldId, goldCost - this.itemsIndb.get(this.goldId)); + this.itemsIndb.set(this.goldId, 0); + return false; + } + this.itemsIndb.set(this.goldId, this.itemsIndb.get(this.goldId) - goldCost); + this.tempConsumes.push({ id: this.goldId, count: goldCost }); + return true + } + + private async decreaseCoin(coin: number[]) { + + if (!this.itemsIndb.has(this.coinId)) { + let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); + this.itemsIndb.set(this.goldId, role.gold); + this.itemsIndb.set(this.coinId, role.coin); + } + let coinCost = coin.reduce((pre, cur) => pre + cur, 0); + if (this.itemsIndb.get(this.coinId) < coinCost) { + this.pushToNotEnoughItems(this.coinId, coinCost - this.itemsIndb.get(this.coinId)); + this.itemsIndb.set(this.coinId, 0); + return false; + } + this.itemsIndb.set(this.coinId, this.itemsIndb.get(this.coinId) - coinCost); + this.tempConsumes.push({ id: this.coinId, count: coinCost }); + return true; + } + + private getMaterialEnough(materials: RewardInter[], notEnoughItems: Map) { + let newMaterials: RewardInter[] = []; + for (let { id, count } of materials) { + if (notEnoughItems.has(id)) { + newMaterials.push({ id, count: count - notEnoughItems.get(id) }); + } else { + newMaterials.push({ id, count }); + } + } + return newMaterials; + } + + // 检查地玉石是否可以合成 + public async composeStone(id: number, count: number) { + let dicStone = gameData.stone.get(id); + if (!dicStone || dicStone.composeMaterial.length <= 0) return false; // 1阶石头不能再从下合成返回不行 + let materials = dicStone.composeMaterial.map(cur => ({ ...cur, count: cur.count * count })); + let isEnough = await this.decrease(materials); + if (!isEnough) { + let notEnoughItems = this.getNotEnoughItems(); + let newMaterials = this.getMaterialEnough(materials, notEnoughItems); + let isEnough = await this.decrease(newMaterials); // 消耗掉除了不足的部分以外的其他部分 + if (!isEnough) return false; + + let isAllOK = true; // 如果有石头不足,向下补充,isAllOK标识不足的都能补充上 + for (let [id, count] of notEnoughItems) { + let isEnough = await this.composeStone(id, count); + if (!isEnough) { + isAllOK = false; break; + } + } + return isAllOK; + } else { + return true; + } + } + + public getConsume() { + return this.consumes; + } +}; + +/** + * 获取升品所需消耗 + * @param id + * @returns + */ +export async function getComposeStoneNeedCost(id: number) { + let dicStone = gameData.stone.get(id); + if (!dicStone || dicStone.composeMaterial.length <= 0) return false; + return dicStone.composeMaterial; +} + +/** + * 获取当前类型6品以下玉石升级相关道具 + * @param {string} roleId + * @param {number} itId + * @returns + */ +export async function getCurItem(roleId: string, itId: number) { + let curItem = new Map(); + let stoneItId = gameData.stoneItId.get(itId); + let goodIds = []; + for (const { good_id, lv } of stoneItId) { + if (lv > ITID_STONE_LIMIT) continue; + let nextLvMaterial = await getComposeStoneNeedCost(good_id); + if (!nextLvMaterial) continue; + for (let material of nextLvMaterial) { + goodIds.push(material.id); + } + } + + let items = await ItemModel.find({ roleId, id: { $in: goodIds } }); + if (!items || items.length == 0) return curItem; + for (let { id, count } of items) { + if (count == 0) continue; + curItem.set(id, count); + } + return curItem; +} + +/** + * 计算玉石一键升品总产出与消耗 + * @param initialJewel + * @param curItem + * @returns + */ +export async function getComposeStoneCostAndAdd(curItem, itId) { + let allAddItem = new Map(); + let allCostItem = new Map(); + + //计算升品所需消耗 + for (let lv = ITID_STONE_LIMIT - 1; lv >= 1; lv--) { + for (let indexLv = lv; indexLv < ITID_STONE_LIMIT; indexLv++) { + let id = gameData.stoneItIdLv.get(`${itId}_${indexLv}`); + let tempItem1 = curItem.get(id) || 0; + let tempItem2 = allAddItem.get(id) || 0 + let count = tempItem1 + tempItem2; + if (count == 0) continue;//当前品没有,无法进行升下一品 + + let nextLvId = gameData.stoneItIdLv.get(`${itId}_${indexLv + 1}`); + if (!nextLvId) continue; //不存在下一品 + + //计算升到下一阶消耗 + let nextLvMaterial = await getComposeStoneNeedCost(nextLvId); + if (!nextLvMaterial || nextLvMaterial.length == 0) { + //升下一品不存在消耗 + //产出 + let addCount = allAddItem.get(nextLvId) || 0 + allAddItem.set(nextLvId, addCount + count); + continue; + } + + // 计算能升品的下一品新增数量 + //设置初始数量 + let initial = nextLvMaterial[0]; + if (!initial.count || initial.count == 0) { + console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId); + continue; + } + let val1 = curItem.get(initial.id) || 0; + let val2 = allAddItem.get(initial.id) || 0; + let nextLvCount = Math.floor((val1 + val2) / initial.count);//设置初始值 + + for (let material of nextLvMaterial) { + if (!material.count || material.count == 0) { + nextLvCount = 0; + console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId); + continue; + } + let tempCount1 = curItem.get(material.id) || 0; + let tempCount2 = allAddItem.get(material.id) || 0; + nextLvCount = Math.min(nextLvCount, Math.floor((tempCount1 + tempCount2) / material.count)); + } + + if (nextLvCount == 0) { + // console.log('---------------- curItem', curItem); + // console.log('---------------- indexLv', indexLv); + // console.log('---------------- nextLvCount', nextLvCount); + // console.log('---------------- allCostItem', allCostItem); + // console.log('---------------- allAddItem', allAddItem); + continue;// 不能升品 + } + + // 消耗 + for (let material of nextLvMaterial) { + let needCostCount = nextLvCount * material.count; //需要消耗数量 + let tempCount1 = curItem.get(material.id) || 0; // 当前item中已有的数量 + let tempCount2 = allAddItem.get(material.id) || 0; // 当前总产出中已有的数量 + let tempCostCount = allCostItem.get(material.id) || 0; // 当前总消耗中已有的数量 + + let diff = tempCount1 - needCostCount; + if (diff > 0) {// 先消耗item中的 + curItem.set(material.id, diff); + allCostItem.set(material.id, tempCostCount + needCostCount); //记录入总消耗(仅item中,allAddItem消耗会在其中减掉) + continue; + } + + curItem.delete(material.id); + if (tempCount1 != 0) allCostItem.set(material.id, tempCostCount + tempCount1);//记录入总消耗(0不记录) + + + if (tempCount2 - Math.abs(diff) < 0) return;//异常 + + allAddItem.set(material.id, (tempCount2 - Math.abs(diff))); + } + + // 产出 + let addCount = allAddItem.get(nextLvId) || 0 + allAddItem.set(nextLvId, addCount + nextLvCount); + } + } + + // console.log('---------------- allCostItem', allCostItem); + // console.log('---------------- allAddItem', allAddItem); + + return { allCostItem, allAddItem }; +} + + + +/** + * 计算升到6彩后剩余碎片 + * @param roleId + * @param hid + * @returns + */ +export async function calUpSixColorsResidueFragment(roleId: string, hero: HeroType, hid: number, count?: number) { + let needFragment = 0; + + let dicHero = gameData.hero.get(hid); + if (!dicHero) return; + let { pieceId, jobid } = dicHero; + + let dicJob = gameData.job.get(jobid); + if (!dicJob) return; + + let curItemCount = count; + if (!count) { + let item = await ItemModel.findbyRoleAndGid(roleId, pieceId); + curItemCount = item?.count || 0; + } + if (curItemCount < 0) return; + + let { star: oldStar, starStage: oldStarStage, quality: oldQuality, colorStar: oldColorStar, colorStarStage: oldColorStarStage, } = hero; + + // 计算升星 + if (oldStar < HERO_GROW_MAX.STAR) { + for (let starIndex = oldStar; starIndex < HERO_GROW_MAX.STAR; starIndex++) { + const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, oldQuality, starIndex); + if (starIndex == oldStar) { + needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * (ABI_STAGE.END - oldStarStage); + continue; + } + needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * ABI_STAGE.END; + } + } + if (curItemCount < needFragment) return; + + // 计算升品 + if (oldQuality < HERO_GROW_MAX.QUALITY) { + for (let qualityIndex = oldQuality; qualityIndex < HERO_GROW_MAX.QUALITY; qualityIndex++) { + const curDicHeroQualityUp = gameData.heroQualityUp.get(qualityIndex); + needFragment += curDicHeroQualityUp?.fragmentNum || 0; + } + } + if (curItemCount < needFragment) return; + + // 计算觉醒升6彩 + if (oldColorStar < HERO_GROW_MAX.COLORSTAR) { + for (let colorStarIndex = oldColorStar; colorStarIndex < 6; colorStarIndex++) { + const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, colorStarIndex) + if (colorStarIndex == 0) { + needFragment += curDicHeroStar?.fragmentNum || 0; + continue; + } + if (colorStarIndex == oldColorStar) { + needFragment += (curDicHeroStar?.fragmentNum || 0) * (ABI_STAGE.END - oldColorStarStage); + continue; + } + needFragment += (curDicHeroStar?.fragmentNum || 0) * ABI_STAGE.END; + + } + } + if (curItemCount < needFragment) return; + + + return curItemCount - needFragment; +} diff --git a/game-server/app/services/role/createHero.ts b/game-server/app/services/role/createHero.ts index 267620da3..b8ddcfcbf 100644 --- a/game-server/app/services/role/createHero.ts +++ b/game-server/app/services/role/createHero.ts @@ -1,103 +1,103 @@ -import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM, COUNTER, PUSH_ROUTE } from "../../consts"; -import { SkinModel } from "../../db/Skin"; -import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero"; -import { SkinUpdate } from "../../db/Skin"; -import { nowSeconds } from "../../pubUtils/timeUtil"; -import { CreateHeroParam, HeroParam, HeroShowParam } from "../../domain/roleField/hero"; -import { ItemInter, RewardInter } from "../../pubUtils/interface"; -import { transPiece } from "./util"; -import { addItems, unlockFigure, } from "./rewardService"; -import { CounterModel } from "../../db/Counter"; -import { calculateCes } from "../playerCeService"; -import { RoleUpdate } from "../../db/Role"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { checkTaskInCreateHero } from "../task/taskService"; -import { filterHeroes } from "../dataService"; -import { pushGetHero } from "../sysChatService"; - -/** - * 创建多个武将 - * @param roleId - * @param sid - * @param serverId - * @param heroInfo - */ - export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[], initRoleInfos?: RoleUpdate) { - heroInfo = filterHeroes(heroInfo, obj => obj.hid, roleId); - let hids = heroInfo.map(cur => cur.hid); - let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId); - - let createHeroeInfos: CreateHeroParam[] = [], pieces: ItemInter[] = []; - for (let h of heroInfo) { - let heroCount = h.count || 1; - if (userHeroesMap.has(h.hid)) { - let { pieceId, count } = transPiece(h.hid); - pieces.push({ id: pieceId, count: count * heroCount }); - } else { - createHeroeInfos.push(h); - userHeroesMap.set(h.hid, null); - if (heroCount > 1) { - let { pieceId, count } = transPiece(h.hid); - pieces.push({ id: pieceId, count: count * (heroCount - 1) }); - } - } - } - - let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], showHeroes: HeroShowParam[] = []; - let figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = []; - let incHeroNum = 0; - let skins: SkinUpdate[] = []; - if (createHeroeInfos.length > 0) { - let heroInfos = new Map(); - for(let {hid, ...info} of createHeroeInfos) { - let originSkins = await SkinModel.findbyRoleAndHid(roleId, hid); - let initSkin = SkinModel.getInitInfo(hid); - skins.push(initSkin); // 初始皮肤 - let seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1; - let initHeroSkins = [initSkin, ...originSkins].map((skin, index) => new HeroSkin(skin, index == 0)); - let initHero = HeroModel.getInitInfo(hid, { ...info, seqId, serverId, roleId, roleName, skins: initHeroSkins }); - heroInfos.set(hid, initHero); - figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid }); - incHeroNum ++; - } - await unlockFigure(sid, roleId, figureConditions); - - let roleUpdata: RoleUpdate = { heroNumUpdatedAt: nowSeconds() }; - if(initRoleInfos) { - roleUpdata = { ...initRoleInfos, ...roleUpdata } - } - let { heroes } = await calculateCes(HERO_SYSTEM_TYPE.INIT, roleId, serverId, sid, heroInfos, roleUpdata, { heroNum: incHeroNum }, { isInitRole: !!initRoleInfos }); - for(let hero of heroes) { - showHeroes.push(new HeroShowParam(hero)); - resultHeroes.push(hero); - pushGetHero(roleId, roleName, serverId, hero); - } - - await SkinModel.insertSkins(roleId, roleName, skins); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, getSkinPushMsg(resultHeroes, skins), sid); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_UPDATE, { heroes: heroes.map(hero => new HeroParam(hero)) }, sid); - } - - if (pieces.length > 0) { - let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE); - resultItems = goods; - } - await checkTaskInCreateHero(serverId, roleId, sid, resultHeroes.length, resultHeroes); - return { heroes: showHeroes, resultHeroes, goods: resultItems } -} - -export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) { - let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]); - return result; -} - -function getSkinPushMsg(resultHeroes: HeroType[], skins: SkinUpdate[]) { - let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息 - for(let { hid, skins } of resultHeroes) { - skinPushMessages.heros.push({ hid, skins }); - } - for(let { id, hid } of skins) { - skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN }) - } - return skinPushMessages; -} \ No newline at end of file +import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM, COUNTER, PUSH_ROUTE } from "@consts"; +import { SkinModel } from "@db/Skin"; +import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "@db/Hero"; +import { SkinUpdate } from "@db/Skin"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { CreateHeroParam, HeroParam, HeroShowParam } from "@domain/roleField/hero"; +import { ItemInter, RewardInter } from "@pubUtils/interface"; +import { transPiece } from "./util"; +import { addItems, unlockFigure, } from "./rewardService"; +import { CounterModel } from "@db/Counter"; +import { calculateCes } from "../playerCeService"; +import { RoleUpdate } from "@db/Role"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { checkTaskInCreateHero } from "../task/taskService"; +import { filterHeroes } from "../dataService"; +import { pushGetHero } from "../sysChatService"; + +/** + * 创建多个武将 + * @param roleId + * @param sid + * @param serverId + * @param heroInfo + */ + export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[], initRoleInfos?: RoleUpdate) { + heroInfo = filterHeroes(heroInfo, obj => obj.hid, roleId); + let hids = heroInfo.map(cur => cur.hid); + let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId); + + let createHeroeInfos: CreateHeroParam[] = [], pieces: ItemInter[] = []; + for (let h of heroInfo) { + let heroCount = h.count || 1; + if (userHeroesMap.has(h.hid)) { + let { pieceId, count } = transPiece(h.hid); + pieces.push({ id: pieceId, count: count * heroCount }); + } else { + createHeroeInfos.push(h); + userHeroesMap.set(h.hid, null); + if (heroCount > 1) { + let { pieceId, count } = transPiece(h.hid); + pieces.push({ id: pieceId, count: count * (heroCount - 1) }); + } + } + } + + let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], showHeroes: HeroShowParam[] = []; + let figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = []; + let incHeroNum = 0; + let skins: SkinUpdate[] = []; + if (createHeroeInfos.length > 0) { + let heroInfos = new Map(); + for(let {hid, ...info} of createHeroeInfos) { + let originSkins = await SkinModel.findbyRoleAndHid(roleId, hid); + let initSkin = SkinModel.getInitInfo(hid); + skins.push(initSkin); // 初始皮肤 + let seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1; + let initHeroSkins = [initSkin, ...originSkins].map((skin, index) => new HeroSkin(skin, index == 0)); + let initHero = HeroModel.getInitInfo(hid, { ...info, seqId, serverId, roleId, roleName, skins: initHeroSkins }); + heroInfos.set(hid, initHero); + figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid }); + incHeroNum ++; + } + await unlockFigure(sid, roleId, figureConditions); + + let roleUpdata: RoleUpdate = { heroNumUpdatedAt: nowSeconds() }; + if(initRoleInfos) { + roleUpdata = { ...initRoleInfos, ...roleUpdata } + } + let { heroes } = await calculateCes(HERO_SYSTEM_TYPE.INIT, roleId, serverId, sid, heroInfos, roleUpdata, { heroNum: incHeroNum }, { isInitRole: !!initRoleInfos }); + for(let hero of heroes) { + showHeroes.push(new HeroShowParam(hero)); + resultHeroes.push(hero); + pushGetHero(roleId, roleName, serverId, hero); + } + + await SkinModel.insertSkins(roleId, roleName, skins); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, getSkinPushMsg(resultHeroes, skins), sid); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_UPDATE, { heroes: heroes.map(hero => new HeroParam(hero)) }, sid); + } + + if (pieces.length > 0) { + let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE); + resultItems = goods; + } + await checkTaskInCreateHero(serverId, roleId, sid, resultHeroes.length, resultHeroes); + return { heroes: showHeroes, resultHeroes, goods: resultItems } +} + +export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) { + let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]); + return result; +} + +function getSkinPushMsg(resultHeroes: HeroType[], skins: SkinUpdate[]) { + let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息 + for(let { hid, skins } of resultHeroes) { + skinPushMessages.heros.push({ hid, skins }); + } + for(let { id, hid } of skins) { + skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN }) + } + return skinPushMessages; +} diff --git a/game-server/app/services/role/resonanceService.ts b/game-server/app/services/role/resonanceService.ts index c421881a7..61767af15 100644 --- a/game-server/app/services/role/resonanceService.ts +++ b/game-server/app/services/role/resonanceService.ts @@ -1,488 +1,488 @@ -import { EQUIP_EPLACEID, EQUIP_STONE, FRIENDSHIP_INDEX, HERO_SYSTEM_TYPE, LINEUP_NUM, RESONANCE, RESONANCE_SORT_TYPE } from "../../consts"; -import { ArtifactModel } from "../../db/Artifact"; -import { EPlace, HeroModel, HeroType } from "../../db/Hero"; -import { JewelModel, JewelType } from "../../db/Jewel"; -import { ResonanceModel, ResonanceType } from "../../db/Resonance"; -import { RoleModel } from "../../db/Role"; -import { HeroParam } from "../../domain/roleField/hero"; -import { gameData, getEquipByJobClassAndEPlace } from "../../pubUtils/data"; -import { ReturnResonanceParam } from "../../pubUtils/interface"; -import { calculateCeWithHeroes } from "../playerCeService"; -import { getNewJob, initSkinTalent } from "../roleService"; -import { pick } from 'underscore'; -import * as util from 'util'; - -export async function refreshResonanceData(roleId: string, serverId: number, sid: string) { - let resonanceDatas: ReturnResonanceParam[] = []; - let resonanceLv = {}, resonanceJob = {}, resonanceCon = [], resonanceEquip = [], resonanceEpQuality = [], resonanceEpStar = [], resonanceJewel = [], resonanceStone = []; - - let role = await RoleModel.findByRoleId(roleId); - let topHids = role.topLineup.map(cur => cur.hid); - if (topHids.length < LINEUP_NUM) return { resonanceDatas }; - - let { dbResonanceMap, newPositionArr, posHids } = await getResonanceDataMap(roleId); - resonanceDatas = newPositionArr; - - let dbHeroes: HeroType[] = await HeroModel.findByHidsAndRole(roleId, [...topHids, ...posHids]); - - let topLineHeroes: HeroType[] = []; - for (const top of role.topLineup) { - topLineHeroes.push(dbHeroes.find(cur => cur.hid == top.hid)); - } - - let dbJewelMap = await getJewelDataMap(dbHeroes); - - // 武将等级 - let topLineHero: HeroType = sortData(topLineHeroes, RESONANCE_SORT_TYPE.LV); - resonanceLv = { hid: topLineHero.hid, lv: topLineHero.lv }; - for (let [hid] of dbResonanceMap) { - let hero = dbHeroes.find(cur => cur.hid == hid); - hero.lv = topLineHero.lv; - hero.exp = topLineHero.exp; - } - - // 职业(职阶、天赋) - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JOBSTAGE); - resonanceJob = { hid: topLineHero.hid, job: topLineHero.job, jobStage: topLineHero.jobStage }; - for (let [hid] of dbResonanceMap) { - let hero = dbHeroes.find(cur => cur.hid == hid); - let preJobStage = hero.jobStage; - hero.jobStage = topLineHero.jobStage; - hero.job = getNewJob(hero, topLineHero.job); - - if (preJobStage != hero.jobStage) { - //天赋树置空 - hero.skins = initSkinTalent(hero.skins || []); - } - } - - // 羁绊1, 2, 3 - for (let index = 1; index <= FRIENDSHIP_INDEX.THREE; index++) { - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.CONNECT, index); - const topDicShipId = gameData.friendShipByIndex.get(`${topLineHero.hid}_${index}`); - const topShipData = (topLineHero.connections || []).find(cur => cur.shipId == topDicShipId); - resonanceCon.push({ hid: topLineHero.hid, index, level: topShipData?.level || 0 }); - if (!topShipData) continue; - for (let [hid] of dbResonanceMap) { - let hero = dbHeroes.find(cur => cur.hid == hid); - const dicShipId = gameData.friendShipByIndex.get(`${hero.hid}_${index}`) - let shipData = hero.connections.find(cur => cur.shipId == dicShipId); - const dicShipData = gameData.friendShipsByLv.get(`${hid}_${dicShipId}_${topShipData?.level || 0}`); - let sign = true; - for (let hi of dicShipData?.hids || []) { - if (!dbHeroes.find(cur => cur.hid == hi)) { - sign = false; - break; - } - } - if (!sign) continue; - if (!shipData) hero.connections.push({ shipId: dicShipId, level: topShipData?.level || 0, exp: topShipData?.exp || 0 }); - else { - shipData.shipId = dicShipId - shipData.exp = topShipData?.exp || 0; - shipData.level = topShipData?.level || 0; - } - - } - } - - // 装备 1武器,2衣甲,3帽子,4鞋子 - for (let id = 1; id <= EQUIP_EPLACEID.SHOE_ID; id++) { - //装备强化 - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_LV, id); - let topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); - if (!topLineHeroEplace) - resonanceEquip.push({ hid: topLineHero.hid, id, lv: 0 }); - else - resonanceEquip.push({ hid: topLineHero.hid, id, lv: topLineHeroEplace?.lv || 0 }); - - for (let [hid] of dbResonanceMap) { - if (!topLineHeroEplace || !topLineHeroEplace.lv) continue; - let hero = dbHeroes.find(cur => cur.hid == hid); - let ePlaceData = hero.ePlace.find(cur => cur.id == id); - if (!ePlaceData) { - hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); - ePlaceData = hero.ePlace.find(cur => cur.id == id); - } - ePlaceData.lv = topLineHeroEplace.lv; - } - - //装备升品 - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_QUALITY, id); - topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); - if (!topLineHeroEplace) - resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: 0, qualityStage: 0 }) - else - resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: topLineHeroEplace?.quality || 0, qualityStage: topLineHeroEplace?.qualityStage || 0 }) - - for (let [hid] of dbResonanceMap) { - if (!topLineHeroEplace || (!topLineHeroEplace.quality && !topLineHeroEplace.qualityStage)) continue; - let hero = dbHeroes.find(cur => cur.hid == hid); - let ePlaceData = hero.ePlace.find(cur => cur.id == id); - if (!ePlaceData) { - hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); - ePlaceData = hero.ePlace.find(cur => cur.id == id); - }; - ePlaceData.quality = topLineHeroEplace.quality; - ePlaceData.qualityStage = topLineHeroEplace.qualityStage; - } - - //装备精练 - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_STAR, id); - topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); - if (!topLineHeroEplace) - resonanceEpStar.push({ hid: topLineHero.hid, id, star: 0, starStage: 0 }) - else - resonanceEpStar.push({ hid: topLineHero.hid, id, star: topLineHeroEplace?.star || 0, starStage: topLineHeroEplace?.starStage || 0 }) - - for (let [hid] of dbResonanceMap) { - if (!topLineHeroEplace || (!topLineHeroEplace.star && !topLineHeroEplace.starStage)) continue; - let hero = dbHeroes.find(cur => cur.hid == hid); - let ePlaceData = hero.ePlace.find(cur => cur.id == id); - if (!ePlaceData) { - hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); - ePlaceData = hero.ePlace.find(cur => cur.id == id); - }; - ePlaceData.star = topLineHeroEplace.star; - ePlaceData.starStage = topLineHeroEplace.starStage; - } - - //天晶 - if (RESONANCE.JEWEL) { - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JEWEL, id, dbJewelMap); - topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); - if (!topLineHeroEplace) - resonanceJewel.push({ hid: topLineHero.hid, id, jewel: 0 }); - else - resonanceJewel.push({ hid: topLineHero.hid, id, jewel: topLineHeroEplace?.jewel || 0 }); - - //破,御,护,命 - for (let [hid] of dbResonanceMap) { - if (!topLineHeroEplace || !topLineHeroEplace.jewel) continue; - let hero = dbHeroes.find(cur => cur.hid == hid); - let ePlaceData = hero.ePlace.find(cur => cur.id == id); - if (!ePlaceData) { - hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); - ePlaceData = hero.ePlace.find(cur => cur.id == id); - }; - ePlaceData.jewel = topLineHeroEplace.jewel; - } - } - - //地玉 - if (RESONANCE.STONE) { - //破,御,护,命 1,2,3 - resonanceStone.push({ id, stones: [] }); - for (let index = 1; index <= EQUIP_STONE.THREE; index++) { - topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.STONE, id, null, index); - topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); - resonanceStone.find(cur => cur.id == id).stones.push({ hid: topLineHero.hid, id: index, stone: 0 }); - if (topLineHeroEplace && topLineHeroEplace.stones) { - const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index); - if (topLineHeroStone) - resonanceStone.find(cur => cur.id == id).stones.find(cur => cur.id == index).stone = topLineHeroStone.stone; - } - - for (let [hid] of dbResonanceMap) { - if (!topLineHeroEplace || !topLineHeroEplace.stones) continue; - const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index); - if (!topLineHeroStone || !topLineHeroStone.stone) continue; - let hero = dbHeroes.find(cur => cur.hid == hid); - let ePlaceData = hero.ePlace.find(cur => cur.id == id); - if (!ePlaceData) { - hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); - ePlaceData = hero.ePlace.find(cur => cur.id == id); - }; - ePlaceData.stones.find(cur => cur.id == index).stone = topLineHeroStone.stone; - } - } - } - - } - - let newHeroes: HeroType[] = []; - for (let hero of dbHeroes) { - if (dbResonanceMap.has(hero.hid)) newHeroes.push(hero); - } - - // 重新计算战力 - if (newHeroes.length > 0) { - let artifacts = await ArtifactModel.findbyHids(roleId, posHids); - let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, newHeroes, { jewels: [...dbJewelMap.values()], heroes: newHeroes, artifacts }); - for (let hero of (heroes || [])) { - const { hid } = hero; - const heroResult = new HeroParam(hero); - resonanceDatas.push({ isResonance: true, position: dbResonanceMap.get(hid).position, ...pick(heroResult, ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) }); - } - } - - return { resonanceDatas, resonanceLv, resonanceJob, resonanceCon, resonanceEquip, resonanceEpQuality, resonanceEpStar, resonanceJewel, resonanceStone }; -} - - -export function sortData(heroes: HeroType[], sortType: number, findType?: number, jewelMap?: Map, extendValue?: number) { - switch (sortType) { - case RESONANCE_SORT_TYPE.LV: - { - heroes.sort((a, b) => { - if (a.lv !== b.lv) { - return b.lv - a.lv; - } else { - return b.ce - a.ce; - } - }); - break; - } - case RESONANCE_SORT_TYPE.JOBSTAGE: - { - heroes.sort((a, b) => { - let gradeA = gameData.job.get(a.job)?.grade || 0; - let gradeB = gameData.job.get(b.job)?.grade || 0; - - if (gradeA != gradeB) { - return gradeB - gradeA; - } - else if (a.jobStage !== b.jobStage) { - return b.jobStage - a.jobStage; - } else { - return b.ce - a.ce; - } - }); - break; - } - case RESONANCE_SORT_TYPE.CONNECT: - { - heroes = sortByConnect(heroes, findType) - break; - } - - case RESONANCE_SORT_TYPE.EQUIP_LV: - { - heroes = sortByEquipLv(heroes, findType); - break; - } - case RESONANCE_SORT_TYPE.EQUIP_QUALITY: - { - heroes = sortByEquipQuality(heroes, findType); - - break; - } - case RESONANCE_SORT_TYPE.EQUIP_STAR: - { - heroes = sortByEquipStar(heroes, findType); - break; - } - case RESONANCE_SORT_TYPE.JEWEL: - { - heroes = sortByEquipJewel(heroes, findType, jewelMap); - break; - } - case RESONANCE_SORT_TYPE.STONE: - { - heroes = sortByEquipStone(heroes, findType, extendValue); - break; - } - } - - let topLineHeroes: HeroType[] = heroes; - - // console.log('-x-x--x-x-x-x-x-x-x-x-x- topLineHeroes', util.inspect(heroes, { depth: null })); - return topLineHeroes[LINEUP_NUM - 1]; -} - -export function sortByConnect(heroes: HeroType[], index: number) { - heroes.sort((a, b) => { - const dicShipIdA = gameData.friendShipByIndex.get(`${a.hid}_${index}`) - const valA = a.connections.find(obj => obj.shipId === dicShipIdA)?.level || 0; - const dicShipIdB = gameData.friendShipByIndex.get(`${b.hid}_${index}`) - const valB = b.connections.find(obj => obj.shipId === dicShipIdB)?.level || 0; - if (valA != valB) { - return valB - valA; - } else { - return b.ce - a.ce; - } - }); - - return heroes -} - -export function sortByEquipLv(heroes: HeroType[], id: number) { - heroes.sort((a, b) => { - const valA = a.ePlace.find(obj => obj.id == id)?.lv || 0 - const valB = b.ePlace.find(obj => obj.id == id)?.lv || 0; - if (valA != valB) { - return valB - valA; - } else { - return b.ce - a.ce; - } - }); - return heroes; -} - -export function sortByEquipQuality(heroes: HeroType[], id: number) { - heroes.sort((a, b) => { - const valA = a.ePlace.find(obj => obj.id == id)?.quality || 0; - const valStageA = a.ePlace.find(obj => obj.id == id)?.qualityStage || 0; - const valB = b.ePlace.find(obj => obj.id == id)?.quality || 0; - const valStageB = b.ePlace.find(obj => obj.id == id)?.qualityStage || 0; - - if (valA != valB) { - return valB - valA; - } - else if (valStageA != valStageB) { - return valStageB - valStageA; - } - else { - return b.ce - a.ce; - } - }); - return heroes; -} - -export function sortByEquipStar(heroes: HeroType[], id: number) { - heroes.sort((a, b) => { - const valA = a.ePlace.find(obj => obj.id == id)?.star || 0; - const valStageA = a.ePlace.find(obj => obj.id == id)?.starStage || 0; - const valB = b.ePlace.find(obj => obj.id == id)?.star || 0; - const valStageB = b.ePlace.find(obj => obj.id == id)?.starStage || 0; - - if (valA != valB) { - return valB - valA; - } - else if (valStageA != valStageB) { - return valStageB - valStageA; - } - else { - return b.ce - a.ce; - } - }); - return heroes; -} - -export function sortByEquipJewel(heroes: HeroType[], eplaceId: number, jewelMap: Map) { - heroes.sort((a, b) => { - const jewelA = a.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0 - let jewelAData = jewelMap.get(jewelA); - const dicJewelALv = gameData.jewel.get(jewelAData?.id || 0)?.lv || 0; - let valA = 0; - if (jewelAData) { - if (jewelAData.randSe && jewelAData.randSe.length > 0) { - for (let { seid, rand } of jewelAData.randSe) { - let dicRandomEffectPool = gameData.randomEffectPool.get(seid); - if (!dicRandomEffectPool) continue; - if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); - if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue; - valA += rand / (dicRandomEffectPool.Max); - } - } - if (jewelAData.rareSe && jewelAData.rareSe.length > 0) { - for (let { seid, rand } of jewelAData.rareSe) { - let dicRandomEffectPool = gameData.randomEffectPool.get(seid); - if (!dicRandomEffectPool) continue; - if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); - if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue; - valA += rand / (dicRandomEffectPool.Max); - } - } - } - - const jewelB = b.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0 - let jewelBData = jewelMap.get(jewelB); - const dicJewelBLv = gameData.jewel.get(jewelBData?.id || 0)?.lv || 0; - let valB = 0; - if (jewelBData) { - if (jewelBData.randSe && jewelBData.randSe.length > 0) { - for (let { seid, rand } of jewelBData.randSe) { - let dicRandomEffectPool = gameData.randomEffectPool.get(seid); - - if (!dicRandomEffectPool) continue; - if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); - if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue; - valB += rand / (dicRandomEffectPool.Max); - } - } - if (jewelBData.rareSe && jewelBData.rareSe.length > 0) { - for (let { seid, rand } of jewelBData.rareSe) { - let dicRandomEffectPool = gameData.randomEffectPool.get(seid); - if (!dicRandomEffectPool) continue; - if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); - if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue; - valB += rand / (dicRandomEffectPool.Max); - } - } - } - - if (dicJewelALv != dicJewelBLv) { - return dicJewelBLv - dicJewelALv; - } - else if (valA != valB) { - return valB - valA; - } else { - return b.ce - a.ce; - } - }); - - return heroes; -} - -export function sortByEquipStone(heroes: HeroType[], id: number, extendValue: number) { - heroes.sort((a, b) => { - const stoneA = a.ePlace.find(obj => obj.id == id)?.stones || []; - const stoneIdA = stoneA.find(obj => obj.id == extendValue)?.stone || 0; - const valA = gameData.stone.get(stoneIdA)?.lv || 0; - const stoneB = b.ePlace.find(obj => obj.id == id)?.stones || []; - const stoneIdB = stoneB.find(obj => obj.id == extendValue)?.stone || 0; - const valB = gameData.stone.get(stoneIdB)?.lv || 0; - - if (valA != valB) { - return valB - valA; - } else { - return b.ce - a.ce; - } - }); - return heroes; -} - - -export async function getResonanceDataMap(roleId: string) { - let dbResonance = await ResonanceModel.findByRoleId(roleId); - let dbResonanceMap = new Map(); - let newPositionArr: ReturnResonanceParam[] = [], posHids: number[] = []; - for (let obj of dbResonance) { - if (obj.hid) { - dbResonanceMap.set(obj.hid, obj); - posHids.push(obj.hid); - } - else newPositionArr.push({ position: obj.position }); - - } - return { dbResonanceMap, newPositionArr, posHids }; -} - -export async function getJewelDataMap(heroes: HeroType[]) { - let dbJewelMap = new Map(); - let seqIds = []; - for (let hero of heroes) { - const { ePlace } = hero; - if (!ePlace || ePlace.length == 0) continue; - for (let { jewel } of ePlace) { - if (jewel == 0) continue; - seqIds.push(jewel); - } - } - if (seqIds.length > 0) { - let dbJewels = await JewelModel.findbySeqIds(seqIds); - if (dbJewels.length > 0) { - for (let obj of dbJewels) { - dbJewelMap.set(obj.seqId, obj); - } - } - } - return dbJewelMap; -} - -export function getInitEplace(id: number, skinId: number) { - const dicHero = gameData.hero.get(skinId) - const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id); - return new EPlace(id, dicEquip.id); -} \ No newline at end of file +import { EQUIP_EPLACEID, EQUIP_STONE, FRIENDSHIP_INDEX, HERO_SYSTEM_TYPE, LINEUP_NUM, RESONANCE, RESONANCE_SORT_TYPE } from "@consts"; +import { ArtifactModel } from "@db/Artifact"; +import { EPlace, HeroModel, HeroType } from "@db/Hero"; +import { JewelModel, JewelType } from "@db/Jewel"; +import { ResonanceModel, ResonanceType } from "@db/Resonance"; +import { RoleModel } from "@db/Role"; +import { HeroParam } from "@domain/roleField/hero"; +import { gameData, getEquipByJobClassAndEPlace } from "@pubUtils/data"; +import { ReturnResonanceParam } from "@pubUtils/interface"; +import { calculateCeWithHeroes } from "../playerCeService"; +import { getNewJob, initSkinTalent } from "../roleService"; +import { pick } from 'underscore'; +import * as util from 'util'; + +export async function refreshResonanceData(roleId: string, serverId: number, sid: string) { + let resonanceDatas: ReturnResonanceParam[] = []; + let resonanceLv = {}, resonanceJob = {}, resonanceCon = [], resonanceEquip = [], resonanceEpQuality = [], resonanceEpStar = [], resonanceJewel = [], resonanceStone = []; + + let role = await RoleModel.findByRoleId(roleId); + let topHids = role.topLineup.map(cur => cur.hid); + if (topHids.length < LINEUP_NUM) return { resonanceDatas }; + + let { dbResonanceMap, newPositionArr, posHids } = await getResonanceDataMap(roleId); + resonanceDatas = newPositionArr; + + let dbHeroes: HeroType[] = await HeroModel.findByHidsAndRole(roleId, [...topHids, ...posHids]); + + let topLineHeroes: HeroType[] = []; + for (const top of role.topLineup) { + topLineHeroes.push(dbHeroes.find(cur => cur.hid == top.hid)); + } + + let dbJewelMap = await getJewelDataMap(dbHeroes); + + // 武将等级 + let topLineHero: HeroType = sortData(topLineHeroes, RESONANCE_SORT_TYPE.LV); + resonanceLv = { hid: topLineHero.hid, lv: topLineHero.lv }; + for (let [hid] of dbResonanceMap) { + let hero = dbHeroes.find(cur => cur.hid == hid); + hero.lv = topLineHero.lv; + hero.exp = topLineHero.exp; + } + + // 职业(职阶、天赋) + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JOBSTAGE); + resonanceJob = { hid: topLineHero.hid, job: topLineHero.job, jobStage: topLineHero.jobStage }; + for (let [hid] of dbResonanceMap) { + let hero = dbHeroes.find(cur => cur.hid == hid); + let preJobStage = hero.jobStage; + hero.jobStage = topLineHero.jobStage; + hero.job = getNewJob(hero, topLineHero.job); + + if (preJobStage != hero.jobStage) { + //天赋树置空 + hero.skins = initSkinTalent(hero.skins || []); + } + } + + // 羁绊1, 2, 3 + for (let index = 1; index <= FRIENDSHIP_INDEX.THREE; index++) { + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.CONNECT, index); + const topDicShipId = gameData.friendShipByIndex.get(`${topLineHero.hid}_${index}`); + const topShipData = (topLineHero.connections || []).find(cur => cur.shipId == topDicShipId); + resonanceCon.push({ hid: topLineHero.hid, index, level: topShipData?.level || 0 }); + if (!topShipData) continue; + for (let [hid] of dbResonanceMap) { + let hero = dbHeroes.find(cur => cur.hid == hid); + const dicShipId = gameData.friendShipByIndex.get(`${hero.hid}_${index}`) + let shipData = hero.connections.find(cur => cur.shipId == dicShipId); + const dicShipData = gameData.friendShipsByLv.get(`${hid}_${dicShipId}_${topShipData?.level || 0}`); + let sign = true; + for (let hi of dicShipData?.hids || []) { + if (!dbHeroes.find(cur => cur.hid == hi)) { + sign = false; + break; + } + } + if (!sign) continue; + if (!shipData) hero.connections.push({ shipId: dicShipId, level: topShipData?.level || 0, exp: topShipData?.exp || 0 }); + else { + shipData.shipId = dicShipId + shipData.exp = topShipData?.exp || 0; + shipData.level = topShipData?.level || 0; + } + + } + } + + // 装备 1武器,2衣甲,3帽子,4鞋子 + for (let id = 1; id <= EQUIP_EPLACEID.SHOE_ID; id++) { + //装备强化 + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_LV, id); + let topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); + if (!topLineHeroEplace) + resonanceEquip.push({ hid: topLineHero.hid, id, lv: 0 }); + else + resonanceEquip.push({ hid: topLineHero.hid, id, lv: topLineHeroEplace?.lv || 0 }); + + for (let [hid] of dbResonanceMap) { + if (!topLineHeroEplace || !topLineHeroEplace.lv) continue; + let hero = dbHeroes.find(cur => cur.hid == hid); + let ePlaceData = hero.ePlace.find(cur => cur.id == id); + if (!ePlaceData) { + hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); + ePlaceData = hero.ePlace.find(cur => cur.id == id); + } + ePlaceData.lv = topLineHeroEplace.lv; + } + + //装备升品 + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_QUALITY, id); + topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); + if (!topLineHeroEplace) + resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: 0, qualityStage: 0 }) + else + resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: topLineHeroEplace?.quality || 0, qualityStage: topLineHeroEplace?.qualityStage || 0 }) + + for (let [hid] of dbResonanceMap) { + if (!topLineHeroEplace || (!topLineHeroEplace.quality && !topLineHeroEplace.qualityStage)) continue; + let hero = dbHeroes.find(cur => cur.hid == hid); + let ePlaceData = hero.ePlace.find(cur => cur.id == id); + if (!ePlaceData) { + hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); + ePlaceData = hero.ePlace.find(cur => cur.id == id); + }; + ePlaceData.quality = topLineHeroEplace.quality; + ePlaceData.qualityStage = topLineHeroEplace.qualityStage; + } + + //装备精练 + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_STAR, id); + topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); + if (!topLineHeroEplace) + resonanceEpStar.push({ hid: topLineHero.hid, id, star: 0, starStage: 0 }) + else + resonanceEpStar.push({ hid: topLineHero.hid, id, star: topLineHeroEplace?.star || 0, starStage: topLineHeroEplace?.starStage || 0 }) + + for (let [hid] of dbResonanceMap) { + if (!topLineHeroEplace || (!topLineHeroEplace.star && !topLineHeroEplace.starStage)) continue; + let hero = dbHeroes.find(cur => cur.hid == hid); + let ePlaceData = hero.ePlace.find(cur => cur.id == id); + if (!ePlaceData) { + hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); + ePlaceData = hero.ePlace.find(cur => cur.id == id); + }; + ePlaceData.star = topLineHeroEplace.star; + ePlaceData.starStage = topLineHeroEplace.starStage; + } + + //天晶 + if (RESONANCE.JEWEL) { + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JEWEL, id, dbJewelMap); + topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); + if (!topLineHeroEplace) + resonanceJewel.push({ hid: topLineHero.hid, id, jewel: 0 }); + else + resonanceJewel.push({ hid: topLineHero.hid, id, jewel: topLineHeroEplace?.jewel || 0 }); + + //破,御,护,命 + for (let [hid] of dbResonanceMap) { + if (!topLineHeroEplace || !topLineHeroEplace.jewel) continue; + let hero = dbHeroes.find(cur => cur.hid == hid); + let ePlaceData = hero.ePlace.find(cur => cur.id == id); + if (!ePlaceData) { + hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); + ePlaceData = hero.ePlace.find(cur => cur.id == id); + }; + ePlaceData.jewel = topLineHeroEplace.jewel; + } + } + + //地玉 + if (RESONANCE.STONE) { + //破,御,护,命 1,2,3 + resonanceStone.push({ id, stones: [] }); + for (let index = 1; index <= EQUIP_STONE.THREE; index++) { + topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.STONE, id, null, index); + topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id); + resonanceStone.find(cur => cur.id == id).stones.push({ hid: topLineHero.hid, id: index, stone: 0 }); + if (topLineHeroEplace && topLineHeroEplace.stones) { + const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index); + if (topLineHeroStone) + resonanceStone.find(cur => cur.id == id).stones.find(cur => cur.id == index).stone = topLineHeroStone.stone; + } + + for (let [hid] of dbResonanceMap) { + if (!topLineHeroEplace || !topLineHeroEplace.stones) continue; + const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index); + if (!topLineHeroStone || !topLineHeroStone.stone) continue; + let hero = dbHeroes.find(cur => cur.hid == hid); + let ePlaceData = hero.ePlace.find(cur => cur.id == id); + if (!ePlaceData) { + hero.ePlace.push({ ...getInitEplace(id, hero.skinId) }); + ePlaceData = hero.ePlace.find(cur => cur.id == id); + }; + ePlaceData.stones.find(cur => cur.id == index).stone = topLineHeroStone.stone; + } + } + } + + } + + let newHeroes: HeroType[] = []; + for (let hero of dbHeroes) { + if (dbResonanceMap.has(hero.hid)) newHeroes.push(hero); + } + + // 重新计算战力 + if (newHeroes.length > 0) { + let artifacts = await ArtifactModel.findbyHids(roleId, posHids); + let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, newHeroes, { jewels: [...dbJewelMap.values()], heroes: newHeroes, artifacts }); + for (let hero of (heroes || [])) { + const { hid } = hero; + const heroResult = new HeroParam(hero); + resonanceDatas.push({ isResonance: true, position: dbResonanceMap.get(hid).position, ...pick(heroResult, ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) }); + } + } + + return { resonanceDatas, resonanceLv, resonanceJob, resonanceCon, resonanceEquip, resonanceEpQuality, resonanceEpStar, resonanceJewel, resonanceStone }; +} + + +export function sortData(heroes: HeroType[], sortType: number, findType?: number, jewelMap?: Map, extendValue?: number) { + switch (sortType) { + case RESONANCE_SORT_TYPE.LV: + { + heroes.sort((a, b) => { + if (a.lv !== b.lv) { + return b.lv - a.lv; + } else { + return b.ce - a.ce; + } + }); + break; + } + case RESONANCE_SORT_TYPE.JOBSTAGE: + { + heroes.sort((a, b) => { + let gradeA = gameData.job.get(a.job)?.grade || 0; + let gradeB = gameData.job.get(b.job)?.grade || 0; + + if (gradeA != gradeB) { + return gradeB - gradeA; + } + else if (a.jobStage !== b.jobStage) { + return b.jobStage - a.jobStage; + } else { + return b.ce - a.ce; + } + }); + break; + } + case RESONANCE_SORT_TYPE.CONNECT: + { + heroes = sortByConnect(heroes, findType) + break; + } + + case RESONANCE_SORT_TYPE.EQUIP_LV: + { + heroes = sortByEquipLv(heroes, findType); + break; + } + case RESONANCE_SORT_TYPE.EQUIP_QUALITY: + { + heroes = sortByEquipQuality(heroes, findType); + + break; + } + case RESONANCE_SORT_TYPE.EQUIP_STAR: + { + heroes = sortByEquipStar(heroes, findType); + break; + } + case RESONANCE_SORT_TYPE.JEWEL: + { + heroes = sortByEquipJewel(heroes, findType, jewelMap); + break; + } + case RESONANCE_SORT_TYPE.STONE: + { + heroes = sortByEquipStone(heroes, findType, extendValue); + break; + } + } + + let topLineHeroes: HeroType[] = heroes; + + // console.log('-x-x--x-x-x-x-x-x-x-x-x- topLineHeroes', util.inspect(heroes, { depth: null })); + return topLineHeroes[LINEUP_NUM - 1]; +} + +export function sortByConnect(heroes: HeroType[], index: number) { + heroes.sort((a, b) => { + const dicShipIdA = gameData.friendShipByIndex.get(`${a.hid}_${index}`) + const valA = a.connections.find(obj => obj.shipId === dicShipIdA)?.level || 0; + const dicShipIdB = gameData.friendShipByIndex.get(`${b.hid}_${index}`) + const valB = b.connections.find(obj => obj.shipId === dicShipIdB)?.level || 0; + if (valA != valB) { + return valB - valA; + } else { + return b.ce - a.ce; + } + }); + + return heroes +} + +export function sortByEquipLv(heroes: HeroType[], id: number) { + heroes.sort((a, b) => { + const valA = a.ePlace.find(obj => obj.id == id)?.lv || 0 + const valB = b.ePlace.find(obj => obj.id == id)?.lv || 0; + if (valA != valB) { + return valB - valA; + } else { + return b.ce - a.ce; + } + }); + return heroes; +} + +export function sortByEquipQuality(heroes: HeroType[], id: number) { + heroes.sort((a, b) => { + const valA = a.ePlace.find(obj => obj.id == id)?.quality || 0; + const valStageA = a.ePlace.find(obj => obj.id == id)?.qualityStage || 0; + const valB = b.ePlace.find(obj => obj.id == id)?.quality || 0; + const valStageB = b.ePlace.find(obj => obj.id == id)?.qualityStage || 0; + + if (valA != valB) { + return valB - valA; + } + else if (valStageA != valStageB) { + return valStageB - valStageA; + } + else { + return b.ce - a.ce; + } + }); + return heroes; +} + +export function sortByEquipStar(heroes: HeroType[], id: number) { + heroes.sort((a, b) => { + const valA = a.ePlace.find(obj => obj.id == id)?.star || 0; + const valStageA = a.ePlace.find(obj => obj.id == id)?.starStage || 0; + const valB = b.ePlace.find(obj => obj.id == id)?.star || 0; + const valStageB = b.ePlace.find(obj => obj.id == id)?.starStage || 0; + + if (valA != valB) { + return valB - valA; + } + else if (valStageA != valStageB) { + return valStageB - valStageA; + } + else { + return b.ce - a.ce; + } + }); + return heroes; +} + +export function sortByEquipJewel(heroes: HeroType[], eplaceId: number, jewelMap: Map) { + heroes.sort((a, b) => { + const jewelA = a.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0 + let jewelAData = jewelMap.get(jewelA); + const dicJewelALv = gameData.jewel.get(jewelAData?.id || 0)?.lv || 0; + let valA = 0; + if (jewelAData) { + if (jewelAData.randSe && jewelAData.randSe.length > 0) { + for (let { seid, rand } of jewelAData.randSe) { + let dicRandomEffectPool = gameData.randomEffectPool.get(seid); + if (!dicRandomEffectPool) continue; + if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); + if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue; + valA += rand / (dicRandomEffectPool.Max); + } + } + if (jewelAData.rareSe && jewelAData.rareSe.length > 0) { + for (let { seid, rand } of jewelAData.rareSe) { + let dicRandomEffectPool = gameData.randomEffectPool.get(seid); + if (!dicRandomEffectPool) continue; + if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); + if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue; + valA += rand / (dicRandomEffectPool.Max); + } + } + } + + const jewelB = b.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0 + let jewelBData = jewelMap.get(jewelB); + const dicJewelBLv = gameData.jewel.get(jewelBData?.id || 0)?.lv || 0; + let valB = 0; + if (jewelBData) { + if (jewelBData.randSe && jewelBData.randSe.length > 0) { + for (let { seid, rand } of jewelBData.randSe) { + let dicRandomEffectPool = gameData.randomEffectPool.get(seid); + + if (!dicRandomEffectPool) continue; + if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); + if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue; + valB += rand / (dicRandomEffectPool.Max); + } + } + if (jewelBData.rareSe && jewelBData.rareSe.length > 0) { + for (let { seid, rand } of jewelBData.rareSe) { + let dicRandomEffectPool = gameData.randomEffectPool.get(seid); + if (!dicRandomEffectPool) continue; + if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1); + if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue; + valB += rand / (dicRandomEffectPool.Max); + } + } + } + + if (dicJewelALv != dicJewelBLv) { + return dicJewelBLv - dicJewelALv; + } + else if (valA != valB) { + return valB - valA; + } else { + return b.ce - a.ce; + } + }); + + return heroes; +} + +export function sortByEquipStone(heroes: HeroType[], id: number, extendValue: number) { + heroes.sort((a, b) => { + const stoneA = a.ePlace.find(obj => obj.id == id)?.stones || []; + const stoneIdA = stoneA.find(obj => obj.id == extendValue)?.stone || 0; + const valA = gameData.stone.get(stoneIdA)?.lv || 0; + const stoneB = b.ePlace.find(obj => obj.id == id)?.stones || []; + const stoneIdB = stoneB.find(obj => obj.id == extendValue)?.stone || 0; + const valB = gameData.stone.get(stoneIdB)?.lv || 0; + + if (valA != valB) { + return valB - valA; + } else { + return b.ce - a.ce; + } + }); + return heroes; +} + + +export async function getResonanceDataMap(roleId: string) { + let dbResonance = await ResonanceModel.findByRoleId(roleId); + let dbResonanceMap = new Map(); + let newPositionArr: ReturnResonanceParam[] = [], posHids: number[] = []; + for (let obj of dbResonance) { + if (obj.hid) { + dbResonanceMap.set(obj.hid, obj); + posHids.push(obj.hid); + } + else newPositionArr.push({ position: obj.position }); + + } + return { dbResonanceMap, newPositionArr, posHids }; +} + +export async function getJewelDataMap(heroes: HeroType[]) { + let dbJewelMap = new Map(); + let seqIds = []; + for (let hero of heroes) { + const { ePlace } = hero; + if (!ePlace || ePlace.length == 0) continue; + for (let { jewel } of ePlace) { + if (jewel == 0) continue; + seqIds.push(jewel); + } + } + if (seqIds.length > 0) { + let dbJewels = await JewelModel.findbySeqIds(seqIds); + if (dbJewels.length > 0) { + for (let obj of dbJewels) { + dbJewelMap.set(obj.seqId, obj); + } + } + } + return dbJewelMap; +} + +export function getInitEplace(id: number, skinId: number) { + const dicHero = gameData.hero.get(skinId) + const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id); + return new EPlace(id, dicEquip.id); +} diff --git a/game-server/app/services/role/rewardService.ts b/game-server/app/services/role/rewardService.ts index 3ce977d60..0bb0d8e9f 100644 --- a/game-server/app/services/role/rewardService.ts +++ b/game-server/app/services/role/rewardService.ts @@ -1,806 +1,806 @@ -import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE, ACTIVITY_TYPE } from '../../consts'; -import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandValueByMinMax, } from '../../pubUtils/util'; -import { RoleModel, RoleType } from '../../db/Role'; -import { setAp } from '../actionPointService'; -import { ItemModel, } from '../../db/Item'; -import { ItemInter, } from '../../pubUtils/interface'; -import { gameData, getDefArtifactByGid } from '../../pubUtils/data'; -import { uniq } from 'underscore'; -import { EPlace, HeroModel, HeroType, } from '../../db/Hero'; -import { Figure } from '../../domain/dbGeneral'; -import { ArtifactParam, JewelParam } from '../../domain/roleField/hero'; -import { HeroSkin } from '../../db/Hero'; -import { BAG } from '../../pubUtils/dicParam'; -import { sendMailByContent } from '../mailService'; -import { SkinModel, } from '../../db/Skin'; -import { reportTAEvent, reportTAUserSet } from '../sdkService'; -import { saveCoinChangeLog, saveFigureInfoLog, saveGoldChangeLog, saveItemChangeLog } from '../../pubUtils/logUtil'; -import { JewelModel, JewelType, jewelUpdate, RandSe } from '../../db/Jewel'; -import { updateEplaces } from '../equipService'; -import { combineItems, getCoinEventProperties, getGoldEventProperties, sortItems } from './util'; -import { nowSeconds } from '../../pubUtils/timeUtil'; -import { calculateCeWithHero, calculateCeWithRole } from '../playerCeService'; -import { sendMessageToUserWithSuc } from '../pushService'; -import { filterGoods } from '../dataService'; -import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from '../../db/Artifact'; -import { ActivityItemModel } from '../../db/ActivityItem'; -import { getActivitiesByType } from '../activity/activityService'; -import { ActivityModelType } from '../../db/Activity'; -import { ForgeData } from '../../domain/activityField/forgeField'; -import { getRoleCreateTime, getServerCreateTime } from '../redisService'; - -export async function handleCost(roleId: string, sid: string, goods: Array, reason: ITEM_CHANGE_REASON) { - - let { items, jewels, gold, coin, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.COST); - let jewelSeqIds = jewels.map(cur => cur.seqId); - let resJewels: JewelType[] = []; - let artifactSeqIds = artifacts.map(cur => cur.seqId); - let resArtifacts: ArtifactModelType[] = []; - - // 检查货币是否充足 - let role = await RoleModel.findByRoleId(roleId); - if (gold.length > 0 || coin.length > 0) { - let { gold: originGold, coin: originCoin } = role; - for(let {count} of gold) { originGold -= count }; - for(let count of coin) { originCoin -= count }; - if(originGold < 0 || originCoin < 0) return false; - } - //检查装备是否存在 - if (jewels.length > 0) { - resJewels = await JewelModel.findbySeqIds(jewelSeqIds); - if (resJewels.length < jewels.length) - return false; - } - //检查宝物是否存在 - if (artifacts.length > 0) { - resArtifacts = await ArtifactModel.findbySeqIds(roleId, artifactSeqIds); - if (resArtifacts.length < artifacts.length) - return false; - } - //检查并修改道具 - if (items.length > 0) { - let { hasError, result } = await ItemModel.decreaseItems(roleId, items); - if (hasError) return false; - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid); - saveItemChangeLog(roleId, result, reason); - } - //检查并修改道具 - if (activityItems.length > 0) { - let { hasError, result } = await ActivityItemModel.decreaseActivityItems(roleId, activityItems); - if (hasError) return false; - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid); - saveItemChangeLog(roleId, result, reason); - } - - //删除装备 - if (resJewels.length > 0) { - let heroMap = new Map(); - for(let jewel of resJewels) { - if(jewel.hid > 0) { - if(!heroMap.has(jewel.hid)) { - let hero = await HeroModel.findByHidAndRole(jewel.hid, roleId); - heroMap.set(jewel.hid, { hero, jewels: [] }); - } - heroMap.get(jewel.hid).jewels.push(jewel); - } - } - for(let [hid, {hero, jewels} ] of heroMap) { - // 脱下天晶石 - let update = new Map>(); - for(let jewel of jewels) { - await JewelModel.putOnOrOff(jewel.id, 0, 0); - let curEquip = hero.ePlace.find(cur => cur.jewel == jewel.id); - if(!!curEquip) { - update.set(curEquip.id, { jewel: 0 }); - } - } - let { newEplace } = updateEplaces(hero.ePlace, update); - await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, role.serverId, sid, hid, { ePlace: newEplace }, { ePlaceIds: [...update.keys()] }); - } - - - let jewels = await JewelModel.deleteBySeqIds(roleId, jewelSeqIds); - saveItemChangeLog(roleId, jewels.map(jewel => ({ id: jewel.id, count: 1, inc: -1 })), reason); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_DEL, { jewels: jewels.map(jewel => ({ seqId: jewel.seqId, id: jewel.id, inc: -1, reason })) }, sid); - } - - //删除宝物 - if (resArtifacts.length > 0) { - let heroMap = new Map(); - for(let artifact of resArtifacts) { - if(artifact.hid > 0) { - heroMap.set(artifact.hid, { artifact }); - } - } - for(let [hid, { artifact } ] of heroMap) { - // 脱下天晶石 - await ArtifactModel.putOnOrOff(roleId, artifact.id, 0); - await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, role.serverId, sid, hid, { artifact: 0 }); - } - - let artifacts = await ArtifactModel.deleteBySeqIds(roleId, artifactSeqIds); - saveItemChangeLog(roleId, artifacts.map(artifact => ({ id: artifact.id, count: 1, inc: -1 })), reason); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_DEL, { artifacts: artifacts.map(artifact => ({ seqId: artifact.seqId, id: artifact.id, inc: -1, reason })) }, sid); - } - - //消耗玩家货币 - if (gold.length > 0 || coin.length > 0) { - let costGold = gold.reduce((pre, cur) => pre + cur.count, 0); - let costCoin = coin.reduce((pre, cur) => pre + cur, 0); - role = await RoleModel.decreaseGoldAndCoin(roleId, gold, costCoin); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin, totalCost: role.totalCost }, sid); - - if(costGold > 0) { - reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getGoldEventProperties(costGold, role.gold, reason)); - reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold }); - saveGoldChangeLog(roleId, role.gold, -1 * costGold, reason); - } - if(costCoin > 0) { - reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getCoinEventProperties(costCoin, role.coin, reason)); - reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin }); - saveCoinChangeLog(roleId, role.coin, -1 * costCoin, reason); - } - - } - - return true; -} - -export async function addItems(roleId: string, roleName: string, sid: string, goods: Array, reason: ITEM_CHANGE_REASON) { - goods = filterGoods(goods, obj => obj.id, roleId, reason); - let { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE); - let showItems: { id: number, seqId?: number|string, count: number, isBag?: boolean, expireTime?: number }[] = []; - let role = await RoleModel.findByRoleId(roleId, '-warCount -topLineup'); - // 1. 装备处理 - if(jewels.length > 0) { - let { jewelCount = 0 } = role; - let incJewels = jewels, mailJewels: { id?: number, hid?: number, seqId?: number }[] = []; - if(jewels.length + jewelCount > BAG.BAG_EQUIP_UPLIMITED) { // 装备上限 - let inc = BAG.BAG_EQUIP_UPLIMITED - jewelCount; - if(inc < 0) inc = 0; - incJewels = jewels.slice(0, inc); - mailJewels = jewels.slice(inc); - } - - // 直接加的 - let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number }[]>incJewels, reason); - for (let jewel of jewelInfos) { - showItems.push({ seqId: jewel.seqId, id: jewel.id, count: 1, isBag: true }); - } - for(let jewel of combineItems(mailJewels)) { - showItems.push({ id: jewel.id, count: jewel.count, isBag: false }); - } - //装备推送 - if (!!jewelInfos.length) - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_ADD, { jewelInfos }, sid); - //统计装备 - if (jewelInfos.length > 0) { - saveItemChangeLog(roleId, jewelInfos, reason); - } - // 发邮件的 - if(mailJewels.length > 0) { - await sendMailByContent(MAIL_TYPE.EQUIP_OVER, roleId, { goods: combineItems(mailJewels) }); - } - } - - // 2. 道具处理 - if(items.length > 0) { - let { items: itemInfos } = await addBags(roleId, roleName, items, reason); - for (let item of items) { - showItems.push({ id: item.id, count: item.count }); - } - //背包除去装备推送 - if (!!itemInfos.length) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: itemInfos }, sid); - saveItemChangeLog(roleId, itemInfos, reason); - } - - } - - // 3. 货币推送 - if(gold.length > 0 || coin.length > 0 || ap > 0) { - await setAp(role.serverId, roleId, null, role.lv, ap, sid, reason); - let incCoin = coin.reduce((pre, cur) => pre + cur, 0); - let incGold = gold.reduce((pre, cur) => pre + cur.count, 0); - role = await RoleModel.increaseGoldAndCoin(roleId, gold, incCoin); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin }, sid); - - if(gold.length > 0) { - gold.forEach(({ count }) => { - showItems.push(getGoldObject(count)); - }); - reportTAEvent(roleId, TA_EVENT.ITEM_GET, getGoldEventProperties(incGold, role.gold, reason)); - reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold }); - saveGoldChangeLog(roleId, role.gold, incGold, reason ); - } - if(coin.length > 0) { - coin.forEach(count => { - showItems.push(getCoinObject(count)); - }); - reportTAEvent(roleId, TA_EVENT.ITEM_GET, getCoinEventProperties(incCoin, role.coin, reason)); - reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin }); - saveCoinChangeLog(roleId, role.coin, incCoin, reason); - } - if(ap > 0) { - showItems.push(getApObject(ap)); - } - } - - // 4. 皮肤处理 - let figureInfos:{ heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; // 头像变化推送信息 - if(skins.length > 0) { - let heroskins: {skins: HeroSkin[], hid: number}[] = []; // 皮肤推送信息 - let skinInfos: {id: number, hid: number, count: number, inc: number, reason: number }[] = []; - let calAllHeroResult = undefined; // 全局战力变化推送 - - for (let skinId of skins) {//皮肤推送 - let hero = await addSkin(roleId, roleName, role.serverId, sid, skinId, false); - skinInfos.push({ id: skinId, hid: hero? hero.hid: 0, count: 1, inc: 1, reason }) - showItems.push({ id: skinId, count: 1 }); - if(hero) heroskins.push({ skins: hero.skins, hid: hero.hid }); - } - if (!!skinInfos.length) { - pushHeroSkinMsg(heroskins, skinInfos, roleId, sid); // 推送onHeroSkinChange - saveItemChangeLog(roleId, skinInfos, reason); - } - } - - // 5. 获得头像和相框等 - if(figures.length > 0) { - let figureInfo = await addFigure(roleId, figures, reason); - if(figureInfo) figureInfos.push(figureInfo); - for (let id of figures) {//皮肤推送 - showItems.push({ id, count: 1 }); - } - } - - // 获得头像或相框或形象推送 - if(!!figureInfos && figureInfos.length > 0) { - for(let figureInfo of figureInfos) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid); - saveFigureInfoLog(roleId, figureInfo, reason) - } - } - - // 6. 宝物处理 - - if(artifacts.length > 0) { - let { artifactCount = 0 } = role; - let incArtifacts = artifacts, mailArtifacts: { id?: number, seqId?: number|string }[] = []; - if(artifacts.length + artifactCount > BAG.BAG_ARTIFACT_UPLIMITED) { // 装备上限 - let inc = BAG.BAG_ARTIFACT_UPLIMITED - artifactCount; - if(inc < 0) inc = 0; - incArtifacts = artifacts.slice(0, inc); - mailArtifacts = artifacts.slice(inc); - } - - // 直接加的 - let { artifacts: artifactInfos } = await addArtifacts(roleId, roleName, <{id: number}[]>incArtifacts, reason); - for (let artifact of artifactInfos) { - showItems.push({ seqId: artifact.seqId, id: artifact.id, count: 1, isBag: true }); - } - for(let artifact of combineItems(mailArtifacts)) { - showItems.push({ id: artifact.id, count: artifact.count, isBag: false }); - } - //装备推送 - if (!!artifactInfos.length) - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_ADD, { artifacts: artifactInfos }, sid); - //统计装备 - if (artifactInfos.length > 0) { - saveItemChangeLog(roleId, artifactInfos, reason); - } - // 发邮件的 - if(mailArtifacts.length > 0) { - await sendMailByContent(MAIL_TYPE.ARTIFACT_OVER, roleId, { goods: combineItems(mailArtifacts) }); - } - } - - // 7. 活动道具处理 - if(activityItems.length > 0) { - let { items: itemInfos } = await addActivityItems(role, activityItems, reason); - for (let item of itemInfos) { - showItems.push({ id: item.id, count: item.inc, expireTime: item.expireTime }); - } - //背包除去装备推送 - if (!!itemInfos.length) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: itemInfos }, sid); - saveItemChangeLog(roleId, itemInfos, reason); - } - - } - return showItems; -} - - -export async function checkGoods(roleId: string, goodIds: Array) { - let jewelSeqIds: Array = []; - let itemIds: Array = []; - let hids: Array = []; - goodIds = uniq(goodIds); - for (let goodId of goodIds) { - let goodInfo = gameData.goods.get(goodId); - if (!!goodInfo) { - let { table } = ITID.get(goodInfo.itid); - if (table == ITEM_TABLE.EQUIP) { - jewelSeqIds.push(goodId); - } else if (table == ITEM_TABLE.ITEM) { - itemIds.push(goodId); - } - } - } - - //检查装备是否存在 - if (!!jewelSeqIds.length) { - let resJewels = await JewelModel.findbySeqIds(jewelSeqIds); - resJewels = uniq(resJewels, function (resEquip) { - return resEquip.id; - }); - if (resJewels.length < jewelSeqIds.length) - return false; - } - //检查并修改道具 - if (itemIds.length > 0) { - let items = await ItemModel.findbyRoleAndIds(roleId, itemIds); - if (items.length < itemIds.length) - return false; - } - return true; -} - -export async function checkHeroes(roleId: string, hids: number[]) { - if (!!hids.length) { - let heros = await HeroModel.findByHidRange(hids, roleId); - if (heros.length < hids.length) - return false; - } - return true -} - -export async function checkHeroEquips(roleId: string, quality: number) { - return await HeroModel.checkEquipByQuality(roleId, quality); -} - -/** - * 解锁头像/相框 - * @param roleId 玩家id - * @param conditions 解锁条件 - * @param role 如果已查询过role表就直接可以使用 - */ -export async function unlockFigure(sid: string, roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role?: RoleType) { - if (!role || !role.heads || !role.frames) { - role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - } - let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role); - role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines }); - if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid); - } -} - - -/** - * 皮肤数据变化去重、推送 - * @param heroskins 推送的皮肤 - * @param roleId 玩家 - */ -function pushHeroSkinMsg(heroskins: {skins: HeroSkin[], hid: number}[], skinInfos: {id: number, hid: number }[], roleId: string, sid: string) { - let pushSkinInfos: {skins: HeroSkin[], hid: number}[] = []; // 可能会有重复的 - for(let { skins, hid } of heroskins) { - let index = pushSkinInfos.findIndex(cur => cur.hid == hid); - if(index == -1) { - pushSkinInfos.push({skins, hid}); - } else { - if(skins.length > pushSkinInfos[index].skins.length) { - pushSkinInfos[index] = {skins, hid}; - } - } - } - if(pushSkinInfos.length > 0 || skinInfos.length > 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, { heros: heroskins, skins: skinInfos }, sid); - } -} - - -/** - * 只插入皮肤,不管那么多的 - * @param roleId - * @param roleName - * @param skinId - * @returns - */ - export async function increaseSkin(roleId:string, roleName: string, skinId: number) { - let dicSkin = gameData.fashion.get(skinId); - if (!dicSkin) return false; - - let skin = await SkinModel.increaseSkin(roleId, skinId, { roleId, roleName, id: skinId, skinName: dicSkin.name, hid: dicSkin.actorId, skinId: dicSkin.heroId }); - if(!skin) return false; // 插入失败 - return skin -} - -/** - * 添加皮肤 - * @param roleId 玩家id - * @param roleName 玩家名 - * @param id 皮肤id - * @param hero 武将,如果已经查询过这个武将就不用再查询一次,主意要select skins字段 - * @returns {{ hero, figureInfo, calAllHeroResult }} hero:添加皮肤后的武将 figureInfo: 触发头像添加信息 calAllHeroResult:全局战力加成后结果 - */ -export async function addSkin(roleId: string, roleName: string, serverId: number, sid: string, skinId: number, enable: boolean, hero?: HeroType) { - let skin = await increaseSkin(roleId, roleName, skinId); - if(!skin) return false; - - if(skin.hid && !hero) hero = await HeroModel.findByHidAndRole(skin.hid, roleId); - let condition = { type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: skinId }; - await unlockFigure(sid, roleId, [condition]); // 解锁头像 - await calculateCeWithRole(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, serverId, sid, {}, { skinId }); // 全局加成 - - if (hero) { // 有武将的,将皮肤链接到武将上 - let curSkin = hero.skins.find(cur => cur.id == skinId); - if (!curSkin) { - hero.skins.push(new HeroSkin(skin, enable)); - await HeroModel.updateHeroInfo(roleId, hero.hid, hero); - } - return hero; - } else { - return null - } -} - -export async function addBags(roleId: string, roleName: string, datas: { id: number, count: number }[], reason: number) { - let items: { id: number, count: number, inc: number }[] = []; - for(let data of datas) { - let item = await addBag(roleId, roleName, data, reason); - items.push(item) - } - return { items } -} - -export async function addBag(roleId: string, roleName: string, data: { id: number, count: number }, reason: number) { - let { id, count } = data; - let { name: itemName, itid, hid } = gameData.goods.get(id); - let { type } = ITID.get(itid); - - let item = await ItemModel.increaseItem(roleId, id, count, { roleId, roleName, itemName, id, type, hid }); - return { id: item.id, count: item.count, inc: count, reason }; -} - -export async function addActivityItems(role: RoleType, datas: { id: number, count: number }[], reason: number) { - let serverTime = await getServerCreateTime(role.serverId); - let createTime = await getRoleCreateTime(role.roleId, role); - let items: { id: number, count: number, inc: number, expireTime: number }[] = []; - for(let data of datas) { - let item = await addActivityItem(role.serverId, role.roleId, role.roleName, data, reason, createTime, serverTime); - if(item) items.push(item) - } - return { items } -} - -export async function addActivityItem(serverId: number, roleId: string, roleName: string, data: { id: number, count: number }, reason: number, createTime: number, serverTime: number) { - let { id, count } = data; - let { name: itemName, activityType } = gameData.goods.get(id); - let activities = await getActivitiesByType(serverId, activityType); - for(let activity of activities) { - let activityData = getActivityData(activity, createTime, serverTime); - if(!activityData || !activityData.canShow()) continue; - let item = await ActivityItemModel.increaseActivityItem(roleId, id, count, { roleId, roleName, itemName, id, expireTime: Math.floor(activityData.nextRefreshTime/1000) }); - return { id: item.id, count: item.count, inc: count, expireTime: item.expireTime, reason }; - } -} - -function getActivityData(activity: ActivityModelType, createTime: number, serverTime: number) { - switch(activity.type) { - case ACTIVITY_TYPE.FORGE: - return new ForgeData(activity, createTime, serverTime) - default: - return null - } -} - -export async function addJewels(roleId: string, roleName: string, jewels: { id: number, }[], reason: number) { - let jewelInfo: jewelUpdate[] = []; - for(let jewel of jewels) { - let info = await getAddJewelInfo(roleId, roleName, jewel); - jewelInfo.push(info); - } - - const jewelResult = await JewelModel.createJewels(roleId, jewelInfo); - return { jewels: jewelResult.map(jewel => new JewelParam(jewel, true, reason))} -} - -export async function getAddJewelInfo(roleId: string, roleName: string, jewel: { id: number, }) { - let { id, } = jewel; - let { name, randomEffect, effectCount, rareEffect } = gameData.jewel.get(id); - - // 随机属性 - let randomResult: number[] = getRandEelm(randomEffect, effectCount); - let rareResult: number[] = getRandEelm(rareEffect, 1); - - let randSe: Array = randomResult.map((id: number, index: number) => { - return getJewelRandSe(index + 1, id); - }); - let rareSe: Array = rareResult.map((id: number, index: number) => { - return getJewelRandSe(index + 1, id); - }); - - return { roleId, roleName, id, name, randSe, rareSe }; -} - -/** - * 天晶石已知词条随机值 - * @param id 词条位置,第几条 - * @param seid 词条id - * @returns - */ -export function getJewelRandSe(id: number, seid: number) { - let dicRandom = gameData.randomEffectPool.get(seid) - // console.log('#### dicRandom', dicRandom) - let rand = 0; - let planPool = gameData.randomEffectPoolPlan.get(dicRandom.planId); - if(planPool && planPool.length > 0) { - let result = getRandEelmWithWeight(planPool); - if(result) rand = Math.round(result.dic.num * 100)/100; - } else { - let randResult = getRandValueByMinMax(dicRandom.Min, dicRandom.Max, getDecimalCnt(dicRandom.gap)); - let n = Math.floor((randResult - dicRandom.Min)/dicRandom.gap); - rand = Math.round(dicRandom.Min + n * dicRandom.gap * 100)/100; - } - return new RandSe(id, dicRandom.id, rand); -} - -export async function addArtifacts(roleId: string, roleName: string, artifacts: { id: number, }[], reason: number) { - let artifactInfos: ArtifactModelUpdate[] = []; - for(let { id } of artifacts) { - let dicArtifact = getDefArtifactByGid(id); - if(dicArtifact) { - let { goodId, artifactId, quality, qualityStage } = dicArtifact; - artifactInfos.push({ roleId, roleName, id: goodId, artifactId, quality, qualityStage }); - } - } - - const artifactResult = await ArtifactModel.createArtifacts(roleId, artifactInfos); - return { artifacts: artifactResult.map(artifact => new ArtifactParam(artifact, true, reason))} -} - -export function getGoldId() { - return CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); -} - -/** - * @description 获取元宝物品 { id, count } - * @param count 元宝数量 - */ -export function getGoldObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count }; -} - -/** - * @description 获取金币物品 { id, count } - * @param count 元宝数量 - */ -export function getCoinObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count }; -} - -/** - * @description 获取体力物品 { id, count } - * @param count 体力数量 - */ - export function getApObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ACTION_POINT), count }; -} -/** - * @description 获取友情点物品 { id, count } - * @param count 友情点数量 - */ -export function getFriendPointObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.FRIEND_POINT), count }; -} - -/** - * @description 获取功勋物品 { id, count } - * @param count 功勋数量 - */ -export function getHonourObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count }; -} - -/** - * @description 获取代金券物品 { id, count } - * @param count 元宝数量 - */ - export function getVoucherObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER), count }; -} - -export function getVoucherCoinObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN), count }; -} - -export function checkVoucherId(id: number) { - let voucher = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER); - let voucherCoin = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN); - return id == voucher || id == voucherCoin; -} - -export function getRougeTechScoreObject(count: number) { - return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ROUGE_TECH)||0, count }; -} - -/** - * 返回 解锁头像/相框 - * @param conditions 解锁条件 - * @param role 如果已查询过role表就直接可以使用 - */ - export function unlockFigureWithoutSave(conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role: RoleType) { - - let { heads, frames, spines, roleId } = role; - let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; - for (let { type, paramHid, paramFavourLv, paramSkinId, paramWinStreakNum } of conditions) { - let canUnLockList = gameData.figureCondition.get(type); - if (canUnLockList) { - canUnLockList = filterGoods(canUnLockList, obj => obj.gid, roleId, ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE); - let reason = 0; - - for (let { id, params, gid } of canUnLockList) { - let flag = false; // 是否达成条件 - if (type == FIGURE_UNLOCK_CONDITION.GET_HERO) { - let [hid] = params; - if (paramHid == hid) flag = true; - reason = ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE; - } else if (type == FIGURE_UNLOCK_CONDITION.HERO_FAVOR) { - let [hid, favourLv] = params; - if (paramHid == hid && paramFavourLv >= favourLv) flag = true; - reason = ITEM_CHANGE_REASON.HERO_FAVOR_UNLOCK_FIGURE; - } else if (type == FIGURE_UNLOCK_CONDITION.GET_SKIN) { - let [id] = params; - if (paramSkinId == id) flag = true; - reason = ITEM_CHANGE_REASON.ADD_SKIN_UNLOCK_FIGURE; - } else if (type == FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES) { - let [winStreakNum] = params; - if (paramWinStreakNum >= winStreakNum) flag = true; - reason = ITEM_CHANGE_REASON.PVP_SERIES_UNLOCK_FIGURE; - } - if (!flag) continue; - let dicGood = gameData.goods.get(gid); - if (!dicGood) continue; - let dicItid = ITID.get(dicGood.itid); - if (!dicItid) continue; - - if (dicItid.type == CONSUME_TYPE.HEAD) { - let figure = unlockSingleFigure(heads, gid, reason, false, id); - if (figure && figure.unlocked) figureInfo.heads.push(figure); - } else if (dicItid.type == CONSUME_TYPE.FRAME) { - let figure = unlockSingleFigure(frames, gid, reason, false, id); - if (figure && figure.unlocked) figureInfo.frames.push(figure); - } else if (dicItid.type == CONSUME_TYPE.SPINE) { - let figure = unlockSingleFigure(spines, gid, reason, false, id); - if (figure && figure.unlocked) figureInfo.spines.push(figure); - } else { - continue; - } - - } - - } - } - return { figureInfo, heads, frames, spines }; -} - - - -// 直接获得形象/相框 -export async function addFigure(roleId: string, ids: number[], reason: number) { - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); - - if (!role) return false; - let { heads, frames, spines } = role; - - let figureInfo = { heads: [], frames: [], spines: [] }; - for (let gid of ids) { - let dicGoods = gameData.goods.get(gid); - if (!dicGoods) continue; - let dicItid = ITID.get(dicGoods.itid); - if (!dicItid) continue; - - if (dicItid.type == CONSUME_TYPE.HEAD) { - let figure = unlockSingleFigure(heads, gid, reason, true); - if (figure && figure.unlocked) figureInfo.heads.push(figure); - } else if (dicItid.type == CONSUME_TYPE.FRAME) { - let figure = unlockSingleFigure(frames, gid, reason, true); - if (figure && figure.unlocked) figureInfo.frames.push(figure); - } else if (dicItid.type == CONSUME_TYPE.SPINE) { - let figure = unlockSingleFigure(spines, gid, reason, true); - if (figure && figure.unlocked) figureInfo.spines.push(figure); - } else { - continue; - } - } - - role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines }); - return figureInfo; -} - -/** - * 根据物品id解锁/获得玩家数据 - * @param dbFigures 数据库内字段 - * @param id 物品id - * @param unlockDirect 是否不计算解锁条件直接解锁 - * @param conditionId 条件id - */ -function unlockSingleFigure(dbFigures: Figure[], id: number, reason: number, unlockDirect = false, conditionId?: number) { - let index = dbFigures.findIndex(cur => cur.id == id); - let figure = dbFigures[index]; - if (index == -1) { - figure = new Figure(id, false); - dbFigures.push(figure); - index = dbFigures.length - 1; - } - if (figure.unlocked) return; // 已解锁过 - if (!figure.unlockedId) figure.unlockedId = new Array(); - - let dicGoods = gameData.goods.get(id); - - let hasUnlockedAll = true; - if (!unlockDirect) { // 不能直接获得,需要通过type解锁 - if (figure.unlockedId.includes(conditionId)) return; - - figure.unlockedId.push(conditionId); - - for (let { id: cid } of dicGoods.condition) { - if (!figure.unlockedId.includes(cid)) { - hasUnlockedAll = false; break; - } - } - } - if (hasUnlockedAll) { - figure.unlocked = true; - delete figure.unlockedId; - - if (dicGoods.timeLimit) { - figure.time = nowSeconds() + dicGoods.timeLimit * 86400 - } - } - - figure.inc = 1; - figure.reason = reason; - dbFigures[index] = figure; - return figure -} - -// async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number, allSkins?: SkinType[]) { -// if(!allSkins) allSkins = await SkinModel.findbyRoleAndHid(roleId, hid); -// let skin = await increaseSkin(roleId, roleName, initialSkin); -// if(skin) allSkins.push(skin); -// let skins: { id: number, skin: string, enable: boolean }[] = []; -// for(let skin of allSkins) { -// skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin }); -// } - -// return skins -// } - -export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) { - let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; - for(let {heads, frames, spines} of figureInfos) { - for(let head of heads) { - figureInfo.heads.push(head); - } - for(let frame of frames) { - figureInfo.frames.push(frame); - } - for(let spine of spines) { - figureInfo.spines.push(spine); - } - } - return figureInfo; -} - -// export class CreateHero { -// roleId: string; -// roleName: string; -// serverId: number; - -// constructor(roleId: string, roleName: string, serverId: number) { - -// } -// } \ No newline at end of file +import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY_TYPE, MAIL_TYPE, HANDLE_REWARD_TYPE, HERO_SYSTEM_TYPE, CURRENCY_BY_TYPE, ITEM_CHANGE_REASON, TA_USERSET_TYPE, TA_EVENT, POP_UP_SHOP_CONDITION_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, PUSH_ROUTE, ACTIVITY_TYPE } from '@consts'; +import { getDecimalCnt, getRandEelm, getRandEelmWithWeight, getRandValueByMinMax, } from '@pubUtils/util'; +import { RoleModel, RoleType } from '@db/Role'; +import { setAp } from '../actionPointService'; +import { ItemModel, } from '@db/Item'; +import { ItemInter, } from '@pubUtils/interface'; +import { gameData, getDefArtifactByGid } from '@pubUtils/data'; +import { uniq } from 'underscore'; +import { EPlace, HeroModel, HeroType, } from '@db/Hero'; +import { Figure } from '@domain/dbGeneral'; +import { ArtifactParam, JewelParam } from '@domain/roleField/hero'; +import { HeroSkin } from '@db/Hero'; +import { BAG } from '@pubUtils/dicParam'; +import { sendMailByContent } from '../mailService'; +import { SkinModel, } from '@db/Skin'; +import { reportTAEvent, reportTAUserSet } from '../sdkService'; +import { saveCoinChangeLog, saveFigureInfoLog, saveGoldChangeLog, saveItemChangeLog } from '@pubUtils/logUtil'; +import { JewelModel, JewelType, jewelUpdate, RandSe } from '@db/Jewel'; +import { updateEplaces } from '../equipService'; +import { combineItems, getCoinEventProperties, getGoldEventProperties, sortItems } from './util'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { calculateCeWithHero, calculateCeWithRole } from '../playerCeService'; +import { sendMessageToUserWithSuc } from '../pushService'; +import { filterGoods } from '../dataService'; +import { ArtifactModel, ArtifactModelType, ArtifactModelUpdate } from '@db/Artifact'; +import { ActivityItemModel } from '@db/ActivityItem'; +import { getActivitiesByType } from '../activity/activityService'; +import { ActivityModelType } from '@db/Activity'; +import { ForgeData } from '@domain/activityField/forgeField'; +import { getRoleCreateTime, getServerCreateTime } from '../redisService'; + +export async function handleCost(roleId: string, sid: string, goods: Array, reason: ITEM_CHANGE_REASON) { + + let { items, jewels, gold, coin, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.COST); + let jewelSeqIds = jewels.map(cur => cur.seqId); + let resJewels: JewelType[] = []; + let artifactSeqIds = artifacts.map(cur => cur.seqId); + let resArtifacts: ArtifactModelType[] = []; + + // 检查货币是否充足 + let role = await RoleModel.findByRoleId(roleId); + if (gold.length > 0 || coin.length > 0) { + let { gold: originGold, coin: originCoin } = role; + for(let {count} of gold) { originGold -= count }; + for(let count of coin) { originCoin -= count }; + if(originGold < 0 || originCoin < 0) return false; + } + //检查装备是否存在 + if (jewels.length > 0) { + resJewels = await JewelModel.findbySeqIds(jewelSeqIds); + if (resJewels.length < jewels.length) + return false; + } + //检查宝物是否存在 + if (artifacts.length > 0) { + resArtifacts = await ArtifactModel.findbySeqIds(roleId, artifactSeqIds); + if (resArtifacts.length < artifacts.length) + return false; + } + //检查并修改道具 + if (items.length > 0) { + let { hasError, result } = await ItemModel.decreaseItems(roleId, items); + if (hasError) return false; + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid); + saveItemChangeLog(roleId, result, reason); + } + //检查并修改道具 + if (activityItems.length > 0) { + let { hasError, result } = await ActivityItemModel.decreaseActivityItems(roleId, activityItems); + if (hasError) return false; + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: result.map(cur => ({...cur, reason })) }, sid); + saveItemChangeLog(roleId, result, reason); + } + + //删除装备 + if (resJewels.length > 0) { + let heroMap = new Map(); + for(let jewel of resJewels) { + if(jewel.hid > 0) { + if(!heroMap.has(jewel.hid)) { + let hero = await HeroModel.findByHidAndRole(jewel.hid, roleId); + heroMap.set(jewel.hid, { hero, jewels: [] }); + } + heroMap.get(jewel.hid).jewels.push(jewel); + } + } + for(let [hid, {hero, jewels} ] of heroMap) { + // 脱下天晶石 + let update = new Map>(); + for(let jewel of jewels) { + await JewelModel.putOnOrOff(jewel.id, 0, 0); + let curEquip = hero.ePlace.find(cur => cur.jewel == jewel.id); + if(!!curEquip) { + update.set(curEquip.id, { jewel: 0 }); + } + } + let { newEplace } = updateEplaces(hero.ePlace, update); + await calculateCeWithHero(HERO_SYSTEM_TYPE.EQUIP_STRENGTH, roleId, role.serverId, sid, hid, { ePlace: newEplace }, { ePlaceIds: [...update.keys()] }); + } + + + let jewels = await JewelModel.deleteBySeqIds(roleId, jewelSeqIds); + saveItemChangeLog(roleId, jewels.map(jewel => ({ id: jewel.id, count: 1, inc: -1 })), reason); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_DEL, { jewels: jewels.map(jewel => ({ seqId: jewel.seqId, id: jewel.id, inc: -1, reason })) }, sid); + } + + //删除宝物 + if (resArtifacts.length > 0) { + let heroMap = new Map(); + for(let artifact of resArtifacts) { + if(artifact.hid > 0) { + heroMap.set(artifact.hid, { artifact }); + } + } + for(let [hid, { artifact } ] of heroMap) { + // 脱下天晶石 + await ArtifactModel.putOnOrOff(roleId, artifact.id, 0); + await calculateCeWithHero(HERO_SYSTEM_TYPE.PUT_ARTIFACT, roleId, role.serverId, sid, hid, { artifact: 0 }); + } + + let artifacts = await ArtifactModel.deleteBySeqIds(roleId, artifactSeqIds); + saveItemChangeLog(roleId, artifacts.map(artifact => ({ id: artifact.id, count: 1, inc: -1 })), reason); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_DEL, { artifacts: artifacts.map(artifact => ({ seqId: artifact.seqId, id: artifact.id, inc: -1, reason })) }, sid); + } + + //消耗玩家货币 + if (gold.length > 0 || coin.length > 0) { + let costGold = gold.reduce((pre, cur) => pre + cur.count, 0); + let costCoin = coin.reduce((pre, cur) => pre + cur, 0); + role = await RoleModel.decreaseGoldAndCoin(roleId, gold, costCoin); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin, totalCost: role.totalCost }, sid); + + if(costGold > 0) { + reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getGoldEventProperties(costGold, role.gold, reason)); + reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold }); + saveGoldChangeLog(roleId, role.gold, -1 * costGold, reason); + } + if(costCoin > 0) { + reportTAEvent(roleId, TA_EVENT.ITEM_CONSUME, getCoinEventProperties(costCoin, role.coin, reason)); + reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin }); + saveCoinChangeLog(roleId, role.coin, -1 * costCoin, reason); + } + + } + + return true; +} + +export async function addItems(roleId: string, roleName: string, sid: string, goods: Array, reason: ITEM_CHANGE_REASON) { + goods = filterGoods(goods, obj => obj.id, roleId, reason); + let { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems } = sortItems(goods, HANDLE_REWARD_TYPE.RECEIVE); + let showItems: { id: number, seqId?: number|string, count: number, isBag?: boolean, expireTime?: number }[] = []; + let role = await RoleModel.findByRoleId(roleId, '-warCount -topLineup'); + // 1. 装备处理 + if(jewels.length > 0) { + let { jewelCount = 0 } = role; + let incJewels = jewels, mailJewels: { id?: number, hid?: number, seqId?: number }[] = []; + if(jewels.length + jewelCount > BAG.BAG_EQUIP_UPLIMITED) { // 装备上限 + let inc = BAG.BAG_EQUIP_UPLIMITED - jewelCount; + if(inc < 0) inc = 0; + incJewels = jewels.slice(0, inc); + mailJewels = jewels.slice(inc); + } + + // 直接加的 + let { jewels: jewelInfos } = await addJewels(roleId, roleName, <{id: number }[]>incJewels, reason); + for (let jewel of jewelInfos) { + showItems.push({ seqId: jewel.seqId, id: jewel.id, count: 1, isBag: true }); + } + for(let jewel of combineItems(mailJewels)) { + showItems.push({ id: jewel.id, count: jewel.count, isBag: false }); + } + //装备推送 + if (!!jewelInfos.length) + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.JEWEL_ADD, { jewelInfos }, sid); + //统计装备 + if (jewelInfos.length > 0) { + saveItemChangeLog(roleId, jewelInfos, reason); + } + // 发邮件的 + if(mailJewels.length > 0) { + await sendMailByContent(MAIL_TYPE.EQUIP_OVER, roleId, { goods: combineItems(mailJewels) }); + } + } + + // 2. 道具处理 + if(items.length > 0) { + let { items: itemInfos } = await addBags(roleId, roleName, items, reason); + for (let item of items) { + showItems.push({ id: item.id, count: item.count }); + } + //背包除去装备推送 + if (!!itemInfos.length) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ITEM_UPDATE, { goods: itemInfos }, sid); + saveItemChangeLog(roleId, itemInfos, reason); + } + + } + + // 3. 货币推送 + if(gold.length > 0 || coin.length > 0 || ap > 0) { + await setAp(role.serverId, roleId, null, role.lv, ap, sid, reason); + let incCoin = coin.reduce((pre, cur) => pre + cur, 0); + let incGold = gold.reduce((pre, cur) => pre + cur.count, 0); + role = await RoleModel.increaseGoldAndCoin(roleId, gold, incCoin); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { gold: role.gold, coin: role.coin }, sid); + + if(gold.length > 0) { + gold.forEach(({ count }) => { + showItems.push(getGoldObject(count)); + }); + reportTAEvent(roleId, TA_EVENT.ITEM_GET, getGoldEventProperties(incGold, role.gold, reason)); + reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_gold: role.gold }); + saveGoldChangeLog(roleId, role.gold, incGold, reason ); + } + if(coin.length > 0) { + coin.forEach(count => { + showItems.push(getCoinObject(count)); + }); + reportTAEvent(roleId, TA_EVENT.ITEM_GET, getCoinEventProperties(incCoin, role.coin, reason)); + reportTAUserSet(TA_USERSET_TYPE.SET, roleId, { current_coin: role.coin }); + saveCoinChangeLog(roleId, role.coin, incCoin, reason); + } + if(ap > 0) { + showItems.push(getApObject(ap)); + } + } + + // 4. 皮肤处理 + let figureInfos:{ heads: Figure[], frames: Figure[], spines: Figure[] }[] = []; // 头像变化推送信息 + if(skins.length > 0) { + let heroskins: {skins: HeroSkin[], hid: number}[] = []; // 皮肤推送信息 + let skinInfos: {id: number, hid: number, count: number, inc: number, reason: number }[] = []; + let calAllHeroResult = undefined; // 全局战力变化推送 + + for (let skinId of skins) {//皮肤推送 + let hero = await addSkin(roleId, roleName, role.serverId, sid, skinId, false); + skinInfos.push({ id: skinId, hid: hero? hero.hid: 0, count: 1, inc: 1, reason }) + showItems.push({ id: skinId, count: 1 }); + if(hero) heroskins.push({ skins: hero.skins, hid: hero.hid }); + } + if (!!skinInfos.length) { + pushHeroSkinMsg(heroskins, skinInfos, roleId, sid); // 推送onHeroSkinChange + saveItemChangeLog(roleId, skinInfos, reason); + } + } + + // 5. 获得头像和相框等 + if(figures.length > 0) { + let figureInfo = await addFigure(roleId, figures, reason); + if(figureInfo) figureInfos.push(figureInfo); + for (let id of figures) {//皮肤推送 + showItems.push({ id, count: 1 }); + } + } + + // 获得头像或相框或形象推送 + if(!!figureInfos && figureInfos.length > 0) { + for(let figureInfo of figureInfos) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid); + saveFigureInfoLog(roleId, figureInfo, reason) + } + } + + // 6. 宝物处理 + + if(artifacts.length > 0) { + let { artifactCount = 0 } = role; + let incArtifacts = artifacts, mailArtifacts: { id?: number, seqId?: number|string }[] = []; + if(artifacts.length + artifactCount > BAG.BAG_ARTIFACT_UPLIMITED) { // 装备上限 + let inc = BAG.BAG_ARTIFACT_UPLIMITED - artifactCount; + if(inc < 0) inc = 0; + incArtifacts = artifacts.slice(0, inc); + mailArtifacts = artifacts.slice(inc); + } + + // 直接加的 + let { artifacts: artifactInfos } = await addArtifacts(roleId, roleName, <{id: number}[]>incArtifacts, reason); + for (let artifact of artifactInfos) { + showItems.push({ seqId: artifact.seqId, id: artifact.id, count: 1, isBag: true }); + } + for(let artifact of combineItems(mailArtifacts)) { + showItems.push({ id: artifact.id, count: artifact.count, isBag: false }); + } + //装备推送 + if (!!artifactInfos.length) + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ARTIFACT_ADD, { artifacts: artifactInfos }, sid); + //统计装备 + if (artifactInfos.length > 0) { + saveItemChangeLog(roleId, artifactInfos, reason); + } + // 发邮件的 + if(mailArtifacts.length > 0) { + await sendMailByContent(MAIL_TYPE.ARTIFACT_OVER, roleId, { goods: combineItems(mailArtifacts) }); + } + } + + // 7. 活动道具处理 + if(activityItems.length > 0) { + let { items: itemInfos } = await addActivityItems(role, activityItems, reason); + for (let item of itemInfos) { + showItems.push({ id: item.id, count: item.inc, expireTime: item.expireTime }); + } + //背包除去装备推送 + if (!!itemInfos.length) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_ITEM_UPDATE, { goods: itemInfos }, sid); + saveItemChangeLog(roleId, itemInfos, reason); + } + + } + return showItems; +} + + +export async function checkGoods(roleId: string, goodIds: Array) { + let jewelSeqIds: Array = []; + let itemIds: Array = []; + let hids: Array = []; + goodIds = uniq(goodIds); + for (let goodId of goodIds) { + let goodInfo = gameData.goods.get(goodId); + if (!!goodInfo) { + let { table } = ITID.get(goodInfo.itid); + if (table == ITEM_TABLE.EQUIP) { + jewelSeqIds.push(goodId); + } else if (table == ITEM_TABLE.ITEM) { + itemIds.push(goodId); + } + } + } + + //检查装备是否存在 + if (!!jewelSeqIds.length) { + let resJewels = await JewelModel.findbySeqIds(jewelSeqIds); + resJewels = uniq(resJewels, function (resEquip) { + return resEquip.id; + }); + if (resJewels.length < jewelSeqIds.length) + return false; + } + //检查并修改道具 + if (itemIds.length > 0) { + let items = await ItemModel.findbyRoleAndIds(roleId, itemIds); + if (items.length < itemIds.length) + return false; + } + return true; +} + +export async function checkHeroes(roleId: string, hids: number[]) { + if (!!hids.length) { + let heros = await HeroModel.findByHidRange(hids, roleId); + if (heros.length < hids.length) + return false; + } + return true +} + +export async function checkHeroEquips(roleId: string, quality: number) { + return await HeroModel.checkEquipByQuality(roleId, quality); +} + +/** + * 解锁头像/相框 + * @param roleId 玩家id + * @param conditions 解锁条件 + * @param role 如果已查询过role表就直接可以使用 + */ +export async function unlockFigure(sid: string, roleId: string, conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role?: RoleType) { + if (!role || !role.heads || !role.frames) { + role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + } + let { figureInfo, heads, frames, spines } = unlockFigureWithoutSave(conditions, role); + role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines }); + if (!!figureInfo && (figureInfo.heads.length > 0 || figureInfo.frames.length > 0 || figureInfo.spines.length > 0)) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HEAD_CHANGE, { ...figureInfo }, sid); + } +} + + +/** + * 皮肤数据变化去重、推送 + * @param heroskins 推送的皮肤 + * @param roleId 玩家 + */ +function pushHeroSkinMsg(heroskins: {skins: HeroSkin[], hid: number}[], skinInfos: {id: number, hid: number }[], roleId: string, sid: string) { + let pushSkinInfos: {skins: HeroSkin[], hid: number}[] = []; // 可能会有重复的 + for(let { skins, hid } of heroskins) { + let index = pushSkinInfos.findIndex(cur => cur.hid == hid); + if(index == -1) { + pushSkinInfos.push({skins, hid}); + } else { + if(skins.length > pushSkinInfos[index].skins.length) { + pushSkinInfos[index] = {skins, hid}; + } + } + } + if(pushSkinInfos.length > 0 || skinInfos.length > 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, { heros: heroskins, skins: skinInfos }, sid); + } +} + + +/** + * 只插入皮肤,不管那么多的 + * @param roleId + * @param roleName + * @param skinId + * @returns + */ + export async function increaseSkin(roleId:string, roleName: string, skinId: number) { + let dicSkin = gameData.fashion.get(skinId); + if (!dicSkin) return false; + + let skin = await SkinModel.increaseSkin(roleId, skinId, { roleId, roleName, id: skinId, skinName: dicSkin.name, hid: dicSkin.actorId, skinId: dicSkin.heroId }); + if(!skin) return false; // 插入失败 + return skin +} + +/** + * 添加皮肤 + * @param roleId 玩家id + * @param roleName 玩家名 + * @param id 皮肤id + * @param hero 武将,如果已经查询过这个武将就不用再查询一次,主意要select skins字段 + * @returns {{ hero, figureInfo, calAllHeroResult }} hero:添加皮肤后的武将 figureInfo: 触发头像添加信息 calAllHeroResult:全局战力加成后结果 + */ +export async function addSkin(roleId: string, roleName: string, serverId: number, sid: string, skinId: number, enable: boolean, hero?: HeroType) { + let skin = await increaseSkin(roleId, roleName, skinId); + if(!skin) return false; + + if(skin.hid && !hero) hero = await HeroModel.findByHidAndRole(skin.hid, roleId); + let condition = { type: FIGURE_UNLOCK_CONDITION.GET_SKIN, paramSkinId: skinId }; + await unlockFigure(sid, roleId, [condition]); // 解锁头像 + await calculateCeWithRole(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, serverId, sid, {}, { skinId }); // 全局加成 + + if (hero) { // 有武将的,将皮肤链接到武将上 + let curSkin = hero.skins.find(cur => cur.id == skinId); + if (!curSkin) { + hero.skins.push(new HeroSkin(skin, enable)); + await HeroModel.updateHeroInfo(roleId, hero.hid, hero); + } + return hero; + } else { + return null + } +} + +export async function addBags(roleId: string, roleName: string, datas: { id: number, count: number }[], reason: number) { + let items: { id: number, count: number, inc: number }[] = []; + for(let data of datas) { + let item = await addBag(roleId, roleName, data, reason); + items.push(item) + } + return { items } +} + +export async function addBag(roleId: string, roleName: string, data: { id: number, count: number }, reason: number) { + let { id, count } = data; + let { name: itemName, itid, hid } = gameData.goods.get(id); + let { type } = ITID.get(itid); + + let item = await ItemModel.increaseItem(roleId, id, count, { roleId, roleName, itemName, id, type, hid }); + return { id: item.id, count: item.count, inc: count, reason }; +} + +export async function addActivityItems(role: RoleType, datas: { id: number, count: number }[], reason: number) { + let serverTime = await getServerCreateTime(role.serverId); + let createTime = await getRoleCreateTime(role.roleId, role); + let items: { id: number, count: number, inc: number, expireTime: number }[] = []; + for(let data of datas) { + let item = await addActivityItem(role.serverId, role.roleId, role.roleName, data, reason, createTime, serverTime); + if(item) items.push(item) + } + return { items } +} + +export async function addActivityItem(serverId: number, roleId: string, roleName: string, data: { id: number, count: number }, reason: number, createTime: number, serverTime: number) { + let { id, count } = data; + let { name: itemName, activityType } = gameData.goods.get(id); + let activities = await getActivitiesByType(serverId, activityType); + for(let activity of activities) { + let activityData = getActivityData(activity as ActivityModelType, createTime, serverTime); + if(!activityData || !activityData.canShow()) continue; + let item = await ActivityItemModel.increaseActivityItem(roleId, id, count, { roleId, roleName, itemName, id, expireTime: Math.floor(activityData.nextRefreshTime/1000) }); + return { id: item.id, count: item.count, inc: count, expireTime: item.expireTime, reason }; + } +} + +function getActivityData(activity: ActivityModelType, createTime: number, serverTime: number) { + switch(activity.type) { + case ACTIVITY_TYPE.FORGE: + return new ForgeData(activity, createTime, serverTime) + default: + return null + } +} + +export async function addJewels(roleId: string, roleName: string, jewels: { id: number, }[], reason: number) { + let jewelInfo: jewelUpdate[] = []; + for(let jewel of jewels) { + let info = await getAddJewelInfo(roleId, roleName, jewel); + jewelInfo.push(info); + } + + const jewelResult = await JewelModel.createJewels(roleId, jewelInfo); + return { jewels: jewelResult.map(jewel => new JewelParam(jewel, true, reason))} +} + +export async function getAddJewelInfo(roleId: string, roleName: string, jewel: { id: number, }) { + let { id, } = jewel; + let { name, randomEffect, effectCount, rareEffect } = gameData.jewel.get(id); + + // 随机属性 + let randomResult: number[] = getRandEelm(randomEffect, effectCount); + let rareResult: number[] = getRandEelm(rareEffect, 1); + + let randSe: Array = randomResult.map((id: number, index: number) => { + return getJewelRandSe(index + 1, id); + }); + let rareSe: Array = rareResult.map((id: number, index: number) => { + return getJewelRandSe(index + 1, id); + }); + + return { roleId, roleName, id, name, randSe, rareSe }; +} + +/** + * 天晶石已知词条随机值 + * @param id 词条位置,第几条 + * @param seid 词条id + * @returns + */ +export function getJewelRandSe(id: number, seid: number) { + let dicRandom = gameData.randomEffectPool.get(seid) + // console.log('#### dicRandom', dicRandom) + let rand = 0; + let planPool = gameData.randomEffectPoolPlan.get(dicRandom.planId); + if(planPool && planPool.length > 0) { + let result = getRandEelmWithWeight(planPool); + if(result) rand = Math.round(result.dic.num * 100)/100; + } else { + let randResult = getRandValueByMinMax(dicRandom.Min, dicRandom.Max, getDecimalCnt(dicRandom.gap)); + let n = Math.floor((randResult - dicRandom.Min)/dicRandom.gap); + rand = Math.round(dicRandom.Min + n * dicRandom.gap * 100)/100; + } + return new RandSe(id, dicRandom.id, rand); +} + +export async function addArtifacts(roleId: string, roleName: string, artifacts: { id: number, }[], reason: number) { + let artifactInfos: ArtifactModelUpdate[] = []; + for(let { id } of artifacts) { + let dicArtifact = getDefArtifactByGid(id); + if(dicArtifact) { + let { goodId, artifactId, quality, qualityStage } = dicArtifact; + artifactInfos.push({ roleId, roleName, id: goodId, artifactId, quality, qualityStage }); + } + } + + const artifactResult = await ArtifactModel.createArtifacts(roleId, artifactInfos); + return { artifacts: artifactResult.map(artifact => new ArtifactParam(artifact, true, reason))} +} + +export function getGoldId() { + return CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); +} + +/** + * @description 获取元宝物品 { id, count } + * @param count 元宝数量 + */ +export function getGoldObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count }; +} + +/** + * @description 获取金币物品 { id, count } + * @param count 元宝数量 + */ +export function getCoinObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count }; +} + +/** + * @description 获取体力物品 { id, count } + * @param count 体力数量 + */ + export function getApObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ACTION_POINT), count }; +} +/** + * @description 获取友情点物品 { id, count } + * @param count 友情点数量 + */ +export function getFriendPointObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.FRIEND_POINT), count }; +} + +/** + * @description 获取功勋物品 { id, count } + * @param count 功勋数量 + */ +export function getHonourObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.HONOUR), count }; +} + +/** + * @description 获取代金券物品 { id, count } + * @param count 元宝数量 + */ + export function getVoucherObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER), count }; +} + +export function getVoucherCoinObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN), count }; +} + +export function checkVoucherId(id: number) { + let voucher = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER); + let voucherCoin = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.VOUCHER_COIN); + return id == voucher || id == voucherCoin; +} + +export function getRougeTechScoreObject(count: number) { + return { id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.ROUGE_TECH)||0, count }; +} + +/** + * 返回 解锁头像/相框 + * @param conditions 解锁条件 + * @param role 如果已查询过role表就直接可以使用 + */ + export function unlockFigureWithoutSave(conditions: { type: number, paramHid?: number, paramFavourLv?: number, paramSkinId?: number, paramWinStreakNum?: number }[], role: RoleType) { + + let { heads, frames, spines, roleId } = role; + let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; + for (let { type, paramHid, paramFavourLv, paramSkinId, paramWinStreakNum } of conditions) { + let canUnLockList = gameData.figureCondition.get(type); + if (canUnLockList) { + canUnLockList = filterGoods(canUnLockList, obj => obj.gid, roleId, ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE); + let reason = 0; + + for (let { id, params, gid } of canUnLockList) { + let flag = false; // 是否达成条件 + if (type == FIGURE_UNLOCK_CONDITION.GET_HERO) { + let [hid] = params; + if (paramHid == hid) flag = true; + reason = ITEM_CHANGE_REASON.GET_HERO_UNLOCK_FIGURE; + } else if (type == FIGURE_UNLOCK_CONDITION.HERO_FAVOR) { + let [hid, favourLv] = params; + if (paramHid == hid && paramFavourLv >= favourLv) flag = true; + reason = ITEM_CHANGE_REASON.HERO_FAVOR_UNLOCK_FIGURE; + } else if (type == FIGURE_UNLOCK_CONDITION.GET_SKIN) { + let [id] = params; + if (paramSkinId == id) flag = true; + reason = ITEM_CHANGE_REASON.ADD_SKIN_UNLOCK_FIGURE; + } else if (type == FIGURE_UNLOCK_CONDITION.PVP_WIN_SERIES) { + let [winStreakNum] = params; + if (paramWinStreakNum >= winStreakNum) flag = true; + reason = ITEM_CHANGE_REASON.PVP_SERIES_UNLOCK_FIGURE; + } + if (!flag) continue; + let dicGood = gameData.goods.get(gid); + if (!dicGood) continue; + let dicItid = ITID.get(dicGood.itid); + if (!dicItid) continue; + + if (dicItid.type == CONSUME_TYPE.HEAD) { + let figure = unlockSingleFigure(heads, gid, reason, false, id); + if (figure && figure.unlocked) figureInfo.heads.push(figure); + } else if (dicItid.type == CONSUME_TYPE.FRAME) { + let figure = unlockSingleFigure(frames, gid, reason, false, id); + if (figure && figure.unlocked) figureInfo.frames.push(figure); + } else if (dicItid.type == CONSUME_TYPE.SPINE) { + let figure = unlockSingleFigure(spines, gid, reason, false, id); + if (figure && figure.unlocked) figureInfo.spines.push(figure); + } else { + continue; + } + + } + + } + } + return { figureInfo, heads, frames, spines }; +} + + + +// 直接获得形象/相框 +export async function addFigure(roleId: string, ids: number[], reason: number) { + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.GET_HEADS); + + if (!role) return false; + let { heads, frames, spines } = role; + + let figureInfo = { heads: [], frames: [], spines: [] }; + for (let gid of ids) { + let dicGoods = gameData.goods.get(gid); + if (!dicGoods) continue; + let dicItid = ITID.get(dicGoods.itid); + if (!dicItid) continue; + + if (dicItid.type == CONSUME_TYPE.HEAD) { + let figure = unlockSingleFigure(heads, gid, reason, true); + if (figure && figure.unlocked) figureInfo.heads.push(figure); + } else if (dicItid.type == CONSUME_TYPE.FRAME) { + let figure = unlockSingleFigure(frames, gid, reason, true); + if (figure && figure.unlocked) figureInfo.frames.push(figure); + } else if (dicItid.type == CONSUME_TYPE.SPINE) { + let figure = unlockSingleFigure(spines, gid, reason, true); + if (figure && figure.unlocked) figureInfo.spines.push(figure); + } else { + continue; + } + } + + role = await RoleModel.updateRoleInfo(roleId, { heads, frames, spines }); + return figureInfo; +} + +/** + * 根据物品id解锁/获得玩家数据 + * @param dbFigures 数据库内字段 + * @param id 物品id + * @param unlockDirect 是否不计算解锁条件直接解锁 + * @param conditionId 条件id + */ +function unlockSingleFigure(dbFigures: Figure[], id: number, reason: number, unlockDirect = false, conditionId?: number) { + let index = dbFigures.findIndex(cur => cur.id == id); + let figure = dbFigures[index]; + if (index == -1) { + figure = new Figure(id, false); + dbFigures.push(figure); + index = dbFigures.length - 1; + } + if (figure.unlocked) return; // 已解锁过 + if (!figure.unlockedId) figure.unlockedId = new Array(); + + let dicGoods = gameData.goods.get(id); + + let hasUnlockedAll = true; + if (!unlockDirect) { // 不能直接获得,需要通过type解锁 + if (figure.unlockedId.includes(conditionId)) return; + + figure.unlockedId.push(conditionId); + + for (let { id: cid } of dicGoods.condition) { + if (!figure.unlockedId.includes(cid)) { + hasUnlockedAll = false; break; + } + } + } + if (hasUnlockedAll) { + figure.unlocked = true; + delete figure.unlockedId; + + if (dicGoods.timeLimit) { + figure.time = nowSeconds() + dicGoods.timeLimit * 86400 + } + } + + figure.inc = 1; + figure.reason = reason; + dbFigures[index] = figure; + return figure +} + +// async function getSkinsOfThisHero(roleId: string, roleName: string, hid: number, initialSkin: number, allSkins?: SkinType[]) { +// if(!allSkins) allSkins = await SkinModel.findbyRoleAndHid(roleId, hid); +// let skin = await increaseSkin(roleId, roleName, initialSkin); +// if(skin) allSkins.push(skin); +// let skins: { id: number, skin: string, enable: boolean }[] = []; +// for(let skin of allSkins) { +// skins.push({ id: skin.id, skin: skin._id, enable: skin.id == initialSkin }); +// } + +// return skins +// } + +export function combineFigureInfo(figureInfos: { heads: Figure[], frames: Figure[], spines: Figure[] }[]) { + let figureInfo = { heads: new Array
(), frames: new Array
(), spines: new Array
() }; + for(let {heads, frames, spines} of figureInfos) { + for(let head of heads) { + figureInfo.heads.push(head); + } + for(let frame of frames) { + figureInfo.frames.push(frame); + } + for(let spine of spines) { + figureInfo.spines.push(spine); + } + } + return figureInfo; +} + +// export class CreateHero { +// roleId: string; +// roleName: string; +// serverId: number; + +// constructor(roleId: string, roleName: string, serverId: number) { + +// } +// } diff --git a/game-server/app/services/role/util.ts b/game-server/app/services/role/util.ts index 7044be472..271b67c6f 100644 --- a/game-server/app/services/role/util.ts +++ b/game-server/app/services/role/util.ts @@ -1,139 +1,139 @@ -import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, HANDLE_REWARD_TYPE, ITEM_CHANGE_REASON, CURRENCY_BY_TYPE } from '../../consts'; -import { ItemInter, RewardInter, } from '../../pubUtils/interface'; -import { gameData } from '../../pubUtils/data'; -import { errlogger } from '../../util/logger'; - -export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) { - let items: { id: number, count: number }[] = []; // 可叠加道具 - let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备 - let artifacts: { seqId?: number|string, id?: number }[] = []; // 不可叠加宝物 - let gold: { count: number, isPay: boolean }[] = []; // 金币 - let coin: number[] = []; - let ap: number = 0; - let skins: number[] = []; - let figures: number[] = []; - let activityItems: { id: number, count: number, expireTime?: number }[] = []; // 可叠加道具 - - for(let good of goods) { - if(good.count == 0) continue; - let dicGood = gameData.goods.get(good.id); - if(!dicGood) { - errlogger.error(`物品 ${good.id} 未配置`); - continue; - } - let dicItid = ITID.get(dicGood.itid); - if(!dicItid) { - errlogger.error(`itid ${dicGood.itid} 未配置`); - continue; - } - let { type, table, isCurrency } = dicItid; - if(table == ITEM_TABLE.JEWEL) { // 装备 - if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { - for(let i = 0; i < good.count; i++) { - jewels.push({ id: good.id, hid: good.hid }) - } - } else { - if(!!good.seqId) { - jewels.push({ seqId: good.seqId }); - } - } - } else if (table == ITEM_TABLE.ITEM) { // 可叠加道具 - let index = items.findIndex(cur => cur.id == good.id); - if(index >= 0) { - items[index].count += good.count; - } else { - items.push({ id: good.id, count: good.count }); - } - } else if (table == ITEM_TABLE.SKIN) { // 皮肤,不可重复获得,不可删 - if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { - let index = skins.indexOf(good.id); - if (index == -1) { - skins.push(good.id); - } - } - } else if (table == ITEM_TABLE.ROLE) { - if(isCurrency) { // 3种货币 - let dicCurrency = CURRENCY.get(good.id); - if(dicCurrency) { - if(dicCurrency.type == CURRENCY_TYPE.GOLD) { // 金币,区分付费和免费,默认免费 - let index = gold.findIndex(cur => cur.isPay == !!good.isPay); - if(index >= 0) { - gold[index].count += good.count; - } else { - gold.push({ count: good.count, isPay: !!good.isPay }); - } - } else if (dicCurrency.type == CURRENCY_TYPE.COIN) { // 铜钱 - coin.push(good.count); - } else if (dicCurrency.type == CURRENCY_TYPE.ACTION_POINT) { // 体力 - ap += good.count; - } - } - } else { - if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { // 头像等,不可重复获得,不可删 - let index = figures.indexOf(good.id); - if (index == -1) { - figures.push(good.id); - } - } - } - } else if (table == ITEM_TABLE.ARTIFACT) { - if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { - for(let i = 0; i < good.count; i++) { - artifacts.push({ id: good.id }) - } - } else { - if(!!good.seqId) { - artifacts.push({ seqId: good.seqId }); - } - } - } else if (table == ITEM_TABLE.ACTIVITY_ITEM) { // 活动道具,限时,可堆叠 - let index = activityItems.findIndex(cur => cur.id == good.id); - if(index >= 0) { - activityItems[index].count += good.count; - } else { - activityItems.push({ id: good.id, count: good.count, expireTime: good.expireTime }); - } - } - - } - - return { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems } -} - -export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) { - let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); - let dicGoods = gameData.goods.get(id); - return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason } -} - -export function getCoinEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) { - let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); - let dicGoods = gameData.goods.get(id); - return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason } -} - -export function combineItems(items: { id?: number, count?: number, seqId?: number|string, isBag?: boolean }[]) { - let result: { id: number, count: number, seqId?: number|string, isBag?: boolean }[] = []; - for(let { id, count = 1, seqId, isBag } of items) { - let dicGoods = gameData.goods.get(id); - let dicItid = ITID.get(dicGoods.itid); - if(dicItid.table != 'jewel' && dicItid.table != 'artifact') { - let index = result.findIndex(cur => cur.id == id); - if(index == -1) { - result.push({ id, count, seqId, isBag }); - } else { - result[index].count += count; - } - } else { - result.push({ id, count, seqId, isBag }); - } - } - return result; -} - - -export function transPiece(hid: number) { - let dicHero = gameData.hero.get(hid); - let count = gameData.heroTransPiece.get(dicHero.quality); - return { pieceId: dicHero.pieceId, count } -} \ No newline at end of file +import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, HANDLE_REWARD_TYPE, ITEM_CHANGE_REASON, CURRENCY_BY_TYPE } from '@consts'; +import { ItemInter, RewardInter, } from '@pubUtils/interface'; +import { gameData } from '@pubUtils/data'; +import { errlogger } from '../../util/logger'; + +export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) { + let items: { id: number, count: number }[] = []; // 可叠加道具 + let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备 + let artifacts: { seqId?: number|string, id?: number }[] = []; // 不可叠加宝物 + let gold: { count: number, isPay: boolean }[] = []; // 金币 + let coin: number[] = []; + let ap: number = 0; + let skins: number[] = []; + let figures: number[] = []; + let activityItems: { id: number, count: number, expireTime?: number }[] = []; // 可叠加道具 + + for(let good of goods) { + if(good.count == 0) continue; + let dicGood = gameData.goods.get(good.id); + if(!dicGood) { + errlogger.error(`物品 ${good.id} 未配置`); + continue; + } + let dicItid = ITID.get(dicGood.itid); + if(!dicItid) { + errlogger.error(`itid ${dicGood.itid} 未配置`); + continue; + } + let { type, table, isCurrency } = dicItid; + if(table == ITEM_TABLE.JEWEL) { // 装备 + if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { + for(let i = 0; i < good.count; i++) { + jewels.push({ id: good.id, hid: good.hid }) + } + } else { + if(!!good.seqId) { + jewels.push({ seqId: good.seqId }); + } + } + } else if (table == ITEM_TABLE.ITEM) { // 可叠加道具 + let index = items.findIndex(cur => cur.id == good.id); + if(index >= 0) { + items[index].count += good.count; + } else { + items.push({ id: good.id, count: good.count }); + } + } else if (table == ITEM_TABLE.SKIN) { // 皮肤,不可重复获得,不可删 + if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { + let index = skins.indexOf(good.id); + if (index == -1) { + skins.push(good.id); + } + } + } else if (table == ITEM_TABLE.ROLE) { + if(isCurrency) { // 3种货币 + let dicCurrency = CURRENCY.get(good.id); + if(dicCurrency) { + if(dicCurrency.type == CURRENCY_TYPE.GOLD) { // 金币,区分付费和免费,默认免费 + let index = gold.findIndex(cur => cur.isPay == !!good.isPay); + if(index >= 0) { + gold[index].count += good.count; + } else { + gold.push({ count: good.count, isPay: !!good.isPay }); + } + } else if (dicCurrency.type == CURRENCY_TYPE.COIN) { // 铜钱 + coin.push(good.count); + } else if (dicCurrency.type == CURRENCY_TYPE.ACTION_POINT) { // 体力 + ap += good.count; + } + } + } else { + if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { // 头像等,不可重复获得,不可删 + let index = figures.indexOf(good.id); + if (index == -1) { + figures.push(good.id); + } + } + } + } else if (table == ITEM_TABLE.ARTIFACT) { + if(handleType == HANDLE_REWARD_TYPE.RECEIVE) { + for(let i = 0; i < good.count; i++) { + artifacts.push({ id: good.id }) + } + } else { + if(!!good.seqId) { + artifacts.push({ seqId: good.seqId }); + } + } + } else if (table == ITEM_TABLE.ACTIVITY_ITEM) { // 活动道具,限时,可堆叠 + let index = activityItems.findIndex(cur => cur.id == good.id); + if(index >= 0) { + activityItems[index].count += good.count; + } else { + activityItems.push({ id: good.id, count: good.count, expireTime: good.expireTime }); + } + } + + } + + return { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems } +} + +export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) { + let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); + let dicGoods = gameData.goods.get(id); + return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason } +} + +export function getCoinEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) { + let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); + let dicGoods = gameData.goods.get(id); + return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason } +} + +export function combineItems(items: { id?: number, count?: number, seqId?: number|string, isBag?: boolean }[]) { + let result: { id: number, count: number, seqId?: number|string, isBag?: boolean }[] = []; + for(let { id, count = 1, seqId, isBag } of items) { + let dicGoods = gameData.goods.get(id); + let dicItid = ITID.get(dicGoods.itid); + if(dicItid.table != 'jewel' && dicItid.table != 'artifact') { + let index = result.findIndex(cur => cur.id == id); + if(index == -1) { + result.push({ id, count, seqId, isBag }); + } else { + result[index].count += count; + } + } else { + result.push({ id, count, seqId, isBag }); + } + } + return result; +} + + +export function transPiece(hid: number) { + let dicHero = gameData.hero.get(hid); + let count = gameData.heroTransPiece.get(dicHero.quality); + return { pieceId: dicHero.pieceId, count } +} diff --git a/game-server/app/services/roleService.ts b/game-server/app/services/roleService.ts index 338eccea7..4e23d5668 100644 --- a/game-server/app/services/roleService.ts +++ b/game-server/app/services/roleService.ts @@ -1,413 +1,413 @@ -import { Channel, pinus } from 'pinus'; -import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr, compareVersion } from '../pubUtils/util'; -import { DEFAULT_HEROES, LINEUP_NUM, ROLE_SELECT, TALENT_RELATION_TYPE, TERAPH_RANDOM, SYSTEM_OPEN_ID, GuideUnloadNum, CHECK_HERO_CONSUME, ABI_STAGE, AUTHOR_BOOK_LIMIT_TYPE } from "../consts"; -import { DicTeraph } from '../pubUtils/dictionary/DicTeraph'; -import { Teraph, RoleModel, RoleType, RoleUpdate } from '../db/Role'; -import { SCHOOL } from '../pubUtils/dicParam'; -import { gameData, getEquipByJobClassAndEPlace, getHeroInitTalent, getHeroStarByQuality, getJobByGradeAndClass } from '../pubUtils/data'; -import { SchoolModel } from '../db/School'; -import { SclResultInter, SclPosInter, RewardInter, ItemInter } from '../pubUtils/interface'; -import { Connect, EPlace, HeroModel, HeroSkin, HeroType, HeroUpdate, Talent } from '../db/Hero'; -import { SkinUpdate } from '../db/Skin'; -import { Figure } from '../domain/dbGeneral'; -import { pick } from 'underscore'; -import { Reward } from '../domain/battleField/pvp'; -import { CheckMeterial } from './role/checkMaterial'; -import IP2Region from "ip2region"; -import { getServerCreateTime } from './redisService'; -import { checkWhiteList } from '../pubUtils/sysUtil'; -import { nowSeconds } from '../pubUtils/timeUtil'; -import { ServerlistModel } from '../db/Serverlist'; -import { AuthorBookModel, AuthorBookType } from '../db/AuthorBook'; -const query = new IP2Region({ disableIpv6: true }); - - -export async function getTeraphStrengthenResult(role: RoleType, count: number, dicTeraph: DicTeraph, teraph: Teraph) { - let criAttr: number[] = [], times = 0; - let check = new CheckMeterial(role.roleId, role); - for(let i = 0; i < count; i++) { - let attrs: number[] = []; // 可以强化的属性 - dicTeraph.mainAttrMax.forEach((max, id) => { - if (teraph.attr.get(id) < max) { - attrs.push(id); - } - }); - if(attrs.length <= 0) break; // 如果所有属性都到最高 - let isEnough = await check.decrease(dicTeraph.upMaterial); - - if(!isEnough) break; // 消耗不足 - - // let num = getRandValueByMinMax(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性 - let arr = getRandEelm(attrs, 1); // 随机出的属性id - let critical = getRandValueByMinMax(0, 100);//属性暴击率 - if(teraph.criCount == undefined || teraph.count == undefined) { - teraph.criCount = 0; - teraph.count = 0; - } - let isCritical = critical <= dicTeraph.criRate; // 每10次需要2次保底暴击 - if(!isCritical && Math.floor((teraph.count + 2)/10) * 2 > teraph.criCount) { - isCritical = true; - } else if (isCritical && Math.ceil(teraph.count/10) * 2 <= teraph.criCount) { - isCritical = false; - } - teraph.count ++; - if(isCritical) teraph.criCount ++; - - let criEffect = isCritical?dicTeraph.criEffect: 1; // 暴击效果 - for (let attrId of arr) { - let val = teraph.attr.get(attrId); // 已有的强化值 - val += dicTeraph.mainAttrUp.get(attrId) * criEffect; - let max = dicTeraph.mainAttrMax.get(attrId); - if(val > max) { - val = max; - let attrIndex = attrs.indexOf(attrId); - attrs.splice(attrIndex, 1); - } - teraph.attr.set(attrId, val); - if(isCritical) criAttr.push(attrId); - } - times++; - - } - return { times, consumes: check.getConsume(), criAttr } -} - -export async function getSimpleRoleInfo(roleId: string) { - if (!roleId) return null; - let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.SHOW_SIMPLE, true); - return pick(role, ['roleId', 'roleName', 'head', 'frame', 'spine', 'lv', 'title', 'job', 'quitTime', 'loginTime', 'vLv', 'guildName', 'serverId', 'userInfo']); -} - -export async function getSimpleRoleInfos(roleIds: string[]) { - if (!roleIds || !roleIds.length) return null; - let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.SHOW_SIMPLE, true); - return roles.map(role => pick(role, ['roleId', 'roleName', 'head', 'frame', 'spine', 'lv', 'title', 'job', 'quitTime', 'loginTime', 'vLv', 'guildName', 'serverId', 'userInfo'])); -} - -/** - * 百家学宫 - * @param roleId - */ -export async function getSchoolList(roleId: string) { - - const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id=>isOpen - - const userSchoolList = await SchoolModel.findByRoleId(roleId); - - let school = new Array(); - gameData.school.forEach((dicSchool) => { - let position = new Array(); - dicPosition.forEach((isOpen, dicId) => { - let id = parseInt(dicId); - - let userSchool = userSchoolList.find(cur => cur.schoolId == dicSchool.id && cur.positionId == id); - if (userSchool) { - position.push({ - id, - hid: userSchool.hid, - isOpen: userSchool.isOpen - }); - } else { - position.push({ - id, - hid: 0, - isOpen: !!isOpen - }); - } - }); - - school.push({ - id: dicSchool.id, - position - }); - }); - return school; -} - -function getDefaultHeroInfos(heroes: Map, skins: Map) { - const initInfos: { heroInfo: HeroUpdate, skinInfo: SkinUpdate}[] = []; - for(let hid of DEFAULT_HEROES) { - initInfos.push({ - heroInfo: heroes.get(hid), - skinInfo: skins.get(hid) - }); - } - return initInfos; -} - -export function getDefaultRoleInfo(heroes: Map, skins: Map, role:RoleUpdate, figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }) { - const initInfos = getDefaultHeroInfos(heroes, skins); - return { initInfos, role, figureInfo }; -} - -export function getInitHeroById(hid: number) { - return { - heroInfo: pinus.app.get('initHeroes').get(hid), - skinInfo: pinus.app.get('initSkins').get(hid) - } -} - -export function addConsumeToHero(oldConsume: Reward[] = [], consumes: ItemInter[] = []) { - if(!oldConsume) oldConsume = []; - let consumeMap = new Map(); - for(let { id, count = 1 } of consumes) { - if(!consumeMap.has(id)) { - consumeMap.set(id, count); - } else { - consumeMap.set(id, consumeMap.get(id) + count); - } - - } - let newConsume: Reward[] = []; - for(let {id, count} of oldConsume) { - if(consumeMap.has(id)) { - newConsume.push({ id, count: count + consumeMap.get(id)}); - consumeMap.delete(id); - } else { - newConsume.push({ id, count }); - } - } - for(let [id, count] of consumeMap) { - newConsume.push({ id, count }); - } - return newConsume; -} - -export function addConnect(connections: Connect[], curConnect: Connect) { - let newConnections: Connect[] = []; - let index = -1; - for(let i = 0; i < connections.length; i++) { - if(connections[i].shipId == curConnect.shipId) { - index = i; - newConnections.push(curConnect); - } else { - newConnections.push(connections[i]); - } - } - if(index == -1) { - newConnections.push(curConnect); - } - return newConnections; -} - -export function checkUnlockTalentCondition(hid: number, id: number, talents: Talent[], usedTalentPoint: number) { - let dicHero = gameData.hero.get(hid); - let dicHeroTalent = gameData.heroTalent.get(id); - if(!dicHeroTalent) return false; - - if(dicHero.talentId != dicHeroTalent.talentId) return false; - - // 累计消耗n点天赋点 - if(dicHeroTalent.preTotalPoint > usedTalentPoint) return false; - // 互斥的天赋没有被解锁 - for(let { type, ids } of dicHeroTalent.relation) { - if(type == TALENT_RELATION_TYPE.CONFLICT) { - let hasTalent = talents.find(talent => ids.indexOf(talent.id) != -1); - if(hasTalent) return false; - } - } - // 前置节点 - let orFlag = false; // 只要其中一个满足就可以 - let maxPrecost = 0; // 前置节点最多的消耗 - for(let arr of dicHeroTalent.prepositionId) { - let andFlag = true; // arr内所有节点都需要满足 - for(let id of arr) { - let curTalent = talents.find(cur => cur.id == id); - if(curTalent) { - let dic = gameData.heroTalent.get(id); - if(dic) { - let allCost = 0; - for(let { lv, cost } of dic.level) { - if(curTalent.level >= lv) allCost += cost; - } - if(allCost > maxPrecost) maxPrecost = allCost; - } - } else { - andFlag = false; - } - } - if(andFlag) orFlag = true; - } - if(!orFlag) return false; - // 在前置节点中消耗至少n点天赋点(在有多个前置节点时,取最高的1个) - if(dicHeroTalent.preSinglePoint > maxPrecost) return false; - return true; -} - -export function updateSkinTalent(skins: HeroSkin[], newTalent: Talent, usedTalentPoint: number) { - let newSkins: HeroSkin[] = []; - let newTalents: Talent[] = []; - for(let skin of skins) { - if(skin.enable) { - let hasNewTalent = false; - for(let talent of skin.talent) { - if(talent.id == newTalent.id) { - newTalents.push(newTalent); - hasNewTalent = true; - } else { - newTalents.push(talent); - } - } - if(!hasNewTalent) newTalents.push(newTalent); - newSkins.push({...skin, talent: newTalents, usedTalentPoint }) - } else { - newSkins.push(skin); - } - } - return { newSkins, newTalents }; -} - -export function initSkinTalent(skins: HeroSkin[], isAll = false) { - let newSkins: HeroSkin[] = []; - for(let skin of skins) { - if(isAll || skin.enable) { - newSkins.push({ ...skin, talent: getHeroInitTalent(skin.skinId), usedTalentPoint: 0 }); - } else { - newSkins.push(skin); - } - } - return newSkins -} - -export function checkSystemIsOpen(role: RoleType, id: SYSTEM_OPEN_ID) { - if(!role || !role.hasInit || !role.guide) return false; - - let dicSystemOpenTime = gameData.sysOpenTime.get(id); - if(!dicSystemOpenTime) return false; - - if(dicSystemOpenTime.warId) { - return role.warStar.findIndex(cur => cur.id == dicSystemOpenTime.warId) != -1; - } else { - return role.lv >= dicSystemOpenTime.lv - } -} - -function calSchoolPoint(quality: number, star: number, colorStar: number) { - let _star = colorStar > 0? colorStar: star; - let point = (quality - 1) * 6 + _star; - return point > 0? point: 0; -} - -export async function getSchoolPoint(roleId: string) { - let schools = await SchoolModel.findByRoleId(roleId); - let hids = schools.filter(cur => cur.isOpen && cur.hid > 0).map(school => school.hid); - let heroes = await HeroModel.findByHidRange(hids, roleId); - return heroes.reduce((pre, cur) => { - return pre + calSchoolPoint(cur.quality, cur.star, cur.colorStar); - }, 0); -} - -export async function getIpLocation(ip: string) { - try { - const res = query.search(ip); - console.log('##### setIpLocation', res) - return res.province||res.country||'未知'; - } catch(e) { - console.error('setIpLocation', e) - } -} - -// 玩家是否是新玩家 -export async function checkIsNewUser(version: string, minVersion: string, uid: number, latestServerUniqId: number) { - let versionFlag = compareVersion(version||'0.0.0.0', minVersion||'0.0.0.1'); - if(versionFlag >= 0) { - let hasRole = await RoleModel.checkHasRole(uid, latestServerUniqId); - return !hasRole - } else { - return true; - } -} - -export function calStarUpConsume(hero: HeroType) { - let originConsumes = hero.consumes||[]; - if(CHECK_HERO_CONSUME) { - let dicHero = gameData.hero.get(hero.hid); - let dicJob = gameData.job.get(dicHero?.jobid); - if(dicHero && dicJob) { - let decrease = 0; - for(let star = dicHero.initialStar; star <= hero.star; star++) { - let curDicHeroStar = getHeroStarByQuality(dicJob.job_class, dicHero.quality, star); - if(!curDicHeroStar) continue; - let max = star == hero.star ? hero.starStage: ABI_STAGE.END; - for (let i = 0; i < max; i++) { - decrease += curDicHeroStar.advanceUpFragmentNum; - } - } - for(let quality = dicHero.quality; quality < hero.quality; quality++) { - let curDicHeroQualityUp = gameData.heroQualityUp.get(quality); - if (!curDicHeroQualityUp) continue; - decrease += curDicHeroQualityUp.fragmentNum; - } - - return decreaseConsume(originConsumes, dicHero.pieceId, decrease); - } - } - return { consumes: originConsumes, newConsumes: [] }; -} - -// 从原始消耗里减去消耗 -function decreaseConsume(origin: Reward[], pieceId: number, decrease: number) { - let consumes: Reward[] = [], newConsumes: Reward[] = []; - for(let { id, count } of origin) { - if(id == pieceId) { - consumes.push({ id, count: count - decrease > 0? count - decrease: 0 }); - newConsumes.push({ id, count: decrease }); - } else { - consumes.push({ id, count }); - } - } - return { consumes, newConsumes }; -} - -/** - * 诸子列表是否解锁 - * @param roleId - * @param bookId - * @returns true: 可以解锁 false:不可解锁 - */ -export function checkAuthorBookLimit(authorBooks: AuthorBookType[], bookId: number) { - let dicAuthorsBook = gameData.authorBook.get(bookId); - if(!dicAuthorsBook) return false; - - for(let { type, bookId, value } of dicAuthorsBook.limit) { - if(type == AUTHOR_BOOK_LIMIT_TYPE.ALL) { - let allProgress = authorBooks.reduce((pre, cur) => pre + cur.progress, 0); - if(allProgress < value) return false; - } else if(type == AUTHOR_BOOK_LIMIT_TYPE.ASSIGN) { - let curBook = authorBooks.find(cur => cur.bookId == bookId); - let progress = curBook?.progress??0; - if(progress < value) return false; - } - } - return true; -} - -export function replaceAuthorBooks(authorBooks: AuthorBookType[], authorBook: AuthorBookType) { - let index = authorBooks.findIndex(cur => cur.bookId == authorBook.bookId); - if(index == -1) { - authorBooks.push(authorBook); - } else { - authorBooks[index] = authorBook; - } - return authorBooks; -} - - -export function getHeroNewEplace(hero: HeroType, ePlace: EPlace[]) { - const dicHero = gameData.hero.get(hero.skinId); - let newEplace = []; - for (let eP of ePlace) { - const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, eP.id); - if (!dicEquip) continue; - // const newEquip = new EPlace(eP.id, dicEquip.id); - newEplace.push({ ...eP, equipId: dicEquip.id }); - } - return newEplace; -} - -export function getNewJob(hero: HeroType, job: number) { - const dicHero = gameData.hero.get(hero.skinId); - let dicMyJob = gameData.job.get(job); - let dicNewJob = getJobByGradeAndClass(dicHero.jobClass, dicMyJob.grade); - return dicNewJob?.jobid || 0; -} \ No newline at end of file +import { Channel, pinus } from 'pinus'; +import { getRandValueByMinMax, getRandEelm, decodeIdCntArrayStr, compareVersion } from '@pubUtils/util'; +import { DEFAULT_HEROES, LINEUP_NUM, ROLE_SELECT, TALENT_RELATION_TYPE, TERAPH_RANDOM, SYSTEM_OPEN_ID, GuideUnloadNum, CHECK_HERO_CONSUME, ABI_STAGE, AUTHOR_BOOK_LIMIT_TYPE } from "@consts"; +import { DicTeraph } from '@pubUtils/dictionary/DicTeraph'; +import { Teraph, RoleModel, RoleType, RoleUpdate } from '@db/Role'; +import { SCHOOL } from '@pubUtils/dicParam'; +import { gameData, getEquipByJobClassAndEPlace, getHeroInitTalent, getHeroStarByQuality, getJobByGradeAndClass } from '@pubUtils/data'; +import { SchoolModel } from '@db/School'; +import { SclResultInter, SclPosInter, RewardInter, ItemInter } from '@pubUtils/interface'; +import { Connect, EPlace, HeroModel, HeroSkin, HeroType, HeroUpdate, Talent } from '@db/Hero'; +import { SkinUpdate } from '@db/Skin'; +import { Figure } from '@domain/dbGeneral'; +import { pick } from 'underscore'; +import { Reward } from '@domain/battleField/pvp'; +import { CheckMeterial } from './role/checkMaterial'; +import IP2Region from "ip2region"; +import { getServerCreateTime } from './redisService'; +import { checkWhiteList } from '@pubUtils/sysUtil'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { ServerlistModel } from '@db/Serverlist'; +import { AuthorBookModel, AuthorBookType } from '@db/AuthorBook'; +const query = new IP2Region({ disableIpv6: true }); + + +export async function getTeraphStrengthenResult(role: RoleType, count: number, dicTeraph: DicTeraph, teraph: Teraph) { + let criAttr: number[] = [], times = 0; + let check = new CheckMeterial(role.roleId, role); + for(let i = 0; i < count; i++) { + let attrs: number[] = []; // 可以强化的属性 + dicTeraph.mainAttrMax.forEach((max, id) => { + if (teraph.attr.get(id) < max) { + attrs.push(id); + } + }); + if(attrs.length <= 0) break; // 如果所有属性都到最高 + let isEnough = await check.decrease(dicTeraph.upMaterial); + + if(!isEnough) break; // 消耗不足 + + // let num = getRandValueByMinMax(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性 + let arr = getRandEelm(attrs, 1); // 随机出的属性id + let critical = getRandValueByMinMax(0, 100);//属性暴击率 + if(teraph.criCount == undefined || teraph.count == undefined) { + teraph.criCount = 0; + teraph.count = 0; + } + let isCritical = critical <= dicTeraph.criRate; // 每10次需要2次保底暴击 + if(!isCritical && Math.floor((teraph.count + 2)/10) * 2 > teraph.criCount) { + isCritical = true; + } else if (isCritical && Math.ceil(teraph.count/10) * 2 <= teraph.criCount) { + isCritical = false; + } + teraph.count ++; + if(isCritical) teraph.criCount ++; + + let criEffect = isCritical?dicTeraph.criEffect: 1; // 暴击效果 + for (let attrId of arr) { + let val = teraph.attr.get(attrId); // 已有的强化值 + val += dicTeraph.mainAttrUp.get(attrId) * criEffect; + let max = dicTeraph.mainAttrMax.get(attrId); + if(val > max) { + val = max; + let attrIndex = attrs.indexOf(attrId); + attrs.splice(attrIndex, 1); + } + teraph.attr.set(attrId, val); + if(isCritical) criAttr.push(attrId); + } + times++; + + } + return { times, consumes: check.getConsume(), criAttr } +} + +export async function getSimpleRoleInfo(roleId: string) { + if (!roleId) return null; + let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.SHOW_SIMPLE, true); + return pick(role, ['roleId', 'roleName', 'head', 'frame', 'spine', 'lv', 'title', 'job', 'quitTime', 'loginTime', 'vLv', 'guildName', 'serverId', 'userInfo']); +} + +export async function getSimpleRoleInfos(roleIds: string[]) { + if (!roleIds || !roleIds.length) return null; + let roles = await RoleModel.findByRoleIds(roleIds, ROLE_SELECT.SHOW_SIMPLE, true); + return roles.map(role => pick(role, ['roleId', 'roleName', 'head', 'frame', 'spine', 'lv', 'title', 'job', 'quitTime', 'loginTime', 'vLv', 'guildName', 'serverId', 'userInfo'])); +} + +/** + * 百家学宫 + * @param roleId + */ +export async function getSchoolList(roleId: string) { + + const dicPosition = decodeIdCntArrayStr(SCHOOL.SCHOOL_POSITION, 1); // id=>isOpen + + const userSchoolList = await SchoolModel.findByRoleId(roleId); + + let school = new Array(); + gameData.school.forEach((dicSchool) => { + let position = new Array(); + dicPosition.forEach((isOpen, dicId) => { + let id = parseInt(dicId); + + let userSchool = userSchoolList.find(cur => cur.schoolId == dicSchool.id && cur.positionId == id); + if (userSchool) { + position.push({ + id, + hid: userSchool.hid, + isOpen: userSchool.isOpen + }); + } else { + position.push({ + id, + hid: 0, + isOpen: !!isOpen + }); + } + }); + + school.push({ + id: dicSchool.id, + position + }); + }); + return school; +} + +function getDefaultHeroInfos(heroes: Map, skins: Map) { + const initInfos: { heroInfo: HeroUpdate, skinInfo: SkinUpdate}[] = []; + for(let hid of DEFAULT_HEROES) { + initInfos.push({ + heroInfo: heroes.get(hid), + skinInfo: skins.get(hid) + }); + } + return initInfos; +} + +export function getDefaultRoleInfo(heroes: Map, skins: Map, role:RoleUpdate, figureInfo: { heads: Figure[], frames: Figure[], spines: Figure[] }) { + const initInfos = getDefaultHeroInfos(heroes, skins); + return { initInfos, role, figureInfo }; +} + +export function getInitHeroById(hid: number) { + return { + heroInfo: pinus.app.get('initHeroes').get(hid), + skinInfo: pinus.app.get('initSkins').get(hid) + } +} + +export function addConsumeToHero(oldConsume: Reward[] = [], consumes: ItemInter[] = []) { + if(!oldConsume) oldConsume = []; + let consumeMap = new Map(); + for(let { id, count = 1 } of consumes) { + if(!consumeMap.has(id)) { + consumeMap.set(id, count); + } else { + consumeMap.set(id, consumeMap.get(id) + count); + } + + } + let newConsume: Reward[] = []; + for(let {id, count} of oldConsume) { + if(consumeMap.has(id)) { + newConsume.push({ id, count: count + consumeMap.get(id)}); + consumeMap.delete(id); + } else { + newConsume.push({ id, count }); + } + } + for(let [id, count] of consumeMap) { + newConsume.push({ id, count }); + } + return newConsume; +} + +export function addConnect(connections: Connect[], curConnect: Connect) { + let newConnections: Connect[] = []; + let index = -1; + for(let i = 0; i < connections.length; i++) { + if(connections[i].shipId == curConnect.shipId) { + index = i; + newConnections.push(curConnect); + } else { + newConnections.push(connections[i]); + } + } + if(index == -1) { + newConnections.push(curConnect); + } + return newConnections; +} + +export function checkUnlockTalentCondition(hid: number, id: number, talents: Talent[], usedTalentPoint: number) { + let dicHero = gameData.hero.get(hid); + let dicHeroTalent = gameData.heroTalent.get(id); + if(!dicHeroTalent) return false; + + if(dicHero.talentId != dicHeroTalent.talentId) return false; + + // 累计消耗n点天赋点 + if(dicHeroTalent.preTotalPoint > usedTalentPoint) return false; + // 互斥的天赋没有被解锁 + for(let { type, ids } of dicHeroTalent.relation) { + if(type == TALENT_RELATION_TYPE.CONFLICT) { + let hasTalent = talents.find(talent => ids.indexOf(talent.id) != -1); + if(hasTalent) return false; + } + } + // 前置节点 + let orFlag = false; // 只要其中一个满足就可以 + let maxPrecost = 0; // 前置节点最多的消耗 + for(let arr of dicHeroTalent.prepositionId) { + let andFlag = true; // arr内所有节点都需要满足 + for(let id of arr) { + let curTalent = talents.find(cur => cur.id == id); + if(curTalent) { + let dic = gameData.heroTalent.get(id); + if(dic) { + let allCost = 0; + for(let { lv, cost } of dic.level) { + if(curTalent.level >= lv) allCost += cost; + } + if(allCost > maxPrecost) maxPrecost = allCost; + } + } else { + andFlag = false; + } + } + if(andFlag) orFlag = true; + } + if(!orFlag) return false; + // 在前置节点中消耗至少n点天赋点(在有多个前置节点时,取最高的1个) + if(dicHeroTalent.preSinglePoint > maxPrecost) return false; + return true; +} + +export function updateSkinTalent(skins: HeroSkin[], newTalent: Talent, usedTalentPoint: number) { + let newSkins: HeroSkin[] = []; + let newTalents: Talent[] = []; + for(let skin of skins) { + if(skin.enable) { + let hasNewTalent = false; + for(let talent of skin.talent) { + if(talent.id == newTalent.id) { + newTalents.push(newTalent); + hasNewTalent = true; + } else { + newTalents.push(talent); + } + } + if(!hasNewTalent) newTalents.push(newTalent); + newSkins.push({...skin, talent: newTalents, usedTalentPoint }) + } else { + newSkins.push(skin); + } + } + return { newSkins, newTalents }; +} + +export function initSkinTalent(skins: HeroSkin[], isAll = false) { + let newSkins: HeroSkin[] = []; + for(let skin of skins) { + if(isAll || skin.enable) { + newSkins.push({ ...skin, talent: getHeroInitTalent(skin.skinId), usedTalentPoint: 0 }); + } else { + newSkins.push(skin); + } + } + return newSkins +} + +export function checkSystemIsOpen(role: RoleType, id: SYSTEM_OPEN_ID) { + if(!role || !role.hasInit || !role.guide) return false; + + let dicSystemOpenTime = gameData.sysOpenTime.get(id); + if(!dicSystemOpenTime) return false; + + if(dicSystemOpenTime.warId) { + return role.warStar.findIndex(cur => cur.id == dicSystemOpenTime.warId) != -1; + } else { + return role.lv >= dicSystemOpenTime.lv + } +} + +function calSchoolPoint(quality: number, star: number, colorStar: number) { + let _star = colorStar > 0? colorStar: star; + let point = (quality - 1) * 6 + _star; + return point > 0? point: 0; +} + +export async function getSchoolPoint(roleId: string) { + let schools = await SchoolModel.findByRoleId(roleId); + let hids = schools.filter(cur => cur.isOpen && cur.hid > 0).map(school => school.hid); + let heroes = await HeroModel.findByHidRange(hids, roleId); + return heroes.reduce((pre, cur) => { + return pre + calSchoolPoint(cur.quality, cur.star, cur.colorStar); + }, 0); +} + +export async function getIpLocation(ip: string) { + try { + const res = query.search(ip); + console.log('##### setIpLocation', res) + return res.province||res.country||'未知'; + } catch(e) { + console.error('setIpLocation', e) + } +} + +// 玩家是否是新玩家 +export async function checkIsNewUser(version: string, minVersion: string, uid: number, latestServerUniqId: number) { + let versionFlag = compareVersion(version||'0.0.0.0', minVersion||'0.0.0.1'); + if(versionFlag >= 0) { + let hasRole = await RoleModel.checkHasRole(uid, latestServerUniqId); + return !hasRole + } else { + return true; + } +} + +export function calStarUpConsume(hero: HeroType) { + let originConsumes = hero.consumes||[]; + if(CHECK_HERO_CONSUME) { + let dicHero = gameData.hero.get(hero.hid); + let dicJob = gameData.job.get(dicHero?.jobid); + if(dicHero && dicJob) { + let decrease = 0; + for(let star = dicHero.initialStar; star <= hero.star; star++) { + let curDicHeroStar = getHeroStarByQuality(dicJob.job_class, dicHero.quality, star); + if(!curDicHeroStar) continue; + let max = star == hero.star ? hero.starStage: ABI_STAGE.END; + for (let i = 0; i < max; i++) { + decrease += curDicHeroStar.advanceUpFragmentNum; + } + } + for(let quality = dicHero.quality; quality < hero.quality; quality++) { + let curDicHeroQualityUp = gameData.heroQualityUp.get(quality); + if (!curDicHeroQualityUp) continue; + decrease += curDicHeroQualityUp.fragmentNum; + } + + return decreaseConsume(originConsumes, dicHero.pieceId, decrease); + } + } + return { consumes: originConsumes, newConsumes: [] }; +} + +// 从原始消耗里减去消耗 +function decreaseConsume(origin: Reward[], pieceId: number, decrease: number) { + let consumes: Reward[] = [], newConsumes: Reward[] = []; + for(let { id, count } of origin) { + if(id == pieceId) { + consumes.push({ id, count: count - decrease > 0? count - decrease: 0 }); + newConsumes.push({ id, count: decrease }); + } else { + consumes.push({ id, count }); + } + } + return { consumes, newConsumes }; +} + +/** + * 诸子列表是否解锁 + * @param roleId + * @param bookId + * @returns true: 可以解锁 false:不可解锁 + */ +export function checkAuthorBookLimit(authorBooks: AuthorBookType[], bookId: number) { + let dicAuthorsBook = gameData.authorBook.get(bookId); + if(!dicAuthorsBook) return false; + + for(let { type, bookId, value } of dicAuthorsBook.limit) { + if(type == AUTHOR_BOOK_LIMIT_TYPE.ALL) { + let allProgress = authorBooks.reduce((pre, cur) => pre + cur.progress, 0); + if(allProgress < value) return false; + } else if(type == AUTHOR_BOOK_LIMIT_TYPE.ASSIGN) { + let curBook = authorBooks.find(cur => cur.bookId == bookId); + let progress = curBook?.progress??0; + if(progress < value) return false; + } + } + return true; +} + +export function replaceAuthorBooks(authorBooks: AuthorBookType[], authorBook: AuthorBookType) { + let index = authorBooks.findIndex(cur => cur.bookId == authorBook.bookId); + if(index == -1) { + authorBooks.push(authorBook); + } else { + authorBooks[index] = authorBook; + } + return authorBooks; +} + + +export function getHeroNewEplace(hero: HeroType, ePlace: EPlace[]) { + const dicHero = gameData.hero.get(hero.skinId); + let newEplace = []; + for (let eP of ePlace) { + const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, eP.id); + if (!dicEquip) continue; + // const newEquip = new EPlace(eP.id, dicEquip.id); + newEplace.push({ ...eP, equipId: dicEquip.id }); + } + return newEplace; +} + +export function getNewJob(hero: HeroType, job: number) { + const dicHero = gameData.hero.get(hero.skinId); + let dicMyJob = gameData.job.get(job); + let dicNewJob = getJobByGradeAndClass(dicHero.jobClass, dicMyJob.grade); + return dicNewJob?.jobid || 0; +} diff --git a/game-server/app/services/sdk/ta.ts b/game-server/app/services/sdk/ta.ts index 95a90e0ba..dfd772462 100644 --- a/game-server/app/services/sdk/ta.ts +++ b/game-server/app/services/sdk/ta.ts @@ -1,396 +1,327 @@ -/** - * 模仿thinkingdata-node直接写一个log的写入,而日志直接用pinus-logger实现 - */ -import { taLogger } from "../../util/logger"; - -const KEY_NAME_MATCH_REGEX = /^[a-zA-Z#][a-zA-Z0-9_]+$/; - -let util: any = {}; -util.version = '1.2.2'; -util.log = function(message: string) { - console.log(message); -} -util.each = function (obj, iterator, context) { - if (obj === null) { - return; - } - if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) { - obj.forEach(iterator, context); - } else if (obj.length === +obj.length) { - for (let i = 0, l = obj.length; i < l; i++) { - if (i in obj && iterator.call(context, obj[i], i, obj) === {}) { - return; - } - } - } else { - for (let key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - if (iterator.call(context, obj[key], key, obj) === {}) { - return; - } - } - } - } -}; -util.formatDate = function (d) { - function pad(n) { - return n < 10 ? '0' + n : n; - } - - function padMilliseconds(n) { - if (n < 10) { - return '00' + n; - } else if (n < 100) { - return '0' + n; - } else { - return n; - } - } - return d.getFullYear() + '-' + - pad(d.getMonth() + 1) + '-' + - pad(d.getDate()) + ' ' + - pad(d.getHours()) + ':' + - pad(d.getMinutes()) + ':' + - pad(d.getSeconds()) + '.' + - padMilliseconds(d.getMilliseconds()); -}; - -util.searchObjDate = function (o) { - if (util.check.isObject(o) || util.check.isArray(o)) { - util.each(o, function (a, b) { - if (util.check.isObject(a) || util.check.isArray(a)) { - util.searchObjDate(o[b]); - } else { - if (util.check.isDate(a)) { - o[b] = util.formatDate(a); - } - } - }); - } -}; - -util.check = { - isUndefined: function (obj) { - return obj === void 0; - }, - - isObject: function (obj) { - return (toString.call(obj) === '[object Object]') && (obj !== null); - }, - - isEmptyObject: function (obj) { - if (util.check.isObject(obj)) { - for (let key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - return false; - } - } - return true; - } - return false; - }, - - isArray: function (obj) { - return toString.call(obj) === '[object Array]'; - }, - - isString: function (obj) { - return toString.call(obj) === '[object String]'; - }, - - isDate: function (obj) { - return toString.call(obj) === '[object Date]'; - }, - - isNumber: function (obj) { - return toString.call(obj) === '[object Number]'; - }, - - isBoolean: function (obj) { - return toString.call(obj) === '[object Boolean]'; - }, - - isJSONString: function (str) { - try { - JSON.parse(str); - } catch (e) { - return false; - } - return true; - } -}; - -util.properties = { - _strip: function (prop) { - if (!util.check.isObject(prop)) { - return prop; - } - util.each(prop, function (v, k) { - if (!(util.check.isString(v) || util.check.isNumber(v) || util.check.isDate(v) || util.check.isBoolean(v) || util.check.isArray(v))) { - util.log('您的数据-', k, v, '-格式不满足要求,我们已经将其删除. 属性值只支持 String, Number, Date, Boolean, Array'); - delete prop[k]; - } - }); - return prop; - }, - - _checkPropertiesKey: function (obj) { - let flag = true; - util.each(obj, (v, k) => { - if (!KEY_NAME_MATCH_REGEX.test(k)) { - util.log('不合法的 KEY 值: ' + k); - flag = false; - } - }); - return flag; - }, - - name: function (s) { - if (!util.check.isString(s) || !KEY_NAME_MATCH_REGEX.test(s)) { - util.log('请检查参数格式, 事件或属性名称必须是英文字母、 \'util\'或\'#\' 开头, 包含字母和数字的字符串: ' + s); - return false; - } else { - return true; - } - }, - - properties: function (p) { - this._strip(p); - if (p) { - if (util.check.isObject(p)) { - if (this._checkPropertiesKey(p)) { - return true; - } else { - util.log('请检查参数格式, properties 的 key 只能以字母或\'#\'开头,包含数字、字母和下划线 util'); - return false; - } - } else { - util.log('properties 可以没有,但有的话必须是对象'); - return false; - } - } else { - return true; - } - }, - - propertiesMust: function (p) { - this._strip(p); - if (p === undefined || !util.check.isObject(p) || util.check.isEmptyObject(p)) { - util.log('properties 必须是对象且有值'); - return false; - } else { - if (this._checkPropertiesKey(p)) { - return true; - } else { - util.log('请检查参数格式, properties 的 key 只能以字母或\'#\'开头,包含数字、字母和下划线 util'); - return false; - } - } - }, - - userId: function (id) { - if (util.check.isString(id) && /^.+$/.test(id)) { - return true; - } else { - util.log('用户 id 必须是不能为空'); - return false; - } - } -} - - -const DEFAULT_PROPERTIES = { - "#lib": "node", - "#lib_version": util.version, -}; - -/** - * 内部函数,创建 ta 实例 - */ -let _createClient = function (consumer) { - let ta: any = {}; - ta.consumer = consumer; - ta.superProperties = {}; - - ta._basicCheck = function (params) { - if (!util.check.isObject(params)) { - return new Error("params for track must be an object"); - } - - if (!util.properties.userId(params.accountId) && !util.properties.userId(params.distinctId)) { - return new Error("account ID and distinct ID cannot be empty at the same time"); - } - - return undefined; - }; - - ta.track = function (params, skipLocalCheck = false) { - let callback = params.callback || function () { - }; - if (!ta._trackCheck(params, skipLocalCheck, callback)) { - return; - } - ta._sendRequest("track", params, callback); - }; - - ta._trackCheck = function (params, skipLocalCheck, callback) { - let err = this._basicCheck(params); - if (err) { - callback(err); - return false; - } - if (!util.properties.name(params.event)) { - callback(new Error("invalid event name")); - return false; - } - if (!skipLocalCheck && !util.properties.properties(params.properties)) { - callback(new Error("invalid properties")); - return false; - } - return true; - }; - - ta.userSet = function (params) { - let callback = params.callback || function () { - }; - - let err = this._basicCheck(params); - if (err) { - callback(err); - return; - } - - if (!util.properties.propertiesMust(params.properties)) { - callback(new Error("invalid properties")); - return; - } - - ta._sendRequest("user_set", params, callback); - }; - - ta.userSetOnce = function (params) { - let callback = params.callback || function () { - }; - - let err = this._basicCheck(params); - if (err) { - callback(err); - return; - } - - if (!util.properties.propertiesMust(params.properties)) { - callback(new Error("invalid properties")); - return; - } - - ta._sendRequest("user_setOnce", params, callback); - }; - - ta.userAdd = function (params) { - let callback = params.callback || function () { - }; - - let err = this._basicCheck(params); - if (err) { - callback(err); - return; - } - - if (!util.properties.propertiesMust(params.properties)) { - callback(new Error("invalid properties")); - return; - } - - ta._sendRequest("user_add", params, callback); - }; - - ta.setDynamicSuperProperties = function (getDynamicProperties, callback) { - let err; - if (typeof getDynamicProperties === "function") { - if (util.properties.properties(getDynamicProperties())) { - ta.getDynamicProperties = getDynamicProperties; - } else { - err = new Error("Invalid return type of getDynamicProperties"); - } - } else { - err = new Error("getDynamicProperties must be a funciton"); - } - - if (callback && err) { - callback(err); - } - }; - - // 内部函数,组织数据格式,并发送给对应的 consumer 去处理 - ta._sendRequest = function (type, eventData, callback) { - let time = util.check.isUndefined(eventData.time) || !util.check.isDate(eventData.time) - ? new Date() - : eventData.time; - - let data = { - "#type": type, - "#time": util.formatDate(time), - }; - - if (eventData.distinctId) { - data["#distinct_id"] = eventData.distinctId; - } - - if (eventData.accountId) { - data["#account_id"] = eventData.accountId; - } - - if (eventData.ip) { - data["#ip"] = eventData.ip; - } - - if (eventData.event) { - data["#event_name"] = eventData.event; - } - - if (eventData.eventId) { - data["#event_id"] = eventData.eventId; - } - - if (eventData.firstCheckId) { - data["#first_check_id"] = eventData.firstCheckId; - } - - if (eventData.uuid) { - data["#uuid"] = eventData.uuid; - } - - if (eventData.appId) { - data["#app_id"] = eventData.appId; - } - - if (type === "track" || - type === "track_update" || - type === "track_overwrite") { - data["properties"] = { ...DEFAULT_PROPERTIES, ...ta.superProperties, ...(ta.getDynamicProperties ? ta.getDynamicProperties() : {}) }; - } else { - data["properties"] = {}; - } - - if ( - util.check.isObject(eventData.properties) && - !util.check.isEmptyObject(eventData.properties) - ) { - data['properties'] = { ...data['properties'], ...eventData.properties || {} } - } - - util.searchObjDate(data); - - this.consumer.add(data, callback); - }; - - return ta; -}; - -export function initTaLoggingMode() { - return _createClient({ - add: (msg: string) => { - taLogger.info(JSON.stringify(msg)); - } - }) -} \ No newline at end of file +/** + * 模仿thinkingdata-node直接写一个log的写入,而日志直接用pinus-logger实现 + */ +import { taLogger } from "../../util/logger"; + +const KEY_NAME_MATCH_REGEX = /^[a-zA-Z#][a-zA-Z0-9_]+$/; + +let util: any = {}; +util.version = '1.2.2'; +util.log = function(message: string) { + console.log(message); +} +util.each = function (obj, iterator, context) { + if (obj === null) { + return; + } + if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (let i = 0, l = obj.length; i < l; i++) { + // @ts-ignore + if (i in obj && iterator.call(context, obj[i], i, obj)) { + return; + } + } + } else { + for (let key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + // @ts-ignore + if (iterator.call(context, obj[key], key, obj)) { + return; + } + } + } + } +}; +util.formatDate = function (d) { + function pad(n) { + return n < 10 ? '0' + n : n; + } + + function padMilliseconds(n) { + if (n < 10) { + return '00' + n; + } else if (n < 100) { + return '0' + n; + } else { + return n; + } + } + return d.getFullYear() + '-' + + pad(d.getMonth() + 1) + '-' + + pad(d.getDate()) + ' ' + + pad(d.getHours()) + ':' + + pad(d.getMinutes()) + ':' + + pad(d.getSeconds()) + '.' + + padMilliseconds(d.getMilliseconds()); +}; + +util.formatString = function (format) { + const args = Array.prototype.slice.call(arguments, 1); + return format.replace(/{(\d+)}/g, function (match, number) { + return typeof args[number] !== 'undefined' + ? args[number] + : match + ; + }); +}; +util.isArray = Array.isArray; +util.isObject = function (obj) { + return obj === Object(obj) && !util.isArray(obj) && typeof obj === 'object'; +}; +util.encodeURIComponent = function (str) { + return encodeURIComponent(str); +} +util.trim = function (str) { + return str.replace(/^\s+|\s+$/g, ''); +} +util.toArray = function (iterable) { + if (!iterable) { + return []; + } + if (iterable.toArray) { + return iterable.toArray(); + } + return [].slice.call(iterable); +} +util.each(['Function', 'String', 'Object', 'Number', 'Boolean', 'Date', 'RegExp', 'Error'], function (name) { + util['is' + name] = function (obj) { + return Object.prototype.toString.call(obj) === '[object ' + name + ']'; + }; +}); +util.getProperty = function (obj, key) { + return obj == null ? undefined : obj[key]; +}; +util.setProperty = function (obj, key, value) { + obj[key] = value; +}; +util.hasProperty = function (obj, key) { + return obj != null && typeof obj === 'object' && key in obj; +}; +util.createLog = function (category) { + const log = function () { + }; + log.debug = function () { + }; + log.info = function () { + }; + log.warn = function () { + }; + log.error = function () { + }; + return log; +}; +const TABLE_NAME = "app_gold_record"; + +const EXTRA_CODE = { + "#": "_j_", + "ing": "_deng_", + "&": "_he_", +}; + +function encodeKey(key) { + let result = ""; + for (let i = 0; i < key.length; i++) { + const c = key.charAt(i); + result += EXTRA_CODE[c] || c; + } + return result; +} + +function decodeKey(key) { + let result = ""; + let i = 0; + while (i < key.length) { + const c = key.charAt(i); + if (c === '_' && i + 2 < key.length) { + const nextTwo = key.substring(i + 1, i + 3); + let found = false; + for (const [encoded, decoded] of Object.entries(EXTRA_CODE)) { + if (nextTwo === encoded.substring(1)) { + result += decoded; + i += 3; + found = true; + break; + } + } + if (!found) { + result += c; + i++; + } + } else { + result += c; + i++; + } + } + return result; +} + +function encode(data) { + const str = JSON.stringify(data); + return new Buffer(str).toString("base64"); +} + +function decode(str) { + return JSON.parse(new Buffer(str, "base64").toString()); +} + +function encodeId(id) { + return encodeKey(encode({ + "appid": 1, + "id": id, + })); +} + +function decodeId(id) { + const decoded = decode(decodeKey(id)); + return decoded["id"]; +} + +function encodeData(data) { + return encode({ + "data": data, + "time": Date.now(), + }); +} + +function decodeData(data) { + const decoded = decode(data); + return decoded["data"]; +} + +let instance = null; + +export class TA { + private appId: string; + private worker: any; + private receiver: any; + + constructor(appId: string, token: string) { + this.appId = appId; + this.worker = null; + this.receiver = null; + } + + userSet(userId: string, properties: any) { + const data = { + "#type": "user_set", + "#time": util.formatDate(new Date()), + "#account_id": userId, + }; + util.each(properties, function (val, key) { + data[key] = val; + }); + this.upload(data); + } + + userSetOnce(userId: string, properties: any) { + const data = { + "#type": "user_setOnce", + "#time": util.formatDate(new Date()), + "#account_id": userId, + }; + util.each(properties, function (val, key) { + data[key] = val; + }); + this.upload(data); + } + + userAdd(userId: string, properties: any) { + const data = { + "#type": "user_add", + "#time": util.formatDate(new Date()), + "#account_id": userId, + }; + util.each(properties, function (val, key) { + data[key] = val; + }); + this.upload(data); + } + + userUnset(userId: string, keys: string[]) { + const data: any = { + "#type": "user_unset", + "#time": util.formatDate(new Date()), + "#account_id": userId, + }; + for (let i = 0; i < keys.length; i++) { + data[keys[i]] = 0; + } + this.upload(data); + } + + userDelete(userId: string) { + const data = { + "#type": "user_del", + "#time": util.formatDate(new Date()), + "#account_id": userId, + }; + this.upload(data); + } + + track(userId: string, eventName: string, properties: any) { + const data = { + "#type": "track", + "#time": util.formatDate(new Date()), + "#account_id": userId, + "#event_name": eventName, + }; + util.each(properties, function (val, key) { + if (!KEY_NAME_MATCH_REGEX.test(key)) { + return; + } + data[key] = val; + }); + this.upload(data); + } + + upload(data) { + if (!instance) { + taLogger.info("ta data:", JSON.stringify(data)); + } else { + taLogger.info("ta data:", JSON.stringify(data)); + } + } +} + +let ta: TA = null; +let initCount = 0; + +export function initTa(appId: string, token: string) { + initCount++; + if (ta == null || initCount <= 1) { + ta = new TA(appId, token); + } + return ta; +} + +export function getTa() { + if (!ta) { + console.error("ta未初始化"); + return null; + } + return ta; +} + +export function reportTAEvent(uid: string, event: string, data: any) { + const ta = getTa(); + if (ta) { + ta.track(uid, event, data); + } +} + +export function reportTAUserSet(uid: string, data: any) { + const ta = getTa(); + if (ta) { + ta.userSet(uid, data); + } +} + +export function initTaLoggingMode(isInit: boolean) { + if (isInit) { + if (!instance) { + instance = new TA("AABBCC", ""); + } + } +} diff --git a/game-server/app/services/sdkService.ts b/game-server/app/services/sdkService.ts index 858022363..ba7fc75c4 100644 --- a/game-server/app/services/sdkService.ts +++ b/game-server/app/services/sdkService.ts @@ -1,343 +1,343 @@ -/********** 37sdk **********/ - -import { RoleModel, RoleType } from "../db/Role"; -import { Chat37Params, CheckGuild37Params, CheckName37Params, GetWordParam, PostGuild37Params, PostName37Params, PushMsg37Param } from "../domain/sdk"; -import { sendMailByContent, sendMailToGuildByContent } from './mailService'; -import { NAMEPLATE } from '../pubUtils/dicParam'; -import { CHANNEL_PREFIX, FILENAME, getSdkChannelId, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, SDK_37_ADDR, SDK_37_CONST, SDK_PUSH_TARGET_TYPE, SDK_TA_CONST, STATUS, TA_EVENT, TA_USERSET_TYPE, THINKING_DATA_MODE, THINKING_DATA_MODE_LIST } from "../consts"; -import { UserModel } from "../db/User"; -import { request37CheckChat, request37GetWord, request37Post, request37PushMessage } from "../pubUtils/httpUtil"; -import { GuildModel } from "../db/Guild"; -import { getRoleOnlineInfo, updateUserInfo } from "./redisService"; -import { Application, pinus } from "pinus"; -import { getRandSingleEelm, parseGoodStr, readWordTxt, resResult, writeWordTxt } from "../pubUtils/util"; -const ThinkingAnalytics = require("thinkingdata-node"); -import Trie from '../pubUtils/trie'; -import _ = require("underscore"); -import { getGoldObject } from "./role/rewardService"; -import { SurveyRecModel } from "../db/SurveyRec"; -import { SurveyModel } from "../db/Survery"; -import { pushGuildInfoUpdate } from "./guildService"; -import { sendMessageToUserWithSuc } from "./pushService"; -import { GuildLeader } from "../domain/rank"; -import { initTaLoggingMode } from "./sdk/ta"; -import { DicPushMessage } from "../pubUtils/dictionary/DicPushMessage"; -import { GiftCodeModel } from "../db/GiftCode"; -import { GiftCodeDetailModel } from "../db/GiftCodeDetail"; - -// 检查私聊是否合法 - -export async function checkPrivateChat(roleId: string, targetRoleId: string, message: string) { - let body = new Chat37Params(message, getSdkChannelId('private')); - let myRole = await RoleModel.findByRoleId(roleId); - let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); - if(myUser.channelInfo) { - body.setByMyRole(myRole, myUser); - let targetRole = await RoleModel.findByRoleId(targetRoleId); - let targetUser = await UserModel.findUserByUid(targetRole.userInfo.uid); - body.setByTargetRole(targetRole, targetUser); - return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); - } - return true; -} - -export async function checkGuildChat(roleId: string, guildCode: string, message: string) { - let body = new Chat37Params(message, getSdkChannelId(CHANNEL_PREFIX.GUILD)); - let myRole = await RoleModel.findByRoleId(roleId); - let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); - if(myUser.channelInfo) { - body.setByMyRole(myRole, myUser); - body.setByGuild(guildCode); - return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); - } - return true; -} - -export async function checkOtherChat(roleId: string, channelPrefix: string, message: string) { - let body = new Chat37Params(message, getSdkChannelId(channelPrefix)); - let myRole = await RoleModel.findByRoleId(roleId); - let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); - if(!!myUser.channelInfo) { - body.setByMyRole(myRole, myUser); - return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); - } - return true; -} - -export async function checkRoleName(roleId: string, roleName: string, myRole?: RoleType) { - if(!myRole) { - myRole = await RoleModel.findByRoleId(roleId); - } - let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); - if(!!myUser.channelInfo) { - let body = new CheckName37Params(myRole, roleName, myUser); - let result = await request37Post(SDK_37_ADDR.CHECK_NAME, body, SDK_37_CONST.CHAT_KEY); - if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 - return await checkFilterWords(roleName); - } else if (result == 0) { - return false; - } - request37Post(SDK_37_ADDR.POST_NAME, new PostName37Params(myRole, roleName, myUser), SDK_37_CONST.CHAT_KEY); - } - return true; -} - -export async function checkGuildName(guildCode: string, serverId: number, name: string, notice: string) { - let nameResult = true, noticeResult = true; - if(name != undefined) { - let body = new CheckGuild37Params(guildCode, serverId, 1, name); - let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY); - if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 - nameResult = await checkFilterWords(name); - } else if (result == 0) { - nameResult = false; - } - if(nameResult) request37Post(SDK_37_ADDR.POST_UNION, new PostGuild37Params(guildCode, serverId, 1, name), SDK_37_CONST.CHAT_KEY); - } - if(notice != undefined) { - if(notice == '') notice = ' '; - let body = new CheckGuild37Params(guildCode, serverId, 2, notice); - let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY); - if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 - noticeResult = await checkFilterWords(name); - } else if (result == 0) { - noticeResult = false; - } - if(noticeResult) request37Post(SDK_37_ADDR.POST_UNION, new PostGuild37Params(guildCode, serverId, 2, notice), SDK_37_CONST.CHAT_KEY); - } - return nameResult && noticeResult -} - - -// 根据37sdk处理违规玩家名 -export async function treatRoleName(roleId: string, isDebug?: boolean) { - let role = await RoleModel.findByRoleId(roleId); - if((role && role.sdkMark) || isDebug) { // 有设置标记的情况下 - let newName = "默认玩家名"; - // 新名字上传 - await checkRoleName(roleId, newName, role); - // 改名字 - await RoleModel.updateRoleInfo(roleId, { roleName: newName, sdkMark: false }); - // 通知处理 - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'roleName', value: newName }]); // redis缓存 - if(role.isGuildLeader) { - await updateUserInfo(REDIS_KEY.GUILD_INFO, role.guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); - } - const { sid } = await getRoleOnlineInfo(roleId); - if(!!sid) { - await pinus.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, roleName: newName }]); // 改session - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { roleName: newName }, sid); - } - // 补偿 - let gold = getGoldObject(NAMEPLATE.NAMEPLATE_FEECOST) - await sendMailByContent(MAIL_TYPE.TREAT_ROLE_NAME, role.roleId, { goods: [gold] }); - } -} - -// 根据37sdk处理违规军团数据 -export async function treatGuildName(content: string) { - let params: { code: string, serverId: number, type: number }; - try { - params = JSON.parse(content); - } catch(e) { - return false; - } - - let guild = await GuildModel.findByCode(params.code, params.serverId, '+members'); - if(guild && guild.sdkMark) { // 有设置标记的情况下 - if(params.type == 1) { // 公会名 - let newName = "默认公会名"; - // 新名字上传 - await checkGuildName(params.code, params.serverId, newName, undefined); - await GuildModel.updateInfo(params.code, { name: newName, sdkMark: false }); - // 通知处理 - await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件 - await pushGuildInfoUpdate(params.code, { name: newName }); - await updateUserInfo(REDIS_KEY.GUILD_INFO, params.code, [{ field: 'name', value: newName }]); // redis缓存信息 - for(let roleId of guild.members) { - await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: newName }]); - } - await RoleModel.updateGuildName(params.code, newName); - - } else if (params.type == 2) { // 公会公告 - await checkGuildName(params.code, params.serverId, undefined, ' '); - await GuildModel.updateInfo(params.code, { notice: ' ', sdkMark: false }); - // 通知处理 - await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件 - await pushGuildInfoUpdate(params.code, { notice: '' }); - } - } -} - -// 37接口 消息推送 -export async function pushMsg37(code: string, dic: DicPushMessage, target: SDK_PUSH_TARGET_TYPE, audience: string) { - let body = new PushMsg37Param(code); - body.setMsgInfo(dic, target, audience); - return await request37PushMessage(SDK_37_ADDR.PUSH_MSG, body, SDK_37_CONST.PUSH_KEY); -} - -export function connectThinkingData(app: Application) { - let ta; - if(app.get('env') != 'development') { - if(THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.DEBUG) { - ta = ThinkingAnalytics.initWithDebugMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); - } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.BATCH) { - ta = ThinkingAnalytics.initWithBatchMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); - } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.LOGGING) { - ta = initTaLoggingMode(); - } - ta.setDynamicSuperProperties(() => { - return { - env: app.get('env'), - sid: app.getServerId() - }; - }); - app.set('ta', ta); - } -} - -export function reportTAEvent(roleId: string, eventName: string, properties: any, ip?: string, distinctId?: string) { - let ta = pinus.app.get('ta'); - if(!ta) return - let event = { - // 账号 ID (可选) - accountId: `${roleId}`, - // 访客 ID (可选),账号 ID 和访客 ID 不可以都为空 - distinctId: (distinctId && distinctId != 'weikaiqishushu')? `${distinctId}`:"", - // 事件名称 (必填) - event: eventName, - // 事件时间 (可选) 如果不填,将以调用接口时的时间作为事件时间 - time: new Date(), - // 事件 IP (可选) 当传入 IP 地址时,后台可以解析所在地 - ip: ip, - // 事件属性 (可选) - properties, - callback(err) { - console.log('*****测试接入事件', err) - } - - }; - ta.track(event); -} - -export function reportTAUserSet(type: TA_USERSET_TYPE, roleId: string, properties: any) { - let ta = pinus.app.get('ta'); - if(!ta) return - let userData = { - // 账号 ID (可选) - accountId: `${roleId}`, - // 访客 ID (可选),账号 ID 和访客 ID 不可以都为空 - distinctId: "", - // 用户属性 - properties, - // 出错时回调 (可选) - callback(e) { - if (e) { - console.log(e); - } - } - }; - if(type == TA_USERSET_TYPE.SET) { - ta.userSet(userData); - } else if (type == TA_USERSET_TYPE.SET_ONCE) { - ta.userSetOnce(userData); - } else if (type == TA_USERSET_TYPE.ADD) { - ta.userAdd(userData); - } -} - -export async function reportCreateRoleEventToTa(role: RoleType, ip: string) { - if(role.shushuMark) { - reportTAEvent(role.roleId, TA_EVENT.CREATE_ROLE, null, ip, role.shushuMark); - await RoleModel.updateRoleInfo(role.roleId, { shushuMark: '' }); - } -} - -export function taflush() { - let ta = pinus.app.get('ta'); - if(!ta) return; - if(ta.flush) ta.flush(); - if(ta.close) ta.close(); -} - -export async function fetch37Words() { - let params = new GetWordParam(); - let result = await request37GetWord(SDK_37_ADDR.GET_WORD, params, SDK_37_CONST.CHAT_KEY); - - writeWordTxt(FILENAME.FILTER_WORDS, result); - return result; -} - -export async function getTire() { - console.log('**********getTire') - let trie = pinus.app.get('tire'); - if(!trie) { - let blockWords = readWordTxt(FILENAME.FILTER_WORDS); - if(!blockWords) { - blockWords = await fetch37Words(); - } - trie = new Trie(); - let blockWordsArr = blockWords.split('\n'); - blockWordsArr.forEach(word => { - let arr = word.split('||'); - trie.insertData(arr[0]); - }); - pinus.app.set('tire', trie); - } - - return trie -} - -export async function _checkFilterWords(word: string) { - let trie = await getTire(); - if (word.length > 30) return false; - - let cleanStr = word.trim().replace(/ /gi, '').replace('\n','').replace(/&/gi, ''); - let hitStr = trie.getHitStr(cleanStr); - if (hitStr) { - console.log(`命中屏蔽词: ${hitStr}`); - return false; - } - return true; -} - -export async function checkFilterWords(word: string) { - if(pinus.app.getServerType() == 'chat') { - return await _checkFilterWords(word); - } else { - let servers = pinus.app.getServersByType('chat'); - let server = getRandSingleEelm(servers); - return await pinus.app.rpc.chat.chatRemote.checkFilterWords.toServer(server.id, word); - } -} - -export async function sendSurveyMail(code: string) { - console.log('***** sendSurveyMail', code); - let rec = await SurveyRecModel.findByCode(code); - if(!rec || rec.hasSentMail) return false; - console.log('***** sendSurveyMail hasSentMail', rec.hasSentMail); - - let survey = await SurveyModel.findBySurveyId(rec.surveyId); - if(!survey) return false; - console.log('***** sendSurveyMail survey', survey); - - await sendMailByContent(MAIL_TYPE.SEND_MAIL, rec.roleId, { goods: survey.reward, params: [survey.mailContent] }); - await sendMessageToUserWithSuc(rec.roleId, PUSH_ROUTE.DELETE_SURVEY, { code: survey.code }); - rec = await SurveyRecModel.send(rec.code); -} - -export async function sendGiftCodeMail(message: string) { - console.log('***** sendGiftCodeMail 1', message); - let [roleId, _giftId] = message.split('|'); - let giftId = parseInt(_giftId); - console.log('****** sendGiftCodeMail 2', roleId, giftId, isNaN(giftId)) - if(isNaN(giftId) || !roleId) return false; - let giftCode = await GiftCodeModel.findByGiftId(giftId); - if(!giftCode) { - console.log('***** sendGiftCodeMail giftId not found', giftId); - return false; - } - - console.log('****** sendGiftCodeMail 3', roleId, giftCode.goods); - await sendMailByContent(MAIL_TYPE.SEND_MAIL, roleId, { goods: giftCode.goods, params: ['尊敬的百家传人,附件为您在平台活动获得的奖励,请查收!'] }); -} \ No newline at end of file +/********** 37sdk **********/ + +import { RoleModel, RoleType } from "@db/Role"; +import { Chat37Params, CheckGuild37Params, CheckName37Params, GetWordParam, PostGuild37Params, PostName37Params, PushMsg37Param } from "@domain/sdk"; +import { sendMailByContent, sendMailToGuildByContent } from './mailService'; +import { NAMEPLATE } from '@pubUtils/dicParam'; +import { CHANNEL_PREFIX, FILENAME, getSdkChannelId, MAIL_TYPE, PUSH_ROUTE, REDIS_KEY, SDK_37_ADDR, SDK_37_CONST, SDK_PUSH_TARGET_TYPE, SDK_TA_CONST, STATUS, TA_EVENT, TA_USERSET_TYPE, THINKING_DATA_MODE, THINKING_DATA_MODE_LIST } from "@consts"; +import { UserModel } from "@db/User"; +import { request37CheckChat, request37GetWord, request37Post, request37PushMessage } from "@pubUtils/httpUtil"; +import { GuildModel } from "@db/Guild"; +import { getRoleOnlineInfo, updateUserInfo } from "./redisService"; +import { Application, pinus } from "pinus"; +import { getRandSingleEelm, parseGoodStr, readWordTxt, resResult, writeWordTxt } from "@pubUtils/util"; +const ThinkingAnalytics = require("thinkingdata-node"); +import Trie from '@pubUtils/trie'; +import _ = require("underscore"); +import { getGoldObject } from "./role/rewardService"; +import { SurveyRecModel } from "@db/SurveyRec"; +import { SurveyModel } from "@db/Survery"; +import { pushGuildInfoUpdate } from "./guildService"; +import { sendMessageToUserWithSuc } from "./pushService"; +import { GuildLeader } from "@domain/rank"; +import { initTaLoggingMode } from "./sdk/ta"; +import { DicPushMessage } from "@pubUtils/dictionary/DicPushMessage"; +import { GiftCodeModel } from "@db/GiftCode"; +import { GiftCodeDetailModel } from "@db/GiftCodeDetail"; + +// 检查私聊是否合法 + +export async function checkPrivateChat(roleId: string, targetRoleId: string, message: string) { + let body = new Chat37Params(message, getSdkChannelId('private')); + let myRole = await RoleModel.findByRoleId(roleId); + let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); + if(myUser.channelInfo) { + body.setByMyRole(myRole, myUser); + let targetRole = await RoleModel.findByRoleId(targetRoleId); + let targetUser = await UserModel.findUserByUid(targetRole.userInfo.uid); + body.setByTargetRole(targetRole, targetUser); + return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); + } + return true; +} + +export async function checkGuildChat(roleId: string, guildCode: string, message: string) { + let body = new Chat37Params(message, getSdkChannelId(CHANNEL_PREFIX.GUILD)); + let myRole = await RoleModel.findByRoleId(roleId); + let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); + if(myUser.channelInfo) { + body.setByMyRole(myRole, myUser); + body.setByGuild(guildCode); + return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); + } + return true; +} + +export async function checkOtherChat(roleId: string, channelPrefix: string, message: string) { + let body = new Chat37Params(message, getSdkChannelId(channelPrefix)); + let myRole = await RoleModel.findByRoleId(roleId); + let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); + if(!!myUser.channelInfo) { + body.setByMyRole(myRole, myUser); + return await request37CheckChat(SDK_37_ADDR.CHECK_CHAT, body, SDK_37_CONST.CHAT_KEY); + } + return true; +} + +export async function checkRoleName(roleId: string, roleName: string, myRole?: RoleType) { + if(!myRole) { + myRole = await RoleModel.findByRoleId(roleId); + } + let myUser = await UserModel.findUserByUid(myRole.userInfo.uid); + if(!!myUser.channelInfo) { + let body = new CheckName37Params(myRole, roleName, myUser); + let result = await request37Post(SDK_37_ADDR.CHECK_NAME, body, SDK_37_CONST.CHAT_KEY); + if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 + return await checkFilterWords(roleName); + } else if (result == 0) { + return false; + } + request37Post(SDK_37_ADDR.POST_NAME, new PostName37Params(myRole, roleName, myUser), SDK_37_CONST.CHAT_KEY); + } + return true; +} + +export async function checkGuildName(guildCode: string, serverId: number, name: string, notice: string) { + let nameResult = true, noticeResult = true; + if(name != undefined) { + let body = new CheckGuild37Params(guildCode, serverId, 1, name); + let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY); + if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 + nameResult = await checkFilterWords(name); + } else if (result == 0) { + nameResult = false; + } + if(nameResult) request37Post(SDK_37_ADDR.POST_UNION, new PostGuild37Params(guildCode, serverId, 1, name), SDK_37_CONST.CHAT_KEY); + } + if(notice != undefined) { + if(notice == '') notice = ' '; + let body = new CheckGuild37Params(guildCode, serverId, 2, notice); + let result = await request37Post(SDK_37_ADDR.CHECK_UNION, body, SDK_37_CONST.CHAT_KEY); + if(result == STATUS.REQUEST_TIME_OUT.code) { // 超时 + noticeResult = await checkFilterWords(name); + } else if (result == 0) { + noticeResult = false; + } + if(noticeResult) request37Post(SDK_37_ADDR.POST_UNION, new PostGuild37Params(guildCode, serverId, 2, notice), SDK_37_CONST.CHAT_KEY); + } + return nameResult && noticeResult +} + + +// 根据37sdk处理违规玩家名 +export async function treatRoleName(roleId: string, isDebug?: boolean) { + let role = await RoleModel.findByRoleId(roleId); + if((role && role.sdkMark) || isDebug) { // 有设置标记的情况下 + let newName = "默认玩家名"; + // 新名字上传 + await checkRoleName(roleId, newName, role); + // 改名字 + await RoleModel.updateRoleInfo(roleId, { roleName: newName, sdkMark: false }); + // 通知处理 + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'roleName', value: newName }]); // redis缓存 + if(role.isGuildLeader) { + await updateUserInfo(REDIS_KEY.GUILD_INFO, role.guildCode, [{ field: 'leader', value: new GuildLeader(role) }]); + } + const { sid } = await getRoleOnlineInfo(roleId); + if(!!sid) { + await pinus.app.rpc.connector.connectorRemote.setOtherUserSession.toServer(sid,[{ roleId, roleName: newName }]); // 改session + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.PLAYER_DATA_CHANGE, { roleName: newName }, sid); + } + // 补偿 + let gold = getGoldObject(NAMEPLATE.NAMEPLATE_FEECOST) + await sendMailByContent(MAIL_TYPE.TREAT_ROLE_NAME, role.roleId, { goods: [gold] }); + } +} + +// 根据37sdk处理违规军团数据 +export async function treatGuildName(content: string) { + let params: { code: string, serverId: number, type: number }; + try { + params = JSON.parse(content); + } catch(e) { + return false; + } + + let guild = await GuildModel.findByCode(params.code, params.serverId, '+members'); + if(guild && guild.sdkMark) { // 有设置标记的情况下 + if(params.type == 1) { // 公会名 + let newName = "默认公会名"; + // 新名字上传 + await checkGuildName(params.code, params.serverId, newName, undefined); + await GuildModel.updateInfo(params.code, { name: newName, sdkMark: false }); + // 通知处理 + await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件 + await pushGuildInfoUpdate(params.code, { name: newName }); + await updateUserInfo(REDIS_KEY.GUILD_INFO, params.code, [{ field: 'name', value: newName }]); // redis缓存信息 + for(let roleId of guild.members) { + await updateUserInfo(REDIS_KEY.USER_INFO, roleId, [{ field: 'guildName', value: newName }]); + } + await RoleModel.updateGuildName(params.code, newName); + + } else if (params.type == 2) { // 公会公告 + await checkGuildName(params.code, params.serverId, undefined, ' '); + await GuildModel.updateInfo(params.code, { notice: ' ', sdkMark: false }); + // 通知处理 + await sendMailToGuildByContent(MAIL_TYPE.TREAT_GUILD_INFO, params.code, {}); // 邮件 + await pushGuildInfoUpdate(params.code, { notice: '' }); + } + } +} + +// 37接口 消息推送 +export async function pushMsg37(code: string, dic: DicPushMessage, target: SDK_PUSH_TARGET_TYPE, audience: string) { + let body = new PushMsg37Param(code); + body.setMsgInfo(dic, target, audience); + return await request37PushMessage(SDK_37_ADDR.PUSH_MSG, body, SDK_37_CONST.PUSH_KEY); +} + +export function connectThinkingData(app: Application) { + let ta; + if(app.get('env') != 'development') { + if(THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.DEBUG) { + ta = ThinkingAnalytics.initWithDebugMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); + } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.BATCH) { + ta = ThinkingAnalytics.initWithBatchMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); + } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.LOGGING) { + ta = initTaLoggingMode(true); + } + ta.setDynamicSuperProperties(() => { + return { + env: app.get('env'), + sid: app.getServerId() + }; + }); + app.set('ta', ta); + } +} + +export function reportTAEvent(roleId: string, eventName: string, properties: any, ip?: string, distinctId?: string) { + let ta = pinus.app.get('ta'); + if(!ta) return + let event = { + // 账号 ID (可选) + accountId: `${roleId}`, + // 访客 ID (可选),账号 ID 和访客 ID 不可以都为空 + distinctId: (distinctId && distinctId != 'weikaiqishushu')? `${distinctId}`:"", + // 事件名称 (必填) + event: eventName, + // 事件时间 (可选) 如果不填,将以调用接口时的时间作为事件时间 + time: new Date(), + // 事件 IP (可选) 当传入 IP 地址时,后台可以解析所在地 + ip: ip, + // 事件属性 (可选) + properties, + callback(err) { + console.log('*****测试接入事件', err) + } + + }; + ta.track(event); +} + +export function reportTAUserSet(type: TA_USERSET_TYPE, roleId: string, properties: any) { + let ta = pinus.app.get('ta'); + if(!ta) return + let userData = { + // 账号 ID (可选) + accountId: `${roleId}`, + // 访客 ID (可选),账号 ID 和访客 ID 不可以都为空 + distinctId: "", + // 用户属性 + properties, + // 出错时回调 (可选) + callback(e) { + if (e) { + console.log(e); + } + } + }; + if(type == TA_USERSET_TYPE.SET) { + ta.userSet(userData); + } else if (type == TA_USERSET_TYPE.SET_ONCE) { + ta.userSetOnce(userData); + } else if (type == TA_USERSET_TYPE.ADD) { + ta.userAdd(userData); + } +} + +export async function reportCreateRoleEventToTa(role: RoleType, ip: string) { + if(role.shushuMark) { + reportTAEvent(role.roleId, TA_EVENT.CREATE_ROLE, null, ip, role.shushuMark); + await RoleModel.updateRoleInfo(role.roleId, { shushuMark: '' }); + } +} + +export function taflush() { + let ta = pinus.app.get('ta'); + if(!ta) return; + if(ta.flush) ta.flush(); + if(ta.close) ta.close(); +} + +export async function fetch37Words() { + let params = new GetWordParam(); + let result = await request37GetWord(SDK_37_ADDR.GET_WORD, params, SDK_37_CONST.CHAT_KEY); + + writeWordTxt(FILENAME.FILTER_WORDS, result); + return result; +} + +export async function getTire() { + console.log('**********getTire') + let trie = pinus.app.get('tire'); + if(!trie) { + let blockWords = readWordTxt(FILENAME.FILTER_WORDS); + if(!blockWords) { + blockWords = await fetch37Words(); + } + trie = new Trie(); + let blockWordsArr = blockWords.split('\n'); + blockWordsArr.forEach(word => { + let arr = word.split('||'); + trie.insertData(arr[0]); + }); + pinus.app.set('tire', trie); + } + + return trie +} + +export async function _checkFilterWords(word: string) { + let trie = await getTire(); + if (word.length > 30) return false; + + let cleanStr = word.trim().replace(/ /gi, '').replace('\n','').replace(/&/gi, ''); + let hitStr = trie.getHitStr(cleanStr); + if (hitStr) { + console.log(`命中屏蔽词: ${hitStr}`); + return false; + } + return true; +} + +export async function checkFilterWords(word: string) { + if(pinus.app.getServerType() == 'chat') { + return await _checkFilterWords(word); + } else { + let servers = pinus.app.getServersByType('chat'); + let server = getRandSingleEelm(servers); + return await pinus.app.rpc.chat.chatRemote.checkFilterWords.toServer(server.id, word); + } +} + +export async function sendSurveyMail(code: string) { + console.log('***** sendSurveyMail', code); + let rec = await SurveyRecModel.findByCode(code); + if(!rec || rec.hasSentMail) return false; + console.log('***** sendSurveyMail hasSentMail', rec.hasSentMail); + + let survey = await SurveyModel.findBySurveyId(rec.surveyId); + if(!survey) return false; + console.log('***** sendSurveyMail survey', survey); + + await sendMailByContent(MAIL_TYPE.SEND_MAIL, rec.roleId, { goods: survey.reward, params: [survey.mailContent] }); + await sendMessageToUserWithSuc(rec.roleId, PUSH_ROUTE.DELETE_SURVEY, { code: survey.code }); + rec = await SurveyRecModel.send(rec.code); +} + +export async function sendGiftCodeMail(message: string) { + console.log('***** sendGiftCodeMail 1', message); + let [roleId, _giftId] = message.split('|'); + let giftId = parseInt(_giftId); + console.log('****** sendGiftCodeMail 2', roleId, giftId, isNaN(giftId)) + if(isNaN(giftId) || !roleId) return false; + let giftCode = await GiftCodeModel.findByGiftId(giftId); + if(!giftCode) { + console.log('***** sendGiftCodeMail giftId not found', giftId); + return false; + } + + console.log('****** sendGiftCodeMail 3', roleId, giftCode.goods); + await sendMailByContent(MAIL_TYPE.SEND_MAIL, roleId, { goods: giftCode.goods, params: ['尊敬的百家传人,附件为您在平台活动获得的奖励,请查收!'] }); +} diff --git a/game-server/app/services/serverService.ts b/game-server/app/services/serverService.ts index af259c4a2..adfc05a1b 100644 --- a/game-server/app/services/serverService.ts +++ b/game-server/app/services/serverService.ts @@ -1,185 +1,185 @@ -import { pinus } from "pinus"; -import { uniq } from "underscore"; -import { ACTIVITY_TYPE, GVG_SERVER_TYPE, REDIS_KEY, SERVER_GROUP_FUN_TYPE } from "../consts"; -import { ServerGroupModel } from "../db/ServerGroup"; -import { ServerlistModel } from "../db/Serverlist"; -import { nowSeconds } from "../pubUtils/timeUtil"; -import { getServerTypeByTime } from "./gvg/gvgService"; -import { getAllServerCreateTime, redisClient } from "./redisService"; -import moment = require("moment"); -import { RegionModel, RegionType } from "../db/Region"; -import { errlogger } from "../util/logger"; -import { CreateServerParam } from "../domain/backEndField/params"; -import { sendOpenServerMail } from "./gmService"; -import { ActivityGroupModel } from "../db/ActivityGroup"; -import { ActivityModel } from "../db/Activity"; - -export async function setServerGroup() { - const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - let now = nowSeconds(); - const gvgServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.GVG); - const pvpServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.PVP); - // const arenaServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.ARENA); - pinus.app.set('gvgServerGroup', servers.map(obj => { - let server = gvgServerGroup.find(cur => cur.serverId == obj.id); - return [obj.id, server? server.groupId: obj.groupId] - })); - pinus.app.set('pvpServerGroup', servers.map(obj => { - let server = pvpServerGroup.find(cur => cur.serverId == obj.id); - return [obj.id, server? server.groupId: obj.groupId] - })); - // pinus.app.set('arenaServerGroup', servers.map(obj => { - // let server = arenaServerGroup.find(cur => cur.serverId == obj.id); - // return [obj.id, server? server.groupId: obj.groupId] - // })); - -} - -export async function getAllGroupOfServer(serverId: number) { - let gvgGroupId = await getGVGGroupIdOfServer(serverId); - let pvpGroupId = await getPVPGroupIdOfServer(serverId); - return uniq([gvgGroupId, pvpGroupId]); -} - -// GVG相关:查询本小区所在战区 -export async function getGVGGroupIdOfServer(serverId: number) { - return await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG); -} - -// PVP相关:查询本小区所在战区 -export async function getPVPGroupIdOfServer(serverId: number) { - return await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.PVP); -} - -// 查询本小区所在的战区 -export async function getGroupIdOfServer(serverId: number, fun: SERVER_GROUP_FUN_TYPE) { - let arr: number[][] = pinus.app.get(getPinusKeyOfFun(fun))||[]; - let obj = arr.find(cur => cur[0] == serverId)||[]; - return obj[1]||0; -} - -// 查询当前和本小区同一个战区的其他小区 -export async function getGVGServersOfSameGroup(type: GVG_SERVER_TYPE, id: number) { - if(type == GVG_SERVER_TYPE.SINGLE) return [id]; - - let groupId = await getGroupIdOfServer(id, SERVER_GROUP_FUN_TYPE.GVG); - return await getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.GVG); -} - -export async function getPVPServersOfSameGroup(serverId: number) { - let groupId = await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.PVP); - return await getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.PVP); -} - -export async function getGVGServersByGroupId(groupId: number) { - return getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.GVG); -} - -export async function getPvpServersByGroupId(groupId: number) { - return getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.PVP); -} - -export async function getServersByGroupId(groupId: number, fun: SERVER_GROUP_FUN_TYPE) { - let arr: number[][] = pinus.app.get(getPinusKeyOfFun(fun))||[]; - let serverCreateTimes = await getAllServerCreateTime(); - - return arr.filter(obj => { - if(fun == SERVER_GROUP_FUN_TYPE.GVG) { - let openTime = parseInt(serverCreateTimes[obj[0]]); - return obj[1] == groupId && getServerTypeByTime(openTime) == GVG_SERVER_TYPE.MULTI; - } else { - return obj[1] == groupId - } - }).map(obj => obj[0]); -} - -function getPinusKeyOfFun(fun: SERVER_GROUP_FUN_TYPE) { - switch(fun) { - case SERVER_GROUP_FUN_TYPE.GVG: return 'gvgServerGroup'; - case SERVER_GROUP_FUN_TYPE.PVP: return 'pvpServerGroup'; - case SERVER_GROUP_FUN_TYPE.ARENA: return 'arenaServerGroup'; - default: return ''; - } -} - -export async function getPVPServerGroup() { - let now = nowSeconds(); - const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - const pvpServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.PVP); - let map = new Map(); - for(let server of servers) { - let serverGroup = pvpServerGroup.find(cur => cur.serverId == server.id); - let groupId = serverGroup? serverGroup.groupId: server.groupId; - if(!map.has(groupId)) map.set(groupId, []); - map.get(groupId).push(server.id); - } - return map -} - -export async function autoCreateServerSchedule() { - console.log('******* autoCreateServerSchedule *******') - let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); - if(!region) { - return errlogger.error('create new server region not found'); - } - let time = moment().format('HH:mm'); - let latestServerOpenTime = region.latestServerOpenTime||0; - if(region.stategy && region.stategy.type == 1 && region.stategy.timers.indexOf(time) != -1 && latestServerOpenTime < nowSeconds()) { - let latestServer = await ServerlistModel.findByServerId(region.latestServerUniqId); - if(!latestServer || latestServer.playerCnt >= region.stategy.maxPlayerCnt) { - let params = new CreateServerParam(); - params.setByRegionStategy(region, nowSeconds()) - await createNewServer(region, (latestServer?.serverId||0) + 1, params); - } - } - -} - -export async function autoCreateServerWhenRoleInit(serverId: number) { - console.log('******* autoCreateServerWhenRoleInit *******') - let server = await ServerlistModel.incRoleCnt(serverId); - if(!server) { - return errlogger.error('server not found'); - } - let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); - if(!region) { - return errlogger.error('create new server region not found'); - } - - let latestServerOpenTime = region.latestServerOpenTime||0; - if(region.stategy && region.stategy.isOpen && region.stategy.type == 2 && region.latestServerUniqId == server.id && server.playerCnt >= region.stategy.maxPlayerCnt && latestServerOpenTime <= nowSeconds()) { - let params = new CreateServerParam(); - params.setByRegionStategy(region, nowSeconds()) - await createNewServer(region, server.serverId + 1, params); - } -} - -export async function createNewServer(region: RegionType ,serverId: number, params: CreateServerParam, uid?: number) { - console.log('******* createNewServer *******') - let newServer = await ServerlistModel.newServer(params, region, serverId, uid); - if(!newServer) return; - if(params.openMail) await sendOpenServerMail('openMail', params.openMail, newServer, uid); - // if(params.circleMail) await sendOpenServerMail('circleMail', params.circleMail, newServer, uid); - if(params.activityGroupId && params.activityGroupId.length > 0) { - await ActivityGroupModel.addServerToGroupData(newServer.id, params.activityGroupId); - let activityGroups = await ActivityGroupModel.findByServerId(newServer.id); - await pinus.app.rpc.activity.activityRemote.addServerToGroup.broadcast(params.activityGroupId, [newServer.id]); - - let aids = activityGroups.reduce((pre, cur) => [...pre, ...cur.activities], []); - let activities = await ActivityModel.findActivityByIds(aids); - let timeLimitRanks = activities.filter(cur => cur.type == ACTIVITY_TYPE.TIME_LIMIT_RANK); - if(timeLimitRanks.length > 0) { - pinus.app.rpc.systimer.systimerRemote.updateTimeLimitRank.broadcast(timeLimitRanks); - } - } - await RegionModel.newServer(region.id, newServer); - await redisClient().hsetAsync(REDIS_KEY.SERVER, `${newServer.id}`, `${newServer.name}`); - await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${newServer.id}`, `${newServer.openTime}`); - await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); - await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); - await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); - await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); - await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); - -} \ No newline at end of file +import { pinus } from "pinus"; +import { uniq } from "underscore"; +import { ACTIVITY_TYPE, GVG_SERVER_TYPE, REDIS_KEY, SERVER_GROUP_FUN_TYPE } from "@consts"; +import { ServerGroupModel } from "@db/ServerGroup"; +import { ServerlistModel } from "@db/Serverlist"; +import { nowSeconds } from "@pubUtils/timeUtil"; +import { getServerTypeByTime } from "./gvg/gvgService"; +import { getAllServerCreateTime, redisClient } from "./redisService"; +import moment = require("moment"); +import { RegionModel, RegionType } from "@db/Region"; +import { errlogger } from "../util/logger"; +import { CreateServerParam } from "@domain/backEndField/params"; +import { sendOpenServerMail } from "./gmService"; +import { ActivityGroupModel } from "@db/ActivityGroup"; +import { ActivityModel } from "@db/Activity"; + +export async function setServerGroup() { + const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + let now = nowSeconds(); + const gvgServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.GVG); + const pvpServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.PVP); + // const arenaServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.ARENA); + pinus.app.set('gvgServerGroup', servers.map(obj => { + let server = gvgServerGroup.find(cur => cur.serverId == obj.id); + return [obj.id, server? server.groupId: obj.groupId] + })); + pinus.app.set('pvpServerGroup', servers.map(obj => { + let server = pvpServerGroup.find(cur => cur.serverId == obj.id); + return [obj.id, server? server.groupId: obj.groupId] + })); + // pinus.app.set('arenaServerGroup', servers.map(obj => { + // let server = arenaServerGroup.find(cur => cur.serverId == obj.id); + // return [obj.id, server? server.groupId: obj.groupId] + // })); + +} + +export async function getAllGroupOfServer(serverId: number) { + let gvgGroupId = await getGVGGroupIdOfServer(serverId); + let pvpGroupId = await getPVPGroupIdOfServer(serverId); + return uniq([gvgGroupId, pvpGroupId]); +} + +// GVG相关:查询本小区所在战区 +export async function getGVGGroupIdOfServer(serverId: number) { + return await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG); +} + +// PVP相关:查询本小区所在战区 +export async function getPVPGroupIdOfServer(serverId: number) { + return await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.PVP); +} + +// 查询本小区所在的战区 +export async function getGroupIdOfServer(serverId: number, fun: SERVER_GROUP_FUN_TYPE) { + let arr: number[][] = pinus.app.get(getPinusKeyOfFun(fun))||[]; + let obj = arr.find(cur => cur[0] == serverId)||[]; + return obj[1]||0; +} + +// 查询当前和本小区同一个战区的其他小区 +export async function getGVGServersOfSameGroup(type: GVG_SERVER_TYPE, id: number) { + if(type == GVG_SERVER_TYPE.SINGLE) return [id]; + + let groupId = await getGroupIdOfServer(id, SERVER_GROUP_FUN_TYPE.GVG); + return await getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.GVG); +} + +export async function getPVPServersOfSameGroup(serverId: number) { + let groupId = await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.PVP); + return await getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.PVP); +} + +export async function getGVGServersByGroupId(groupId: number) { + return getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.GVG); +} + +export async function getPvpServersByGroupId(groupId: number) { + return getServersByGroupId(groupId, SERVER_GROUP_FUN_TYPE.PVP); +} + +export async function getServersByGroupId(groupId: number, fun: SERVER_GROUP_FUN_TYPE) { + let arr: number[][] = pinus.app.get(getPinusKeyOfFun(fun))||[]; + let serverCreateTimes = await getAllServerCreateTime(); + + return arr.filter(obj => { + if(fun == SERVER_GROUP_FUN_TYPE.GVG) { + let openTime = parseInt(serverCreateTimes[obj[0]]); + return obj[1] == groupId && getServerTypeByTime(openTime) == GVG_SERVER_TYPE.MULTI; + } else { + return obj[1] == groupId + } + }).map(obj => obj[0]); +} + +function getPinusKeyOfFun(fun: SERVER_GROUP_FUN_TYPE) { + switch(fun) { + case SERVER_GROUP_FUN_TYPE.GVG: return 'gvgServerGroup'; + case SERVER_GROUP_FUN_TYPE.PVP: return 'pvpServerGroup'; + case SERVER_GROUP_FUN_TYPE.ARENA: return 'arenaServerGroup'; + default: return ''; + } +} + +export async function getPVPServerGroup() { + let now = nowSeconds(); + const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + const pvpServerGroup = await ServerGroupModel.findByTime(now, SERVER_GROUP_FUN_TYPE.PVP); + let map = new Map(); + for(let server of servers) { + let serverGroup = pvpServerGroup.find(cur => cur.serverId == server.id); + let groupId = serverGroup? serverGroup.groupId: server.groupId; + if(!map.has(groupId)) map.set(groupId, []); + map.get(groupId).push(server.id); + } + return map +} + +export async function autoCreateServerSchedule() { + console.log('******* autoCreateServerSchedule *******') + let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); + if(!region) { + return errlogger.error('create new server region not found'); + } + let time = moment().format('HH:mm'); + let latestServerOpenTime = region.latestServerOpenTime||0; + if(region.stategy && region.stategy.type == 1 && region.stategy.timers.indexOf(time) != -1 && latestServerOpenTime < nowSeconds()) { + let latestServer = await ServerlistModel.findByServerId(region.latestServerUniqId); + if(!latestServer || latestServer.playerCnt >= region.stategy.maxPlayerCnt) { + let params = new CreateServerParam(); + params.setByRegionStategy(region, nowSeconds()) + await createNewServer(region, (latestServer?.serverId||0) + 1, params); + } + } + +} + +export async function autoCreateServerWhenRoleInit(serverId: number) { + console.log('******* autoCreateServerWhenRoleInit *******') + let server = await ServerlistModel.incRoleCnt(serverId); + if(!server) { + return errlogger.error('server not found'); + } + let region = await RegionModel.findRegionByEnv(pinus.app.get('env')); + if(!region) { + return errlogger.error('create new server region not found'); + } + + let latestServerOpenTime = region.latestServerOpenTime||0; + if(region.stategy && region.stategy.isOpen && region.stategy.type == 2 && region.latestServerUniqId == server.id && server.playerCnt >= region.stategy.maxPlayerCnt && latestServerOpenTime <= nowSeconds()) { + let params = new CreateServerParam(); + params.setByRegionStategy(region, nowSeconds()) + await createNewServer(region, server.serverId + 1, params); + } +} + +export async function createNewServer(region: RegionType ,serverId: number, params: CreateServerParam, uid?: number) { + console.log('******* createNewServer *******') + let newServer = await ServerlistModel.newServer(params, region, serverId, uid); + if(!newServer) return; + if(params.openMail) await sendOpenServerMail('openMail', params.openMail, newServer, uid); + // if(params.circleMail) await sendOpenServerMail('circleMail', params.circleMail, newServer, uid); + if(params.activityGroupId && params.activityGroupId.length > 0) { + await ActivityGroupModel.addServerToGroupData(newServer.id, params.activityGroupId); + let activityGroups = await ActivityGroupModel.findByServerId(newServer.id); + await pinus.app.rpc.activity.activityRemote.addServerToGroup.broadcast(params.activityGroupId, [newServer.id]); + + let aids = activityGroups.reduce((pre, cur) => [...pre, ...cur.activities], []); + let activities = await ActivityModel.findActivityByIds(aids); + let timeLimitRanks = activities.filter(cur => cur.type == ACTIVITY_TYPE.TIME_LIMIT_RANK); + if(timeLimitRanks.length > 0) { + pinus.app.rpc.systimer.systimerRemote.updateTimeLimitRank.broadcast(timeLimitRanks); + } + } + await RegionModel.newServer(region.id, newServer); + await redisClient().hsetAsync(REDIS_KEY.SERVER, `${newServer.id}`, `${newServer.name}`); + await redisClient().hsetAsync(REDIS_KEY.SERVER_OPEN_TIME, `${newServer.id}`, `${newServer.openTime}`); + await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); + await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); + await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); + await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); + await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); + +} diff --git a/game-server/app/services/shopService.ts b/game-server/app/services/shopService.ts index d91d7702d..ff5a6a2c9 100644 --- a/game-server/app/services/shopService.ts +++ b/game-server/app/services/shopService.ts @@ -1,228 +1,228 @@ -import { gameData, getShopType } from "../pubUtils/data"; -import { ShopData, ShopDicExtendData, ShopReturnData } from '../domain/roleField/shop'; -import { UserShopModel, UserShopType } from "../db/UserShop"; -import { getActivitiesByType, getActivityById } from "./activity/activityService"; -import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "../consts"; -import { getRoleCreateTime, getServerCreateTime } from "./redisService"; -import { decodeArrayListStr } from "../pubUtils/util"; -import { UserShopTypeModel, UserShopTypeType } from "../db/UserShopType"; -import { GuildModel } from "../db/Guild"; -import { RoleModel } from "../db/Role"; -import { DicShop } from "../pubUtils/dictionary/DicShop"; -import { BackendSession, pinus } from "pinus"; -import { ActivityModelType } from "../db/Activity"; -import { addItems } from "./role/rewardService"; -import { LadderMatchModel } from "../db/LadderMatch"; -import { isGoodsHidden } from "./dataService"; - -export async function getAllShopList(roleId: string, serverId: number) { - let seasonNum = pinus.app.get('pvpSeasonNum'); - let userShopRecs = await UserShopModel.findByRoleId(roleId, seasonNum); - let userShopTypeRecs = await UserShopTypeModel.findByRoleId(roleId); - let activities = await getShopActivityDatas(roleId, serverId); - - let shops: ShopReturnData[] = []; - for(let [_, { shop, type } ] of gameData.shopType) { - let activity = activities.find(cur => cur.shop == shop && cur.type == type); - let readRecord = userShopTypeRecs.find(cur => cur.shop == shop && cur.type == type); - let shopData = await getShopListByData(shop, type, userShopRecs, activity, readRecord); - shops.push(shopData); - } - return shops; -} - -export async function getShopListByType(shop: number, type: number, roleId: string, serverId: number) { - let seasonNum = pinus.app.get('pvpSeasonNum'); - let userShopRecs = await UserShopModel.findByShopType(roleId, shop, type, seasonNum); - let activities = await getShopActivityDatas(roleId, serverId); - let activity = activities.find(cur => cur.shop == shop && cur.type == type); - let readRecord = await UserShopTypeModel.findByType(roleId, shop, type); - return await getShopListByData(shop, type, userShopRecs, activity, readRecord); -} - -async function getShopListByData(shop: number, type: number, userShopRecs: UserShopType[], activity: ShopData, readRecord: UserShopTypeType) { - let result = new ShopReturnData(shop, type); - - let dicShopType = getShopType(shop, type); - if(dicShopType && dicShopType.isLimit) { - if(activity) result.setDicByActivity(activity); - result.setReadRecord(readRecord); - } - for(let userShop of userShopRecs) { - result.addUserRecords(userShop); - } - - return result; -} - - -export async function getShopDicById(activityId: number, itemId: number, roleId: string, serverId: number) { - if(!activityId || activityId == 0) { - return gameData.shopItem.get(itemId); - } else { - let activityData = await getShopActivityById(roleId, serverId, activityId); - return activityData.findByItemId(itemId); - } -} - -export async function getShopActivityDatas(roleId: string, serverId: number) { - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.SHOP); - return activities.map(activity => { - return new ShopData(activity, createTime, serverTime); - }); -} - -export async function getShopActivityById(roleId: string, serverId: number, activityId: number) { - let createTime = await getRoleCreateTime(roleId); - let serverTime = await getServerCreateTime(serverId); - let activity = await getActivityById(activityId); - return new ShopData(activity, createTime, serverTime); -} - -/** - * - * @param goodId 物品 - * @param count 本次购买次数 - * @param buyCount 上次购买到多少次 - * @param str 字典 - */ -export function getShopPrice(goodId: number, count: number, buyCount: number, str: string) { - let arr = parseShopPrice(str); - let result = 0; - for(let i = 0; i < count; i++) { - let curPrice = 0; - for(let { times, price, maxTimes } of arr) { - if(buyCount + i + 1 >= times && (buyCount + i + 1 <= maxTimes||maxTimes == -1)) { - curPrice = price; break; - } - } - result += curPrice; - } - return [{ - id: goodId, - count: result - }] -} - -function parseShopPrice(str: string) { - let result = new Array<{ times: number, price: number, maxTimes: number }>(); - if (!str) return result; - let decodeArr = decodeArrayListStr(str); - for (let i = 0; i < decodeArr.length; i++) { - let [times, price] = decodeArr[i]; - if (isNaN(parseInt(times)) || isNaN(parseInt(price))) { - throw new Error('data table format wrong'); - } - result.push({ times: parseInt(times), price: parseInt(price), maxTimes: -1 }); - if(result[i - 1]) result[i - 1].maxTimes = parseInt(times); - } - return result -} - -export async function checkShopInPurchase(session: BackendSession, activityId: number, count: number, buyCount: number, dicShopItem: DicShop|ShopDicExtendData) { - let roleId = session.get('roleId'); - let guildCode = session.get('guildCode'); - let serverId = session.get('serverId'); - let vipStartTime: number = session.get('vipStartTime'); - - return await checkShopItemCanBuy(activityId, dicShopItem.id, roleId, serverId, guildCode, vipStartTime, count, buyCount, dicShopItem) -} - -export async function checkShopCanBuyInOrder(roleId: string, serverId: number, activity: ActivityModelType, productID: string) { - let seasonNum = pinus.app.get('pvpSeasonNum'); - let role = await RoleModel.findByRoleId(roleId, 'guildCode createTime vipStartTime'); - let { createTime, guildCode, vipStartTime } = role; - let serverTime = await getServerCreateTime(serverId); - let shopData = new ShopData(activity, createTime, serverTime); - if(!shopData) return false; - let dicItem = shopData.findByProductID(productID); - if(!dicItem) return false; - - let userShop = await UserShopModel.findByRoleAndItem(roleId, dicItem, seasonNum); - let result = await checkShopItemCanBuy(activity.activityId, dicItem.id, roleId, serverId, guildCode, vipStartTime, 1, userShop?.count||0, dicItem); - return result.code == STATUS.SUCCESS.code; -} - -export async function checkShopItemCanBuy(activityId: number, shopItemId: number, roleId: string, serverId: number, guildCode: string, vipStartTime: number, count: number, buyCount: number, dicShopItem?: DicShop|ShopDicExtendData) { - - if(!dicShopItem) { - dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); - } - if(!dicShopItem) return STATUS.DIC_DATA_NOT_FOUND; - - if(dicShopItem.guildLvLimit) { - let myGuild = await GuildModel.findByCode(guildCode, serverId); - if(!myGuild || myGuild.lv < dicShopItem.guildLvLimit) return STATUS.GUILD_LV_LIMIT; - } - if(dicShopItem.lvLimit) { - let role = await RoleModel.findByRoleId(roleId, 'lv'); - if(role.lv < dicShopItem.lvLimit) { - return STATUS.LV_LIMIT; - } - } - if(dicShopItem.ranklimit) { - let ladder = await LadderMatchModel.findByRoleId(roleId); - if(ladder.historyRank > dicShopItem.ranklimit) { - return STATUS.LADDER_LV_LIMIT; - } - } - if(dicShopItem.purchaseLimit != -1) { - if(vipStartTime > 0 && dicShopItem.vipPurchaseLimit != -1) { - if(buyCount + count > dicShopItem.purchaseLimit + dicShopItem.vipPurchaseLimit) { - return STATUS.BUY_COUNT_OVER; - } - } else { - if(buyCount + count > dicShopItem.purchaseLimit) { - return STATUS.BUY_COUNT_OVER; - } - } - } - if(isGoodsHidden(dicShopItem.goodId)) { - return STATUS.ITEM_IS_HIDDEN; - } - return STATUS.SUCCESS -} - -/** - * rmb购买 - * - * @param {number} serverId 区Id - * @param {number} activityId 活动Id - * @param {string} roleId 角色Id - * @param {string} productID 商品ID - * - */ - export async function makeShopOrder(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { - let seasonNum = pinus.app.get('pvpSeasonNum'); - let activityData: ActivityModelType = await getActivityById(activityId); - if (!activityData) { - return STATUS.ACTIVITY_MISSING; - } - if (activityData.type !== ACTIVITY_TYPE.SHOP) { - return STATUS.ACTIVITY_TYPE_ERROR; - } - let role = await RoleModel.findByRoleId(roleId, 'guildCode createTime vipStartTime'); - let { createTime, guildCode, vipStartTime } = role; - let serverTime = await getServerCreateTime(serverId); - let shopData = new ShopData(activityData, createTime, serverTime); - let dicItem = shopData.findByProductID(productID); - if(!dicItem) return STATUS.DIC_DATA_NOT_FOUND; - - let userShop = await UserShopModel.findByRoleAndItem(roleId, dicItem, seasonNum); - let result = await checkShopItemCanBuy(activityId, dicItem.id, roleId, serverId, guildCode, vipStartTime, 1, userShop?.count||0, dicItem); - if(result.code != STATUS.SUCCESS.code) return result; - - let reward = [{ - id: dicItem.goodId, - count: 1 - }]; - await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE); - - await UserShopModel.purchase(roleId, roleName, activityId, dicItem, 1, seasonNum); - return { - code: 0, - data: Object.assign({}, { item: { shop: dicItem.shop, type: dicItem.type, shopItemId: dicItem.id }, activityId: activityId }) - } -} \ No newline at end of file +import { gameData, getShopType } from "@pubUtils/data"; +import { ShopData, ShopDicExtendData, ShopReturnData } from '@domain/roleField/shop'; +import { UserShopModel, UserShopType } from "@db/UserShop"; +import { getActivitiesByType, getActivityById } from "./activity/activityService"; +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "@consts"; +import { getRoleCreateTime, getServerCreateTime } from "./redisService"; +import { decodeArrayListStr } from "@pubUtils/util"; +import { UserShopTypeModel, UserShopTypeType } from "@db/UserShopType"; +import { GuildModel } from "@db/Guild"; +import { RoleModel } from "@db/Role"; +import { DicShop } from "@pubUtils/dictionary/DicShop"; +import { BackendSession, pinus } from "pinus"; +import { ActivityModelType } from "@db/Activity"; +import { addItems } from "./role/rewardService"; +import { LadderMatchModel } from "@db/LadderMatch"; +import { isGoodsHidden } from "./dataService"; + +export async function getAllShopList(roleId: string, serverId: number) { + let seasonNum = pinus.app.get('pvpSeasonNum'); + let userShopRecs = await UserShopModel.findByRoleId(roleId, seasonNum); + let userShopTypeRecs = await UserShopTypeModel.findByRoleId(roleId); + let activities = await getShopActivityDatas(roleId, serverId); + + let shops: ShopReturnData[] = []; + for(let [_, { shop, type } ] of gameData.shopType) { + let activity = activities.find(cur => cur.shop == shop && cur.type == type); + let readRecord = userShopTypeRecs.find(cur => cur.shop == shop && cur.type == type); + let shopData = await getShopListByData(shop, type, userShopRecs, activity, readRecord); + shops.push(shopData); + } + return shops; +} + +export async function getShopListByType(shop: number, type: number, roleId: string, serverId: number) { + let seasonNum = pinus.app.get('pvpSeasonNum'); + let userShopRecs = await UserShopModel.findByShopType(roleId, shop, type, seasonNum); + let activities = await getShopActivityDatas(roleId, serverId); + let activity = activities.find(cur => cur.shop == shop && cur.type == type); + let readRecord = await UserShopTypeModel.findByType(roleId, shop, type); + return await getShopListByData(shop, type, userShopRecs, activity, readRecord); +} + +async function getShopListByData(shop: number, type: number, userShopRecs: UserShopType[], activity: ShopData, readRecord: UserShopTypeType) { + let result = new ShopReturnData(shop, type); + + let dicShopType = getShopType(shop, type); + if(dicShopType && dicShopType.isLimit) { + if(activity) result.setDicByActivity(activity); + result.setReadRecord(readRecord); + } + for(let userShop of userShopRecs) { + result.addUserRecords(userShop); + } + + return result; +} + + +export async function getShopDicById(activityId: number, itemId: number, roleId: string, serverId: number) { + if(!activityId || activityId == 0) { + return gameData.shopItem.get(itemId); + } else { + let activityData = await getShopActivityById(roleId, serverId, activityId); + return activityData.findByItemId(itemId); + } +} + +export async function getShopActivityDatas(roleId: string, serverId: number) { + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.SHOP); + return activities.map(activity => { + return new ShopData(activity, createTime, serverTime); + }); +} + +export async function getShopActivityById(roleId: string, serverId: number, activityId: number) { + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let activity = await getActivityById(activityId); + return new ShopData(activity, createTime, serverTime); +} + +/** + * + * @param goodId 物品 + * @param count 本次购买次数 + * @param buyCount 上次购买到多少次 + * @param str 字典 + */ +export function getShopPrice(goodId: number, count: number, buyCount: number, str: string) { + let arr = parseShopPrice(str); + let result = 0; + for(let i = 0; i < count; i++) { + let curPrice = 0; + for(let { times, price, maxTimes } of arr) { + if(buyCount + i + 1 >= times && (buyCount + i + 1 <= maxTimes||maxTimes == -1)) { + curPrice = price; break; + } + } + result += curPrice; + } + return [{ + id: goodId, + count: result + }] +} + +function parseShopPrice(str: string) { + let result = new Array<{ times: number, price: number, maxTimes: number }>(); + if (!str) return result; + let decodeArr = decodeArrayListStr(str); + for (let i = 0; i < decodeArr.length; i++) { + let [times, price] = decodeArr[i]; + if (isNaN(parseInt(times)) || isNaN(parseInt(price))) { + throw new Error('data table format wrong'); + } + result.push({ times: parseInt(times), price: parseInt(price), maxTimes: -1 }); + if(result[i - 1]) result[i - 1].maxTimes = parseInt(times); + } + return result +} + +export async function checkShopInPurchase(session: BackendSession, activityId: number, count: number, buyCount: number, dicShopItem: DicShop|ShopDicExtendData) { + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + let vipStartTime: number = session.get('vipStartTime'); + + return await checkShopItemCanBuy(activityId, dicShopItem.id, roleId, serverId, guildCode, vipStartTime, count, buyCount, dicShopItem) +} + +export async function checkShopCanBuyInOrder(roleId: string, serverId: number, activity: ActivityModelType, productID: string) { + let seasonNum = pinus.app.get('pvpSeasonNum'); + let role = await RoleModel.findByRoleId(roleId, 'guildCode createTime vipStartTime'); + let { createTime, guildCode, vipStartTime } = role; + let serverTime = await getServerCreateTime(serverId); + let shopData = new ShopData(activity, createTime, serverTime); + if(!shopData) return false; + let dicItem = shopData.findByProductID(productID); + if(!dicItem) return false; + + let userShop = await UserShopModel.findByRoleAndItem(roleId, dicItem, seasonNum); + let result = await checkShopItemCanBuy(activity.activityId, dicItem.id, roleId, serverId, guildCode, vipStartTime, 1, userShop?.count||0, dicItem); + return result.code == STATUS.SUCCESS.code; +} + +export async function checkShopItemCanBuy(activityId: number, shopItemId: number, roleId: string, serverId: number, guildCode: string, vipStartTime: number, count: number, buyCount: number, dicShopItem?: DicShop|ShopDicExtendData) { + + if(!dicShopItem) { + dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); + } + if(!dicShopItem) return STATUS.DIC_DATA_NOT_FOUND; + + if(dicShopItem.guildLvLimit) { + let myGuild = await GuildModel.findByCode(guildCode, serverId); + if(!myGuild || myGuild.lv < dicShopItem.guildLvLimit) return STATUS.GUILD_LV_LIMIT; + } + if(dicShopItem.lvLimit) { + let role = await RoleModel.findByRoleId(roleId, 'lv'); + if(role.lv < dicShopItem.lvLimit) { + return STATUS.LV_LIMIT; + } + } + if(dicShopItem.ranklimit) { + let ladder = await LadderMatchModel.findByRoleId(roleId); + if(ladder.historyRank > dicShopItem.ranklimit) { + return STATUS.LADDER_LV_LIMIT; + } + } + if(dicShopItem.purchaseLimit != -1) { + if(vipStartTime > 0 && dicShopItem.vipPurchaseLimit != -1) { + if(buyCount + count > dicShopItem.purchaseLimit + dicShopItem.vipPurchaseLimit) { + return STATUS.BUY_COUNT_OVER; + } + } else { + if(buyCount + count > dicShopItem.purchaseLimit) { + return STATUS.BUY_COUNT_OVER; + } + } + } + if(isGoodsHidden(dicShopItem.goodId)) { + return STATUS.ITEM_IS_HIDDEN; + } + return STATUS.SUCCESS +} + +/** + * rmb购买 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ + export async function makeShopOrder(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { + let seasonNum = pinus.app.get('pvpSeasonNum'); + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.SHOP) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let role = await RoleModel.findByRoleId(roleId, 'guildCode createTime vipStartTime'); + let { createTime, guildCode, vipStartTime } = role; + let serverTime = await getServerCreateTime(serverId); + let shopData = new ShopData(activityData, createTime, serverTime); + let dicItem = shopData.findByProductID(productID); + if(!dicItem) return STATUS.DIC_DATA_NOT_FOUND; + + let userShop = await UserShopModel.findByRoleAndItem(roleId, dicItem, seasonNum); + let result = await checkShopItemCanBuy(activityId, dicItem.id, roleId, serverId, guildCode, vipStartTime, 1, userShop?.count||0, dicItem); + if(result.code != STATUS.SUCCESS.code) return result; + + let reward = [{ + id: dicItem.goodId, + count: 1 + }]; + await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE); + + await UserShopModel.purchase(roleId, roleName, activityId, dicItem, 1, seasonNum); + return { + code: 0, + data: Object.assign({}, { item: { shop: dicItem.shop, type: dicItem.type, shopItemId: dicItem.id }, activityId: activityId }) + } +} diff --git a/game-server/app/services/sysChatService.ts b/game-server/app/services/sysChatService.ts index 779184cdd..0b06374cc 100644 --- a/game-server/app/services/sysChatService.ts +++ b/game-server/app/services/sysChatService.ts @@ -1,176 +1,176 @@ -import { EPlace, HeroType } from '../db/Hero'; -import { GuildType } from '../db/Guild'; -import { CHANNEL_PREFIX, HERO_GROW_MAX, HERO_INITIAL_QUALITY, MSG_SOURCE, MSG_TYPE, WAR_TYPE } from '../consts'; -import { createGroupMsg, pushGroupMsgToRoom } from './chatService'; -import { pick } from 'lodash'; -import { isString } from 'underscore'; -import { BossInstanceType } from '../db/BossInstance'; -import { GroupMessageType } from '../db/GroupMessage'; -import { HERO } from '../pubUtils/dicParam'; - -async function pushNormalHeroInfoBySource(roleId: string, roleName: string, serverId: number | string, source: number, heroInfo: Partial) { - const hero = pick(heroInfo, ['hName', 'hid', 'seqId', 'quality', 'star', 'starStage', 'colorStar', 'colorStarStage']); - const content = JSON.stringify({ roleId, roleName, hero }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); - await pushGroupMsgToRoom(msgData); -} - -export async function pushHeroQualityUpMsg(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { - await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_QUALITY_UP, heroInfo); -} - -export async function pushGetHero(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { - if (heroInfo.quality == HERO_INITIAL_QUALITY.ORANGE) { - await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.GET_ORANGE_HERO, heroInfo); - } else if(heroInfo.quality == HERO_INITIAL_QUALITY.UR){ - await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.GET_UR_HERO, heroInfo); - } -} - -export async function pushHeroStarMax(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { - if (heroInfo.colorStar !== HERO_GROW_MAX.STAR) { - return; - } - await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_STAR_MAX, heroInfo); -} - -export async function pushHeroWakeUp(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { - await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_WAKE_UP, heroInfo); -} - -// 装备升星到12星 -export async function pushEquipStarMax(roleId: string, roleName: string, serverId: number, hid: number, equip: EPlace, isUpStar: boolean) { - const { id, equipId, star, quality, } = equip; - if(!isUpStar || star != HERO_GROW_MAX.EQUIP_STAR) return; - - const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_STAR_UP, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -// 装备升品到金色 -export async function pushEquipQualityMax(roleId: string, roleName: string, serverId: number, hid: number, equip: EPlace, isUpQuality: boolean) { - const { id, equipId, star, quality, } = equip; - if(isUpQuality && quality == HERO_GROW_MAX.EQUIP_QUALITY) { - const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_QUALITY_UP, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; - } - if(isUpQuality && quality == HERO_GROW_MAX.EQUIP_QUALITY_TO_6) { - const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_QUALITY_TO_6, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; - - } - -} - -export async function pushPresent(roleId: string, roleName: string, serverId: number | string, toRoleName: string, id: number) { - const content = JSON.stringify({ roleId, roleName, toRoleName, id }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GROUP_SEND_GIFT, content, null, null); - await pushGroupMsgToRoom(msgData); -} - -export async function pushComBtlTeamMsg(teamCode: string, roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.TEAM, teamCode, type, source, content, targetRoleId, targetMsgCode); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushGuildNoticeUpdateMsg(roleId: string, roleName: string, guildInfo: Partial) { - const { code, notice } = guildInfo; - if (!code || !isString(notice)) return null; - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, code, MSG_TYPE.TEXT, MSG_SOURCE.GUILD_NOTICE, notice, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushGuildUpStructureMsg(roleId: string, roleName: string, guildInfo: Partial, structure: {id: number, lv: number}) { - const { code, name } = guildInfo; - const guild = { code, name, structure }; - const content = JSON.stringify({ roleId, roleName, guild }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, code, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_STRUCTURE_LV_UP, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushGuildTrainSucMsg(roleId: string, roleName: string, guildCode: string, hid: number) { - if (!guildCode) return null; - const content = JSON.stringify({ roleId, roleName, hid }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_TRAIN_SUC, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushGuildBossSucMsg(roleId: string, roleName: string, guildCode: string, bossInstance: BossInstanceType) { - const boss = pick(bossInstance, ['warId', 'bossLv']); - const content = JSON.stringify({ roleId, roleName, boss }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_BOSS_SUC, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushNormalEquipMsg(roleId: string, roleName: string, serverId: number, source: number, id: number, name: string, quality: number) { - const content = JSON.stringify({ roleId, roleName, equip: { id, name, quality } }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushNormalItemMsg(roleId: string, roleName: string, serverId: number, source: number, id: number, name: string) { - const content = JSON.stringify({ roleId, roleName, equip: { id, name } }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushTowerMsg(roleId: string, roleName: string, serverId: number, source: number, lv: number) { - if (!shouldPushTowerMsg(lv)) return null; - const content = JSON.stringify({ roleId, roleName, lv }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -async function pushGKFirstMsg(roleId: string, roleName: string, serverId: number, source: number, warType: number, warId: number) { - const content = JSON.stringify({ roleId, roleName, warInfo: { warType, warId } }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function pushMysteryFirstMsg(roleId: string, roleName: string, serverId: number, warType: number, warId: number) { - if (warType !== WAR_TYPE.MYSTERY) return null; - const result = await pushGKFirstMsg(roleId, roleName, serverId, MSG_SOURCE.MYSTERY_FIRST_SUC, warType, warId); - return result; -} - -export async function pushVestigeFirstMsg(roleId: string, roleName: string, serverId: number, warType: number, warId: number) { - if (warType !== WAR_TYPE.VESTIGE) return null; - const result = await pushGKFirstMsg(roleId, roleName, serverId, MSG_SOURCE.VESTIGE_FIRST_SUC, warType, warId); - return result; -} - -export async function pushLadderTopChangeMsg(roleId: string, roleName: string, serverId: number | string) { - const content = JSON.stringify({ roleId, roleName }); - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.LADDER_FIRST_CHANGE, content, null, null); - await pushGroupMsgToRoom(msgData); - return msgData; -} - -export async function createMarqueeMsg(roleId: string, roleName: string, serverId: number | string, content: string) { - const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.SEND_MARQUEE, content, null, null); - return msgData; -} - -export async function pushMarqueeMsg(msgData: GroupMessageType) { - await pushGroupMsgToRoom(msgData); -} - -function shouldPushTowerMsg(lv: number) { - // 100 层之后每 50 层触发 - return lv >= 100 && lv % 50 === 0; -} +import { EPlace, HeroType } from '@db/Hero'; +import { GuildType } from '@db/Guild'; +import { CHANNEL_PREFIX, HERO_GROW_MAX, HERO_INITIAL_QUALITY, MSG_SOURCE, MSG_TYPE, WAR_TYPE } from '@consts'; +import { createGroupMsg, pushGroupMsgToRoom } from './chatService'; +import { pick } from 'lodash'; +import { isString } from 'underscore'; +import { BossInstanceType } from '@db/BossInstance'; +import { GroupMessageType } from '@db/GroupMessage'; +import { HERO } from '@pubUtils/dicParam'; + +async function pushNormalHeroInfoBySource(roleId: string, roleName: string, serverId: number | string, source: number, heroInfo: Partial) { + const hero = pick(heroInfo, ['hName', 'hid', 'seqId', 'quality', 'star', 'starStage', 'colorStar', 'colorStarStage']); + const content = JSON.stringify({ roleId, roleName, hero }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); + await pushGroupMsgToRoom(msgData); +} + +export async function pushHeroQualityUpMsg(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { + await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_QUALITY_UP, heroInfo); +} + +export async function pushGetHero(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { + if (heroInfo.quality == HERO_INITIAL_QUALITY.ORANGE) { + await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.GET_ORANGE_HERO, heroInfo); + } else if(heroInfo.quality == HERO_INITIAL_QUALITY.UR){ + await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.GET_UR_HERO, heroInfo); + } +} + +export async function pushHeroStarMax(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { + if (heroInfo.colorStar !== HERO_GROW_MAX.STAR) { + return; + } + await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_STAR_MAX, heroInfo); +} + +export async function pushHeroWakeUp(roleId: string, roleName: string, serverId: number | string, heroInfo: Partial) { + await pushNormalHeroInfoBySource(roleId, roleName, serverId, MSG_SOURCE.HERO_WAKE_UP, heroInfo); +} + +// 装备升星到12星 +export async function pushEquipStarMax(roleId: string, roleName: string, serverId: number, hid: number, equip: EPlace, isUpStar: boolean) { + const { id, equipId, star, quality, } = equip; + if(!isUpStar || star != HERO_GROW_MAX.EQUIP_STAR) return; + + const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_STAR_UP, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +// 装备升品到金色 +export async function pushEquipQualityMax(roleId: string, roleName: string, serverId: number, hid: number, equip: EPlace, isUpQuality: boolean) { + const { id, equipId, star, quality, } = equip; + if(isUpQuality && quality == HERO_GROW_MAX.EQUIP_QUALITY) { + const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_QUALITY_UP, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; + } + if(isUpQuality && quality == HERO_GROW_MAX.EQUIP_QUALITY_TO_6) { + const content = JSON.stringify({ roleId, roleName, hid, eplaceId: id, equipId, star, quality }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.EQUIP_QUALITY_TO_6, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; + + } + +} + +export async function pushPresent(roleId: string, roleName: string, serverId: number | string, toRoleName: string, id: number) { + const content = JSON.stringify({ roleId, roleName, toRoleName, id }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GROUP_SEND_GIFT, content, null, null); + await pushGroupMsgToRoom(msgData); +} + +export async function pushComBtlTeamMsg(teamCode: string, roleId: string, roleName: string, type: number, source: number, content: string, targetRoleId: string, targetMsgCode: string) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.TEAM, teamCode, type, source, content, targetRoleId, targetMsgCode); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushGuildNoticeUpdateMsg(roleId: string, roleName: string, guildInfo: Partial) { + const { code, notice } = guildInfo; + if (!code || !isString(notice)) return null; + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, code, MSG_TYPE.TEXT, MSG_SOURCE.GUILD_NOTICE, notice, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushGuildUpStructureMsg(roleId: string, roleName: string, guildInfo: Partial, structure: {id: number, lv: number}) { + const { code, name } = guildInfo; + const guild = { code, name, structure }; + const content = JSON.stringify({ roleId, roleName, guild }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, code, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_STRUCTURE_LV_UP, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushGuildTrainSucMsg(roleId: string, roleName: string, guildCode: string, hid: number) { + if (!guildCode) return null; + const content = JSON.stringify({ roleId, roleName, hid }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_TRAIN_SUC, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushGuildBossSucMsg(roleId: string, roleName: string, guildCode: string, bossInstance: BossInstanceType) { + const boss = pick(bossInstance, ['warId', 'bossLv']); + const content = JSON.stringify({ roleId, roleName, boss }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.GUILD, guildCode, MSG_TYPE.RICH_TEXT, MSG_SOURCE.GUILD_BOSS_SUC, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushNormalEquipMsg(roleId: string, roleName: string, serverId: number, source: number, id: number, name: string, quality: number) { + const content = JSON.stringify({ roleId, roleName, equip: { id, name, quality } }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushNormalItemMsg(roleId: string, roleName: string, serverId: number, source: number, id: number, name: string) { + const content = JSON.stringify({ roleId, roleName, equip: { id, name } }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushTowerMsg(roleId: string, roleName: string, serverId: number, source: number, lv: number) { + if (!shouldPushTowerMsg(lv)) return null; + const content = JSON.stringify({ roleId, roleName, lv }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +async function pushGKFirstMsg(roleId: string, roleName: string, serverId: number, source: number, warType: number, warId: number) { + const content = JSON.stringify({ roleId, roleName, warInfo: { warType, warId } }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, source, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function pushMysteryFirstMsg(roleId: string, roleName: string, serverId: number, warType: number, warId: number) { + if (warType !== WAR_TYPE.MYSTERY) return null; + const result = await pushGKFirstMsg(roleId, roleName, serverId, MSG_SOURCE.MYSTERY_FIRST_SUC, warType, warId); + return result; +} + +export async function pushVestigeFirstMsg(roleId: string, roleName: string, serverId: number, warType: number, warId: number) { + if (warType !== WAR_TYPE.VESTIGE) return null; + const result = await pushGKFirstMsg(roleId, roleName, serverId, MSG_SOURCE.VESTIGE_FIRST_SUC, warType, warId); + return result; +} + +export async function pushLadderTopChangeMsg(roleId: string, roleName: string, serverId: number | string) { + const content = JSON.stringify({ roleId, roleName }); + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.LADDER_FIRST_CHANGE, content, null, null); + await pushGroupMsgToRoom(msgData); + return msgData; +} + +export async function createMarqueeMsg(roleId: string, roleName: string, serverId: number | string, content: string) { + const msgData = await createGroupMsg(roleId, roleName, CHANNEL_PREFIX.SYS, `${serverId}`, MSG_TYPE.RICH_TEXT, MSG_SOURCE.SEND_MARQUEE, content, null, null); + return msgData; +} + +export async function pushMarqueeMsg(msgData: GroupMessageType) { + await pushGroupMsgToRoom(msgData); +} + +function shouldPushTowerMsg(lv: number) { + // 100 层之后每 50 层触发 + return lv >= 100 && lv % 50 === 0; +} diff --git a/game-server/app/services/task/taskObj.ts b/game-server/app/services/task/taskObj.ts index cbe9ff193..f1917229e 100644 --- a/game-server/app/services/task/taskObj.ts +++ b/game-server/app/services/task/taskObj.ts @@ -1,1594 +1,1594 @@ -import { ACTIVITY_TYPE, PUSH_ROUTE, TASK_SUM_TYPE, TASK_TYPE, WAR_TYPE } from "../../consts"; -import { ActivityModelType } from "../../db/Activity"; -import { ActivityBuyRecordsModel } from "../../db/ActivityBuyRecords"; -import { ActivityDailyChallengesModel } from "../../db/ActivityDailyChallenges"; -import { ActivityGrowthModel } from "../../db/ActivityGrowth"; -import { ActivityGrowthFundModel } from "../../db/ActivityGrowthFund"; -import { ActivityRefreshTaskModel } from "../../db/ActivityRefreshTask"; -import { ActivityThirtyDaysModel } from "../../db/ActivityThirtyDays"; -import { ActivityTreasureHuntTaskModel } from "../../db/ActivityTreasureHuntTask"; -import { RoleModel, RoleType } from "../../db/Role"; -import { UserTaskRecModel } from "../../db/UserTaskRec"; -import { GrowthFundData } from "../../domain/activityField/growthFundField"; -import { RefreshTaskData } from "../../domain/activityField/refreshTaskField"; -import { SevenDaysData } from "../../domain/activityField/sevenDaysField"; -import { ThirtyDaysData } from "../../domain/activityField/thirtyDaysField"; -import { TreasureHuntData } from "../../domain/activityField/treasureHuntField"; -import { TaskListReturn, TaskParam, TaskParamInter, UpdateTaskParam } from "../../domain/roleField/task"; -import { gameData, getDicBlueprtById, getEquipSuitByHero, getGVGTasksByType } from "../../pubUtils/data"; -import { getZeroPoint } from "../../pubUtils/timeUtil"; -import { getActivityByServerId } from "../activity/activityService"; -import { getRoleCreateTime, getRoleOnlineInfo, getServerCreateTime } from "../redisService"; -import { getEquipById, getJewelByEquip, isRandSeUnLock } from "../equipService"; -import { sendMessageToUserWithSuc } from "../pushService"; -import { GVGUserTaskModel } from "../../db/GVGUserTask"; - -export class CheckTask { - serverId: number; // 区id - roleId: string; // 玩家id - role?: RoleType; - roleCreateTime: number; // 玩家的创建时间 - serverCreateTime: number; // 服务器的创建时间 - - configId?: number; - leagueCode?: string; - - taskPushMessages: TaskListReturn[] = []; - activityTaskPushMessages = []; - gvgTaskPushMessages = []; - - tasks: CheckSingleTask[] = []; - - constructor(serverId: number, roleId: string) { - this.serverId = serverId; - this.roleId = roleId; - } - - public setParam(taskType: TASK_TYPE, param: TaskParamInter) { - let task = new CheckSingleTask(taskType, this); - task.param.setParam(param); - this.tasks.push(task); - } - - setLeague(configId: number, leagueCode: string) { - this.configId = configId; - this.leagueCode = leagueCode; - } - - public async saveAndPush(sid?: string) { - for(let task of this.tasks) { - await task.check(); - } - await this.pushMessage(sid); - } - - public setRole(role: RoleType) { - this.role = role; - } - - // 用于活动任务:获取服务器开服时间 - async getServerCreateTime() { - if(!this.serverCreateTime) { - this.serverCreateTime = await getServerCreateTime(this.serverId); - } - return this.serverCreateTime; - } - - // 用于活动任务:获取玩家创建时间 - async getRoleCreateTime() { - if(!this.roleCreateTime) { - if(this.role) { - this.roleCreateTime = this.role?.createTime; - } else { - this.roleCreateTime = await getRoleCreateTime(this.roleId); - } - } - if(!this.roleCreateTime) { - let role = await RoleModel.findByRoleId(this.roleId); - this.role = role; - this.roleCreateTime = role.createTime; - } - return this.roleCreateTime; - } - - // 推送 - public async pushMessage(sid?: string) { - let roleId = this.roleId; - if (!sid) { - let onlineUser = await getRoleOnlineInfo(roleId); - sid = onlineUser.sid; - } - if(!!sid) { - if (this.taskPushMessages.length > 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TASK_UPDATE,this.taskPushMessages, sid); - } - if(this.gvgTaskPushMessages.length > 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_TASK_UPDATE,this.gvgTaskPushMessages, sid); - } - if (this.activityTaskPushMessages.length > 0) { - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_TASK_UPDATE, this.activityTaskPushMessages, sid); - } - } - } - -} - -/** - * @class CheckTask - * @classdesc 检查某个玩家任务的达成情况 - */ -export class CheckSingleTask { - serverId: number; // 区id - roleId: string; // 玩家id - taskType: TASK_TYPE; // 任务type - parent: CheckTask; - param: TaskParam; // 检查任务时传入的参数 - - constructor(taskType: TASK_TYPE, parent: CheckTask) { - this.taskType = taskType; - this.parent = parent; - this.serverId = parent.serverId; - this.roleId = parent.roleId; - this.param = new TaskParam(); - } - - private addTaskPushMessage(...param: TaskListReturn[]) { - this.parent.taskPushMessages.push(...param); - } - - private addGVGTaskPushMessage(...param: {id: number, count: number}[]) { - this.parent.gvgTaskPushMessages.push(...param); - } - - private addActivityTaskPushMessage(...param: any[]) { - this.parent.activityTaskPushMessages.push(...param); - } - - private getServerCreateTime() { - return this.parent.getServerCreateTime(); - } - - private getRoleCreateTime() { - return this.parent.getRoleCreateTime(); - } - - private getRole() { - return this.parent.role; - } - - /** - * @description 检查任务的主程序 - */ - public async check() { - let { taskType, roleId, serverId } = this; - let serverCreateTime = await this.getServerCreateTime(); - let roleCreateTime = await this.getRoleCreateTime(); - let param = this.param; - let dicTaskTypeDesc = gameData.taskDescByType.get(taskType); - - // 检查一般任务 - let dicTasks = gameData.taskType.get(taskType)||[]; - let groups = new Map(); // 以group做区分 - for (let { id, type, group, taskParam } of dicTasks) { - if (!groups.has(`${type}_${group}`)) { - groups.set(`${type}_${group}`, { type, group, taskParam, taskIds: [] }); - } - groups.get(`${type}_${group}`).taskIds.push(id); - } - for (let [_typeAndGroup, { type, group, taskParam, taskIds }] of groups) { - - let taskUpdateParam = await this.checkIsMatch(taskParam, async () => { - let data = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); - return data?.records ?? []; - }); - if (taskUpdateParam) { - let rec = await UserTaskRecModel.setOrIncTask(roleId, type, taskType, group, taskUpdateParam); - if (!rec) continue; - - for (let id of taskIds) { - if (rec.received && rec.received.includes(id)) continue; // 已领取,不再推送 - let received = rec.received || []; - this.addTaskPushMessage({ type, id: id, count: rec.count, received: received.includes(id) }); - } - - } - } - - // 联军任务 - let dicGVGTasks = getGVGTasksByType(taskType); - for(let { taskId, taskType, taskParam } of dicGVGTasks) { - let taskUpdateParam = await this.checkIsMatch(taskParam, async () => []); - if (taskUpdateParam) { - let rec = await GVGUserTaskModel.setOrIncTask(this.parent.configId, this.parent.leagueCode, roleId, taskType, taskId, taskUpdateParam); - if (!rec) continue; - - if(rec.status == 1) { - this.addGVGTaskPushMessage({ id: taskId, count: rec.count }); - } - } - } - - // 检查活动任务 - let activities = await getActivityByServerId(serverId); - for(let activity of activities) { - let { activityId, type: activityType } = activity; - switch(activityType) { - case ACTIVITY_TYPE.SEVEN_DAY: - case ACTIVITY_TYPE.FOURTEEN_DAY://十四天乐活动 28 - case ACTIVITY_TYPE.COMMON_SEVEN_DAY://通用七天乐活动 29 - { - //成长活动统计 - let playerData = new SevenDaysData(activity, roleCreateTime, serverCreateTime); - let growthTaskArray = playerData.growth.findTaskByType(taskType); // 所有任务 - for (let task of growthTaskArray) { - if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !playerData.canShow()) { - continue; - } - let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { - let data = await ActivityGrowthModel.findDataByCellIndex(serverId, activityId, roleId, task.dayIndex, task.cellIndex); - return data?.records ?? []; - }); - if(taskUpdateParam) { - let rec = await ActivityGrowthModel.setOrIncTask(serverId, activityId, roleId, task.dayIndex, task.cellIndex, taskType, taskUpdateParam); - if(!rec) continue; - this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId, activityType: "growth" }); - } - } - //今日挑战统计 - let dailyChallengeTaskArray = playerData.dailyChallenge.findTaskByType(taskType); - for (let task of dailyChallengeTaskArray) { - if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && task.dayIndex != playerData.today()) { - continue; - } else if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.SUM && task.dayIndex < playerData.today()) { - continue; - } - let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { - let data = await ActivityDailyChallengesModel.findDataByCellIndex(serverId, activityId, roleId, task.dayIndex, task.cellIndex); - return data?.records ?? []; - }); - if(taskUpdateParam) { - let rec = await ActivityDailyChallengesModel.setOrIncTask(serverId, activityId, roleId, task.dayIndex, task.cellIndex, taskType, taskUpdateParam); - if(!rec) continue; - this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId, activityType: "daily" }); - } - } - break; - } - case ACTIVITY_TYPE.REFRESH_TASK: - { - // 通用的刷新任务 - let taskActivity = new RefreshTaskData(activity, roleCreateTime, serverCreateTime); - let taskArray = taskActivity.findTaskByType(taskType); - for (let task of taskArray) { - if(!taskActivity.canShow()) { - continue; - } - let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { - let data = await ActivityRefreshTaskModel.findDataById(serverId, activityId, roleId, taskActivity.roundIndex, task.pageIndex, task.id, task.getRefTime()); - return data?.records ?? []; - }); - if(taskUpdateParam) { - let rec = await ActivityRefreshTaskModel.setOrIncTask(serverId, activityId, roleId, taskActivity.roundIndex, task.pageIndex, task.id, task.getRefTime(), taskType, taskUpdateParam); - if(!rec) continue; - this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId }); - } - } - break; - } - case ACTIVITY_TYPE.TREASURE_HUNT: - { - // 寻宝奇兵任务 - let playerData = new TreasureHuntData(activity, roleCreateTime, serverCreateTime); - let taskArray = playerData.tasks.findItemByTaskType(taskType); - for (let task of taskArray) { - if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !playerData.canShow()) { - continue; - } - let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { - let data = await ActivityTreasureHuntTaskModel.findDataByCellIndex(serverId, activityId, roleId, playerData.roundIndex, task.cellIndex); - return data?.records ?? []; - }); - if(taskUpdateParam) { - let rec = await ActivityTreasureHuntTaskModel.setOrIncTask(serverId, activityId, roleId, playerData.roundIndex, task.cellIndex, taskType, taskUpdateParam); - if(!rec) continue; - this.addActivityTaskPushMessage({ ...task, isReceive: rec.receiveRewardCount > 0? true: false, totalCount: rec.totalCount, activityId }); - } - } - break; - } - case ACTIVITY_TYPE.THIRTY_DAYS: - { - //30天任务统计 - let thirtyDaysActivity = new ThirtyDaysData(activity, roleCreateTime, serverCreateTime); - let taskArray = thirtyDaysActivity.findTaskByType(taskType); - for (let task of taskArray) { - if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !thirtyDaysActivity.canShow()) { - continue; - } - let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { - let data = await ActivityThirtyDaysModel.findDataByCellIndex(serverId, thirtyDaysActivity.activityId, roleId, task.pageIndex, task.cellIndex, task.tab); - return data?.records ?? []; - }); - if(taskUpdateParam) { - let rec = await ActivityThirtyDaysModel.setOrIncTask(serverId, thirtyDaysActivity.activityId, roleId, task.pageIndex, task.cellIndex, task.tab, taskType, taskUpdateParam); - if(!rec) continue; - task.setPlayerRecord(rec); - this.addActivityTaskPushMessage({ ...task, totalCount: rec.totalCount, activityId }); - } - } - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN: - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: - { - //主线成长基金 - if(taskType != TASK_TYPE.BATTLE_MAIN) continue; - let dicWar = gameData.war.get(param.warId); - if(!dicWar || dicWar.warType != WAR_TYPE.NORMAL) continue; - await this.checkFundAcctivityTask(activity, param.warId); - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_TOWER: - case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP: - { - //镇念塔成长基金 - if(taskType != TASK_TYPE.BATTLE_TOWER_LV) continue; - await this.checkFundAcctivityTask(activity, param.towerLv); - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: - case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP: - { - //精英成长基金 - if(taskType != TASK_TYPE.BATTLE_MAIN_ELITE) continue; - let dicWar = gameData.war.get(param.warId); - if(!dicWar || dicWar.warType != WAR_TYPE.MAIN_ELITE) continue; - await this.checkFundAcctivityTask(activity, param.warId); - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE: - case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP: - { - //学宫成长基金 - if (taskType != TASK_TYPE.FUND_ROUGE) continue; - await this.checkFundAcctivityTask(activity, param.rougeId); - break; - } - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR: - case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP: - { - //列传成长基金 - if (taskType != TASK_TYPE.FUND_AUTHOR) continue; - await this.checkFundAcctivityTask(activity, param.authorProgress); - break; - } - } - } - - } - - private async checkFundAcctivityTask(activity: ActivityModelType, unlockParam: number) { - let serverCreateTime = await this.getServerCreateTime(); - let roleCreateTime = await this.getRoleCreateTime(); - let growthFundActivity = new GrowthFundData(activity, roleCreateTime, serverCreateTime); - let playerRecords = await ActivityGrowthFundModel.findData(activity.activityId, this.roleId); - growthFundActivity.setPlayerRecords(playerRecords); - if (growthFundActivity.isVipActivity()) {//vip高阶需要购买 - let buyRecords = await ActivityBuyRecordsModel.findRecordsByActivityId(activity.activityId, this.roleId); - growthFundActivity.initBuyRecords(buyRecords); - } - let taskArray = growthFundActivity.unLockItem(unlockParam); - //推送 - this.addActivityTaskPushMessage(...taskArray); - } - - public async checkIsMatch(dicTaskParam: number[], getRecord: () => Promise) { - let param = this.param; - let result: UpdateTaskParam = null; - - if(this.param.debugInfo) { - return { set: this.param.debugInfo.condition } - } - - switch(this.taskType) { - case TASK_TYPE.LOGIN_SUM: // 1. 累计登录 x 天 - { - let records = await getRecord(); - let today = `${getZeroPoint()}`; - if (records.indexOf(today) == -1) { - result = { inc: 1, records: [...records, today] } - } - break; - } - case TASK_TYPE.LOGIN_SERIES: // 2. 连续登录 x 天 - { - let records = await getRecord(); - let today = `${getZeroPoint()}`; - let yesterday = `${getZeroPoint() - 24 * 60 * 60}` - if (records.indexOf(today) == -1) { - if (records.indexOf(yesterday) == -1) { - result = { set: 1, records: [...records, today] } - } else { - result = { inc: 1, records: [...records, today] } - } - } - break; - } - case TASK_TYPE.ROLE_LV: // 3. 主公达x级 - { - let { lv, oldLv } = param; - if(lv > oldLv) { - result = { set: lv } - } - break; - } - case TASK_TYPE.GACHA: // 4. 招募x次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.HERO_NUM: // 5. 拥有x名武将 - { - let { heroNum } = param; - result = { inc: heroNum }; - break; - } - case TASK_TYPE.HERO_STAR_UP: // 6. x名武将升星x次 - { - let { hero } = param; - let records = await getRecord(); - let count = 0, index = -1; - for(let i = 0; i < records.length; i++) { - let arr = records[i].split('_'); - if(parseInt(arr[0]) == hero.hid) { - count = parseInt(arr[1]); - index = i; - break; - } - } - if(index == -1) { - records.push(`${hero.hid}_${count + 1}`); - } else { - records[index] = `${hero.hid}_${count + 1}`; - } - if(count + 1 >= dicTaskParam[1]) { - result = { inc: 1, records } - } else { - result = { records } - } - break; - } - case TASK_TYPE.HERO_QUALITY: // 7. 拥有x名初始x品质武将 - { - let { heroes } = param; - let num = 0; - for(let { hid } of heroes) { - let dicHero = gameData.hero.get(hid); - if(dicHero.quality == dicTaskParam[1] ) { - num ++; - } - } - result = { inc: num }; - break; - } - case TASK_TYPE.HERO_QUALITY_STAR_UP: // 8. x名x品质升至x星 - { - let { heroes, hero, oldStar, oldColorStar } = param; - if(param.heroes) { // 创建武将的时候 - let records = await getRecord(); - let num = 0; - for(let { hid, star, colorStar } of heroes) { - let dicHero = gameData.hero.get(hid); - if(dicHero.quality == dicTaskParam[1] && (star + colorStar) == dicTaskParam[2] && records.indexOf(`${hid}`) == -1) { - records.push(`${hid}`); - num ++; - } - } - result = { records, inc: num }; - } else { // 武将升星的时候 - let hid = hero.hid; - let dicHero = gameData.hero.get(hid); - if(dicHero.quality == dicTaskParam[1] && (hero.star + hero.colorStar) >= dicTaskParam[2] && (oldStar + oldColorStar) < dicTaskParam[2] ) { - let records = await getRecord(); - if(records.indexOf(`${hid}`) == -1) { - records.push(`${hid}`); - result = { records, inc: 1 } - } - } - } - break; - } - case TASK_TYPE.HERO_LV: // 9. x名武将升至x级 - { - let { heroes, hero, oldLv } = param; - if(heroes) { // 创建武将的时候 - let num = 0; - for(let { lv } of heroes) { - if(lv >= dicTaskParam[1]) { - num ++; - } - } - result = { inc: num }; - } else { // 武将升级的时候 - if(hero.lv >= dicTaskParam[1] && oldLv < dicTaskParam[1]) { - result = { inc: 1 } - } - } - break; - } - case TASK_TYPE.HERO_TRAIN: // 10. x名武将各训练x次 - { - let { hero, trainCount } = param; - let records = await getRecord(); - let count = 0, index = -1; - for(let i = 0; i < records.length; i++) { - let arr = records[i].split('_'); - if(parseInt(arr[0]) == hero.hid) { - count = parseInt(arr[1]); - index = i; - break; - } - } - if(index == -1) { - records[index] = `${hero.hid}_${count + trainCount}`; - } else { - records.push(`${hero.hid}_${count + trainCount}`); - } - if( count < dicTaskParam[1] && count + trainCount >= dicTaskParam[1]) { - result = { inc: 1, records } - } else { - result = { records } - } - break; - } - case TASK_TYPE.HERO_QUALITY_UP: // 11. x名武将进行升品 - { - let { hero } = param; - let records = await getRecord(); - if(records.indexOf(`${hero.hid}`) == -1) { - records.push(`${hero.hid}`); - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.HERO_WAKE_UP: // 12.武将觉醒x次 - { - let { hero, oldColorStar } = param; - if(oldColorStar == 0 && hero.colorStar > 0) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.HERO_TRAIN_SUM: // 13. 训练x次 - { - let { trainCount } = param; - result = { inc: trainCount }; - break; - } - case TASK_TYPE.HERO_STAGE_UP: // 14. x名武将各兵种进阶x次 - { - let { hero, stageUpCnt } = param; - let records = await getRecord(); - let count = 0, index = -1; - for(let i = 0; i < records.length; i++) { - let arr = records[i].split('_'); - if(parseInt(arr[0]) == hero.hid) { - count = parseInt(arr[1]); - index = i; - break; - } - } - if(index == -1) { - records.push(`${hero.hid}_${count + stageUpCnt}`); - } else { - records[index] = `${hero.hid}_${count + stageUpCnt}`; - } - if( count < dicTaskParam[1] && count + stageUpCnt >= dicTaskParam[1]) { - result = { inc: 1, records } - } else { - result = { records } - } - break; - } - // case TASK_TYPE.HERO_FAVOUR_LV: // 15. - // { - // let { hero, oldFavourLv } = param; - // if(dicTaskParam[1] > oldFavourLv && dicTaskParam[1] <= hero.favourLv) { - // result = { inc: 1 }; - // } - // break; - // } - case TASK_TYPE.HERO_CONNECT: // 16. 激活x次 x星 武将羁绊 - { - let { shipId, connections, oldConnections } = param; - let oldConnectLv = oldConnections.find(cur => cur.shipId == shipId)?.level||0; - let connectLv = connections.find(cur => cur.shipId == shipId)?.level||0; - if(dicTaskParam[1] <= connectLv && dicTaskParam[1] > oldConnectLv) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.ROLE_SCHOOL_UNLOCK: // 17. 百家学宫解锁x个安置位 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.ROLE_SCHOOL_PUT_HERO: // 18. 百家学宫放置x个武将 - { - let records = await getRecord(); - let { hid } = param; - if(records.indexOf(`${hid}`) == -1) { - records.push(`${hid}`) - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.ROLE_TITLE: // 19. 爵位升至x - { - let { title, oldTitle } = param; - if(title > oldTitle) { - result = { set: title }; - } - break; - } - case TASK_TYPE.ROLE_TERAPH_STRENGTHEN: // 20. 神像强化x次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.ROLE_SCROLL_ACTIVE: // 21. 名将谱激活x武将 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.FRIEND_NUM: // 34. 拥有x名好友 - { - let role = this.getRole(); - result = { set: role.friendCnt }; - break; - } - case TASK_TYPE.FRIEND_SEND_HEART: // 35. 赠送x次友情点 - { - let { count } = param; - if(count > 0) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.CHAT: // 36. 聊天频道发言x次 - { - let { chatType, count = 1 } = param; - if (dicTaskParam[0] == 0 || dicTaskParam[0] == chatType) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_COST_AP: // 37. 消耗体力 - { - let { count } = param; - if(count > 0) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_WITH_HERO: // 38. 使用hId武将挑战x关卡x次 - { - let { warId, battleHeroes } = param; - if(this.checkIdList(dicTaskParam, 2, warId) && battleHeroes.indexOf(dicTaskParam[0]) != -1) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.BATTLE_MAIN: // 39. 主线通关第x关 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.NORMAL && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_MAIN_SWEEP: // 40. 主线扫荡X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.NORMAL) { - result = { inc: count } - } - break; - } - case TASK_TYPE.BATTLE_EVENT: // 41. 奇遇(答题/解救百姓/劫匪) x 次 - { - let { eventType } = param; - if(dicTaskParam[0] == 0|| dicTaskParam[0] == eventType) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.BATTLE_DAILY_STAR: // 42. 每日x星通关 x 次 - { - let { warId, battleStar, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0|| battleStar >= dicTaskParam[0]) && this.checkIdList(dicTaskParam, 2, warId)) { - result = { inc: count||1 } - } - break; - } - case TASK_TYPE.BATTLE_DAILY: // 43. 每日关卡挑战x次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if(dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0 || dicTaskParam[0] == dicWar.dailyType)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_DUNGEON: // 44. 参与秘境x次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if(dicWar.warType == WAR_TYPE.MYSTERY) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_DUNGEON_WAR: // 45. 秘境通关x关x难度 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if ((dicWar.warType == WAR_TYPE.MYSTERY) && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_TOWER_LV: // 46. 通关镇念塔x层 - { - let { towerLv } = param; - result = { set: towerLv }; - break; - } - case TASK_TYPE.BATTLE_TOWER: // 47. 通关镇念塔x次 - { - let { warId, count = 1, skipTower } = param; - let dicWar = gameData.war.get(warId); - // console.log('##### skipTower', skipTower) - if (skipTower || dicWar.warType == WAR_TYPE.TOWER) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_VESTIGE: // 48. 挑战遗迹x次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.VESTIGE && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_EXPEDITION: // 49. 开启远征x次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.EXPEDITION) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_EXPEDITION_BOX: // 50. 领取x次远征 x宝箱 - { - let { point } = param; - if(dicTaskParam[1] == 0 || dicTaskParam[1] == point) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.COM_BATTLE_CREATE_TEAM: // 51. 寻宝招募队友x次 - { - result = { inc: 1 }; - break; - } - - case TASK_TYPE.COM_BATTLE_ASSIST_TEAM: // 53. 协助寻宝x次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.COM_BATTLE: // 54. 组队寻宝 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.PVP: // 57. pvp挑战 x 次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.PVP_WIN: // 58. pvp胜利 x 次 - { - let { isSuccess } = param; - if(isSuccess) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.PVP_RECEIVE_BOX: // 59. 领取x次pvp巅峰之路宝箱 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.PVP_WIN_SERIES: // 60. pvp连胜x次 - { - let { isSuccess } = param; - if (isSuccess) { - result = { inc: 1 }; - } else { - result = { set: 0 }; - } - break; - } - case TASK_TYPE.PVP_HERO_SCORE: // 61. pvp拥有x个积分达到x的武将 - { - let { heroScores } = param; - let count = 0; - for (let { score } of heroScores) { - if (score >= dicTaskParam[0]) { - count++; - } - } - if (count > 0) { - result = { set: count }; - } - break; - - } - case TASK_TYPE.PVP_RANK: // 62. pvp赛季排名达到 x 名 - { - let { pvpRank } = param; - - let records = await getRecord(); - let oldPvpRank = parseInt(records[0]); - if(isNaN(oldPvpRank)) oldPvpRank = 0; - if(pvpRank > oldPvpRank) { - records[0] = `${pvpRank}`; - result = { set: pvpRank, records } - } - break; - } - case TASK_TYPE.GUILD_JOB: // 63. 军团官职晋升为x - { - let { guildJob } = param; - - let records = await getRecord(); - let oldGuildJob = parseInt(records[0]); - if(isNaN(oldGuildJob)) oldGuildJob = 0; - if(guildJob > oldGuildJob) { - records[0] = `${guildJob}`; - result = { set: guildJob, records } - } - break; - } - case TASK_TYPE.GUILD_DONATE: // 64. 军团捐献x次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.GUILD_RECEIVE_BOX: //65. 领取x次军团活跃宝箱 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.GUILD_ASSIST_REFINE: // 67. 助力炼器堂研发加速x次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.GUILD_TRAIN_SUCESS: // 68. 练兵场军团成功压制x次 - { - let { isSuccess } = param; - if(isSuccess) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.GUILD_BOSS: // 69. 演武台军团挑战x次boss - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.GUILD_TRAIN: // 70. 挑战练兵场X次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.GUILD_ACTIVITY: // 71. 参与 xxx 军团活动 x 次 - { - let { aid } = param; - if (dicTaskParam[0] == 0 || aid == dicTaskParam[0]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.GUILD_JOIN: // 72. 加入军团 - { - result = { set: 1 }; - break; - } - case TASK_TYPE.BATTLE_MAIN_ELITE: // 73. 精英通关第x关 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.MAIN_ELITE && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.HERO_QUALITY_TO_QUALITY_COUNT: // 74. x名初始x品质武将升至X品质 - { - let { hero } = param; - let dicHero = gameData.hero.get(hero.hid); - if(dicHero.quality == dicTaskParam[1] && hero.quality == dicTaskParam[2]) { - let records = await getRecord(); - if(records.indexOf(`${hero.hid}`) == -1) { - records.push(`${hero.hid}`) - result = { records, inc: 1 }; - } - } - break; - } - case TASK_TYPE.HERO_QUALITY_WAKE_UP_COUNT: // 75. x名初始x品质武将觉醒 - { - let { hero, oldColorStar } = param; - let dicHero = gameData.hero.get(hero.hid); - if(dicTaskParam[1] == dicHero.quality && oldColorStar == 0 && hero.colorStar > 0) { - let records = await getRecord(); - if(records.indexOf(`${hero.hid}`) == -1) { - records.push(`${hero.hid}`) - result = { records, inc: 1 }; - } - } - break; - } - case TASK_TYPE.HERO_WAKE_UP_STAR_UP_COUNT: // 76. x名武将觉醒后升至x星 - { - let { hero, oldColorStar } = param; - if(dicTaskParam[1] > oldColorStar && hero.colorStar >= dicTaskParam[1]) { - let records = await getRecord(); - if(records.indexOf(`${hero.hid}`) == -1) { - records.push(`${hero.hid}`) - result = { records, inc: 1 }; - } - } - break; - } - case TASK_TYPE.GUILD_TRAIN_COUNT: // 79. 练兵场通关x关x次 - { - let { warId, isComplete } = param; - if(isComplete && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.HERO_UNLOCK: // 80. 名将谱x阵营全部激活 - { - let { hero } = param; - let dicHero = gameData.hero.get(hero.hid); - if(dicHero && dicHero.camp == dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.GACHA_QUALITY_COUNT: // 81. 抽到*次品质*武将 - { - let { heroes } = param; - let count = 0; - for (let hero of heroes) { - let dicHero = gameData.hero.get(hero.hid); - if(dicHero.quality == dicTaskParam[1]) count++; - } - if(count > 0) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.ROLE_TERAPH_STAGE_UP: // 82. 神像进阶 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.HERO_WAKE_UP_COUNT: // 84. x名武将觉醒 - { - let { hero, oldColorStar } = param; - if(oldColorStar == 0 && hero.colorStar > 0) { - let records = await getRecord(); - if(records.indexOf(`${hero.hid}`) == -1) { - records.push(`${hero.hid}`); - result = { records, inc: 1 }; - } - } - break; - } - case TASK_TYPE.ACTIVITY_RMB: // 86. 某个活动充值*元 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.EQUIP_LV_TO: // 87. x件装备强化至x级 - { - let { oldEplace, newEplace, ePlaceIds } = param; - let addCount = 0; - for(let eplaceId of ePlaceIds) { - let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, eplaceId); - // console.log('##### oldEquip', oldEquip.lv, newEquip.lv, dicTaskParam[1]) - if(oldEquip.lv < dicTaskParam[1] && newEquip.lv >= dicTaskParam[1]) { - addCount += 1; - } - } - if(addCount != 0) { - result = { inc: addCount }; - } - break; - } - case TASK_TYPE.EQUIP_PUT_JEWEL: // 88. x件装备镶嵌X阶天晶石 - { - let { hid, newEquip, jewels } = param; - if(!newEquip) break; - - let jewel = getJewelByEquip(newEquip, jewels); - let lv = gameData.jewel.get(jewel?.id)?.lv || 0; - if(lv < dicTaskParam[1]) break; - - let records = await getRecord(); - if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { - records.push(`${hid}_${newEquip.id}`) - result = { records, inc: 1 }; - } - - break; - } - case TASK_TYPE.EQUIP_PUT_STONE: // 89. x件装备镶嵌X个地玉石 - { - let { hid, newEquip } = param; - if(!newEquip) break; - let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; - if(newStoneCnt < dicTaskParam[1]) break; - - let records = await getRecord(); - if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { - records.push(`${hid}_${newEquip.id}`); - result = { records, inc: 1 }; - } - - break; - } - case TASK_TYPE.EQUIP_STAR_UP_TO: // 90. x件装备升至X星 - { - let { oldEquip, newEquip } = param; - let oldStar = oldEquip?.star||0; - let star = newEquip?.star||0 - if(oldStar < dicTaskParam[1] && star >= dicTaskParam[1]) { - result = { inc: 1 }; - }; - break; - } - case TASK_TYPE.EQUIP_STAR_UP_CNT: // 91. x件装备升星X次 - { - let { hid, ePlaceId, count: paramCount } = param; - let records = await getRecord(); - let count = 0, index = -1; - for(let i = 0; i < records.length; i++) { - let arr = records[i].split('_'); - if(parseInt(arr[0]) == hid && parseInt(arr[1]) == ePlaceId) { - count = parseInt(arr[2]); - index = i; - break; - } - } - - if(index == -1) { - records.push(`${hid}_${ePlaceId}_${count + paramCount}`); - } else { - records[index] = `${hid}_${ePlaceId}_${count + paramCount}`; - } - if(count < dicTaskParam[1] && count + paramCount >= dicTaskParam[1]) { - result = { inc: 1, records } - } else { - result = { records } - } - break; - } - case TASK_TYPE.EQUIP_SUIT_SEID_NUM: // 92. x名武将激活X条套装属性 - { - let { oldEplace, newEplace, skinId } = param; - let dicEquipSuit = getEquipSuitByHero(skinId); - let oldSuitStars: number[] = [], newSuitStars: number[] = []; - for(let equipId of dicEquipSuit.equips) { - let oldEquip = oldEplace.find(cur => cur.equipId == equipId); - oldSuitStars.push(oldEquip? oldEquip.star: 0); - let newEquip = newEplace.find(cur => cur.equipId == equipId); - newSuitStars.push(newEquip? newEquip.star: 0); - } - let oldStar = Math.min(...oldSuitStars); - let newStar = Math.min(...newSuitStars); - let oldCount = 0, count = 0; - for(let { star } of dicEquipSuit.effect) { - if(oldStar >= star) oldCount++; - if(newStar >= star) count++; - } - if(oldCount < dicTaskParam[1] && count >= dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_QUALITY_UP: // 93. x件装备进行升品 - { - let { hid, ePlaceId } = param; - let records = await getRecord(); - if(records.indexOf(`${hid}_${ePlaceId}`) == -1) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_QUALITY_UP_CNT: // 94. 装备升品X次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.EQUIP_QUALITY_UP_TO: // 95. X件装备升品至Y品质 - { - let { oldEquip, newEquip } = param; - let oldQuality = oldEquip?.quality||0; - let quality = newEquip?.quality||0; - if(oldQuality < dicTaskParam[1] && quality >= dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_COMPOSE: // 96. 装备X件装备 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.EQUIP_COMPOSE_CNT: // 97. x名武将各装备x件装备 - { - let { oldEplace, newEplace } = param; - if(oldEplace.length < dicTaskParam[1] && newEplace.length >= dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_LV_UP: // 98. 装备强化X次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.EQUIP_PUT_JEWEL_CNT: // 99. X件装备镶嵌天晶 - { - let { newEquip } = param; - if(!newEquip || !newEquip.jewel) break; - let records = await getRecord(); - if(records.indexOf(`${newEquip.jewel}`) == -1) { - records.push(`${newEquip.jewel}`); - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_PUT_STONE_CNT: // 100. X件装备镶嵌地玉 - { - let { hid, newEquip } = param; - if(!newEquip) break; - let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; - if(newStoneCnt <= 0) break; - let records = await getRecord(); - - if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { - records.push(`${hid}_${newEquip.id}`); - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_STONE_CNT: // 101. 镶嵌X个地玉 - { - let { oldEquip, newEquip } = param; - let oldStoneCnt = oldEquip.stones.filter(cur => cur.stone != 0).length; - let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; - result = { inc: newStoneCnt - oldStoneCnt }; - break; - } - case TASK_TYPE.EQUIP_STONE_CNT_LV: // 102. X件装备镶嵌X个大于等于X阶地玉 - { - let { hid, newEquip } = param; - if(!newEquip) break; - let newStoneLvs = newEquip.stones.map(cur => { - let dicStone = gameData.stone.get(cur.stone); - return dicStone?dicStone.lv: 0; - }); - let newCount = newStoneLvs.filter(lv => lv >= dicTaskParam[2]).length; - if(newCount < dicTaskParam[1]) break; - - let records = await getRecord(); - if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { - records.push(`${hid}_${newEquip.id}`); - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT: // 103.X个天晶的Y条特性词条被激活 - { - let { newEquip, jewels } = param; - let newJewel = getJewelByEquip(newEquip, jewels); - if(!newJewel) break; - - let newRandSe = newJewel?.randSe||[]; - let newUnlockSeCnt = newRandSe.filter(se => { - return isRandSeUnLock(newJewel.id, se.id, newEquip.stones); - }).length; - - if(newUnlockSeCnt < dicTaskParam[1]) break; - let records = await getRecord(); - if(records.indexOf(`${newJewel.seqId}`) == -1) { - records.push(`${newJewel.seqId}`); - result = { records, inc: 1 }; - } - break; - } - case TASK_TYPE.STONE_COMPOSE: // 104. 地玉合成X次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.JEWEL_RESET: // 105. 天晶洗炼X次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.JEWEL_QUENCH: // 106. 天晶淬炼X次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.JEWEL_QUENCH_SUCCESS: // 107. 天晶成功淬炼X次 - { - let { isSuccess } = param; - if(isSuccess) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.COM_BATTLE_LV: // 108. 寻宝x品阶x次 - { - let { gid } = param; - let dicJewel = getDicBlueprtById(gid); - if(dicTaskParam[0] == dicJewel.lv) { - result = { inc: 1 }; - } - break - } - case TASK_TYPE.GUILD_REFINE: // 109. 炼器堂兑换X品阶天晶X次 - { - let { quality, count } = param; - if(dicTaskParam[0] == quality) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.EQUIP_STAR_UP_CNT_SUM: // 110. 装备总共升星x次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.BATTLE_MAIN_START: // 111. 挑战主线X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.NORMAL) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_TOWER_START: // 112. 挑战镇念塔X次 - { - let { warId, count = 1, skipTower } = param; - let dicWar = gameData.war.get(warId); - if (skipTower || dicWar.warType == WAR_TYPE.TOWER ) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_VESTIGE_START: // 113. 挑战遗迹X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.VESTIGE) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_DAILY_START: // 114. 挑战每日关卡X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if(dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0 || dicTaskParam[0] == dicWar.dailyType)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.COM_BATTLE_CREATE_TEAM_WIN: // 115. 寻宝招募队友x次 - { - result = { inc: 1 }; - break; - } - - case TASK_TYPE.COM_BATTLE_ASSIST_TEAM_WIN: // 116. 协助寻宝x次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.COM_BATTLE_WIN: // 117. 组队寻宝 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.BATTLE_EXPEDITION_START: // 118. 远征挑战X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.EXPEDITION) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.BATTLE_DUNGEON_START: // 119. 秘境挑战X次 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if(dicWar.warType == WAR_TYPE.MYSTERY) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.GUILD_GOLD_DONATE: // 120. 军团元宝捐献x次 - { - result = { inc: 1 }; - break; - } - case TASK_TYPE.LADDER_CNT: // 121. 名将擂台挑战x次 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.LADDER_SUCCESS_CNT: // 122. 名将擂台挑战胜利x次 - { - let { isSuccess, count } = param; - if(isSuccess) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.LADDER_RANK: // 123. 名将擂台排名 - { - let { oldLadderRank, ladderRank } = param; - if(ladderRank < oldLadderRank && dicTaskParam[0] >= ladderRank) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.CONNECT_ONE_HERO_MAX_LV: // 124. 单个武将其中最高等级的羁绊达X级 - { - let { connections } = param; - let records = await getRecord(); - let oldLv = records.length > 0? parseInt(records[0]): 0; - - let maxLv = Math.max(...connections.map(cur => cur.level))||0; - // console.log('##### TASK_TYPE.CONNECT_ONE_HERO_MAX_LV', oldLv, maxLv ) - if(oldLv < maxLv) { - result = { set: maxLv, records: [`${maxLv}`] }; - } - break; - } - case TASK_TYPE.CONNECT_ONE_HERO_SUM_LV: // 125. 单个武将3条羁绊总共提升X级 - { - let { connections } = param; - let records = await getRecord(); - let oldLv = records.length > 0? parseInt(records[0]): 0; - let sumLv = connections.reduce((pre, cur) => pre + cur.level, 0); - if(oldLv < sumLv) { - result = { set: sumLv, records: [`${sumLv}`] }; - } - break; - } - case TASK_TYPE.ARTIFACT_LV: // 127. 强化X件宝物至X级 - { - let { artifacts } = param; - let records = await getRecord(); - for(let { seqId, lv, hid } of artifacts) { - if(hid > 0 && lv >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) { - records.push(`${seqId}`); - } - } - result = { records, set: records.length }; - break; - } - case TASK_TYPE.ARTIFACT_QUALITY_EQUIP: // 128. 穿戴X件品质为X的宝物 - { - let { artifacts } = param; - let records = await getRecord(); - for(let { seqId, quality, hid } of artifacts) { - if(hid > 0 && quality >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) { - records.push(`${seqId}`); - } - } - result = { records, set: records.length }; - break; - } - case TASK_TYPE.ARTIFACT_COMPOSE: // 129. 合成X次宝物 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.STAR_UP_SUM: // 130. 升星总和 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.BATTLE_BRANCH_ELITE: // 131. 主线梦魇支线 - { - let { warId, count } = param; - let dicWar = gameData.war.get(warId); - if (dicWar.warType == WAR_TYPE.BRANCH_ELITE && this.checkIdList(dicTaskParam, 0, warId)) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.GVG_FARM: // 132. 农庄种植/矿山采集/木堆砍柴 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.GVG_VESTIGE: // 133. 中原遗迹挑战 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.GVG_TECH: // 134. 千机阁捐献 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.MINI_GAME_SHOOT: // 135. 单局射箭获得X分 - case TASK_TYPE.MINI_GAME_EAT_ZONGZI: // 137. 单局接粽子获得X分(大于等于均可) - case TASK_TYPE.MINI_GAME_CATCH_ZONGZI: // 138. 单局吃粽子获得X分(大于等于均可) - { - let { score } = param; - if(score >= dicTaskParam[0]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.MINI_GAME_ERASE: // 136. 单局翻牌不超出X步 - { - let { step } = param; - if(step <= dicTaskParam[0]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.MINI_GAME_SCORE: // 139. 小游戏超过X分 - { - let { gameType, score } = param; - if(gameType == dicTaskParam[0] && score >= dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.MINI_GAME_STEP: // 140. 小游戏小于X步 - { - let { gameType, step } = param; - if(gameType == dicTaskParam[0] && step <= dicTaskParam[1]) { - result = { inc: 1 }; - } - break; - } - case TASK_TYPE.FUND_ROUGE: //143 通关XX试炼几 - { - let { rougeId, count } = param; - if (rougeId == dicTaskParam[0]) { - result = { inc: count }; - } - break; - } - case TASK_TYPE.FUND_AUTHOR: //144 列传收集进度 - { - let { authorProgress } = param; - result = { set: authorProgress }; - break; - } - case TASK_TYPE.ROUGE_GET_COIN: // 145. 学宫积累x个试炼币 - { - let { addCoin } = param; - result = { inc: addCoin } - break; - } - case TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT: // 146.流派卡收集 - { - let records = await getRecord(); - let { authorType, cardType, cardIds } = param; - if (authorType == dicTaskParam[0] && cardType == dicTaskParam[1]) { - for (let cardId of cardIds) { - if (records.indexOf(`${cardId}`) == -1) { - records.push(`${cardId}`); - } - } - result = { records, set: records.length }; - } - break;; - } - case TASK_TYPE.ROUGE_HOLY_COLLECT: // 147.圣物卡收集 - { - let records = await getRecord(); - let { cardIds } = param; - for (let cardId of cardIds) { - if (records.indexOf(`${cardId}`) == -1) { - records.push(`${cardId}`); - } - } - result = { records, set: records.length }; - - break; - } - case TASK_TYPE.ROUGE_EVENT_COLLECT: // 148.事件收集 - { - let records = await getRecord(); - let { eventGroups } = param; - for (let eventGroup of eventGroups){ - records.push(`${eventGroup}`); - } - result = { records, set: records.length }; - break; - } - case TASK_TYPE.ROUGE_TECH_OPEN: // 149.法阵开启数量 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.ROUGE_GAME_COUNT: // 150.肉鸽次数 - { - let { count } = param; - result = { inc: count }; - break; - } - case TASK_TYPE.ROUGE_BOSS_PASS: // 151.试炼通过boss关 - { - let { authorType, count } = param; - if (authorType == dicTaskParam[0]) { - result = { inc: count }; - } - break; - } - } - return result - } - - private checkIdList(taskParam: number[], index: number, id: number) { - let count = taskParam[index]; - if (!count) return false; - let idList = taskParam.slice(index + 1, index + 1 + count); - return idList.indexOf(id) != -1; - } - -} +import { ACTIVITY_TYPE, PUSH_ROUTE, TASK_SUM_TYPE, TASK_TYPE, WAR_TYPE } from "@consts"; +import { ActivityModelType } from "@db/Activity"; +import { ActivityBuyRecordsModel } from "@db/ActivityBuyRecords"; +import { ActivityDailyChallengesModel } from "@db/ActivityDailyChallenges"; +import { ActivityGrowthModel } from "@db/ActivityGrowth"; +import { ActivityGrowthFundModel } from "@db/ActivityGrowthFund"; +import { ActivityRefreshTaskModel } from "@db/ActivityRefreshTask"; +import { ActivityThirtyDaysModel } from "@db/ActivityThirtyDays"; +import { ActivityTreasureHuntTaskModel } from "@db/ActivityTreasureHuntTask"; +import { RoleModel, RoleType } from "@db/Role"; +import { UserTaskRecModel } from "@db/UserTaskRec"; +import { GrowthFundData } from "@domain/activityField/growthFundField"; +import { RefreshTaskData } from "@domain/activityField/refreshTaskField"; +import { SevenDaysData } from "@domain/activityField/sevenDaysField"; +import { ThirtyDaysData } from "@domain/activityField/thirtyDaysField"; +import { TreasureHuntData } from "@domain/activityField/treasureHuntField"; +import { TaskListReturn, TaskParam, TaskParamInter, UpdateTaskParam } from "@domain/roleField/task"; +import { gameData, getDicBlueprtById, getEquipSuitByHero, getGVGTasksByType } from "@pubUtils/data"; +import { getZeroPoint } from "@pubUtils/timeUtil"; +import { getActivityByServerId } from "../activity/activityService"; +import { getRoleCreateTime, getRoleOnlineInfo, getServerCreateTime } from "../redisService"; +import { getEquipById, getJewelByEquip, isRandSeUnLock } from "../equipService"; +import { sendMessageToUserWithSuc } from "../pushService"; +import { GVGUserTaskModel } from "@db/GVGUserTask"; + +export class CheckTask { + serverId: number; // 区id + roleId: string; // 玩家id + role?: RoleType; + roleCreateTime: number; // 玩家的创建时间 + serverCreateTime: number; // 服务器的创建时间 + + configId?: number; + leagueCode?: string; + + taskPushMessages: TaskListReturn[] = []; + activityTaskPushMessages = []; + gvgTaskPushMessages = []; + + tasks: CheckSingleTask[] = []; + + constructor(serverId: number, roleId: string) { + this.serverId = serverId; + this.roleId = roleId; + } + + public setParam(taskType: TASK_TYPE, param: TaskParamInter) { + let task = new CheckSingleTask(taskType, this); + task.param.setParam(param); + this.tasks.push(task); + } + + setLeague(configId: number, leagueCode: string) { + this.configId = configId; + this.leagueCode = leagueCode; + } + + public async saveAndPush(sid?: string) { + for(let task of this.tasks) { + await task.check(); + } + await this.pushMessage(sid); + } + + public setRole(role: RoleType) { + this.role = role; + } + + // 用于活动任务:获取服务器开服时间 + async getServerCreateTime() { + if(!this.serverCreateTime) { + this.serverCreateTime = await getServerCreateTime(this.serverId); + } + return this.serverCreateTime; + } + + // 用于活动任务:获取玩家创建时间 + async getRoleCreateTime() { + if(!this.roleCreateTime) { + if(this.role) { + this.roleCreateTime = this.role?.createTime; + } else { + this.roleCreateTime = await getRoleCreateTime(this.roleId); + } + } + if(!this.roleCreateTime) { + let role = await RoleModel.findByRoleId(this.roleId); + this.role = role; + this.roleCreateTime = role.createTime; + } + return this.roleCreateTime; + } + + // 推送 + public async pushMessage(sid?: string) { + let roleId = this.roleId; + if (!sid) { + let onlineUser = await getRoleOnlineInfo(roleId); + sid = onlineUser.sid; + } + if(!!sid) { + if (this.taskPushMessages.length > 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TASK_UPDATE,this.taskPushMessages, sid); + } + if(this.gvgTaskPushMessages.length > 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.GVG_TASK_UPDATE,this.gvgTaskPushMessages, sid); + } + if (this.activityTaskPushMessages.length > 0) { + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.ACTIVITY_TASK_UPDATE, this.activityTaskPushMessages, sid); + } + } + } + +} + +/** + * @class CheckTask + * @classdesc 检查某个玩家任务的达成情况 + */ +export class CheckSingleTask { + serverId: number; // 区id + roleId: string; // 玩家id + taskType: TASK_TYPE; // 任务type + parent: CheckTask; + param: TaskParam; // 检查任务时传入的参数 + + constructor(taskType: TASK_TYPE, parent: CheckTask) { + this.taskType = taskType; + this.parent = parent; + this.serverId = parent.serverId; + this.roleId = parent.roleId; + this.param = new TaskParam(); + } + + private addTaskPushMessage(...param: TaskListReturn[]) { + this.parent.taskPushMessages.push(...param); + } + + private addGVGTaskPushMessage(...param: {id: number, count: number}[]) { + this.parent.gvgTaskPushMessages.push(...param); + } + + private addActivityTaskPushMessage(...param: any[]) { + this.parent.activityTaskPushMessages.push(...param); + } + + private getServerCreateTime() { + return this.parent.getServerCreateTime(); + } + + private getRoleCreateTime() { + return this.parent.getRoleCreateTime(); + } + + private getRole() { + return this.parent.role; + } + + /** + * @description 检查任务的主程序 + */ + public async check() { + let { taskType, roleId, serverId } = this; + let serverCreateTime = await this.getServerCreateTime(); + let roleCreateTime = await this.getRoleCreateTime(); + let param = this.param; + let dicTaskTypeDesc = gameData.taskDescByType.get(taskType); + + // 检查一般任务 + let dicTasks = gameData.taskType.get(taskType)||[]; + let groups = new Map(); // 以group做区分 + for (let { id, type, group, taskParam } of dicTasks) { + if (!groups.has(`${type}_${group}`)) { + groups.set(`${type}_${group}`, { type, group, taskParam, taskIds: [] }); + } + groups.get(`${type}_${group}`).taskIds.push(id); + } + for (let [_typeAndGroup, { type, group, taskParam, taskIds }] of groups) { + + let taskUpdateParam = await this.checkIsMatch(taskParam, async () => { + let data = await UserTaskRecModel.findByRoleAndGroup(roleId, type, taskType, group); + return data?.records ?? []; + }); + if (taskUpdateParam) { + let rec = await UserTaskRecModel.setOrIncTask(roleId, type, taskType, group, taskUpdateParam); + if (!rec) continue; + + for (let id of taskIds) { + if (rec.received && rec.received.includes(id)) continue; // 已领取,不再推送 + let received = rec.received || []; + this.addTaskPushMessage({ type, id: id, count: rec.count, received: received.includes(id) }); + } + + } + } + + // 联军任务 + let dicGVGTasks = getGVGTasksByType(taskType); + for(let { taskId, taskType, taskParam } of dicGVGTasks) { + let taskUpdateParam = await this.checkIsMatch(taskParam, async () => []); + if (taskUpdateParam) { + let rec = await GVGUserTaskModel.setOrIncTask(this.parent.configId, this.parent.leagueCode, roleId, taskType, taskId, taskUpdateParam); + if (!rec) continue; + + if(rec.status == 1) { + this.addGVGTaskPushMessage({ id: taskId, count: rec.count }); + } + } + } + + // 检查活动任务 + let activities = await getActivityByServerId(serverId); + for(let activity of activities) { + let { activityId, type: activityType } = activity; + switch(activityType) { + case ACTIVITY_TYPE.SEVEN_DAY: + case ACTIVITY_TYPE.FOURTEEN_DAY://十四天乐活动 28 + case ACTIVITY_TYPE.COMMON_SEVEN_DAY://通用七天乐活动 29 + { + //成长活动统计 + let playerData = new SevenDaysData(activity, roleCreateTime, serverCreateTime); + let growthTaskArray = playerData.growth.findTaskByType(taskType); // 所有任务 + for (let task of growthTaskArray) { + if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !playerData.canShow()) { + continue; + } + let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { + let data = await ActivityGrowthModel.findDataByCellIndex(serverId, activityId, roleId, task.dayIndex, task.cellIndex); + return data?.records ?? []; + }); + if(taskUpdateParam) { + let rec = await ActivityGrowthModel.setOrIncTask(serverId, activityId, roleId, task.dayIndex, task.cellIndex, taskType, taskUpdateParam); + if(!rec) continue; + this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId, activityType: "growth" }); + } + } + //今日挑战统计 + let dailyChallengeTaskArray = playerData.dailyChallenge.findTaskByType(taskType); + for (let task of dailyChallengeTaskArray) { + if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && task.dayIndex != playerData.today()) { + continue; + } else if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.SUM && task.dayIndex < playerData.today()) { + continue; + } + let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { + let data = await ActivityDailyChallengesModel.findDataByCellIndex(serverId, activityId, roleId, task.dayIndex, task.cellIndex); + return data?.records ?? []; + }); + if(taskUpdateParam) { + let rec = await ActivityDailyChallengesModel.setOrIncTask(serverId, activityId, roleId, task.dayIndex, task.cellIndex, taskType, taskUpdateParam); + if(!rec) continue; + this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId, activityType: "daily" }); + } + } + break; + } + case ACTIVITY_TYPE.REFRESH_TASK: + { + // 通用的刷新任务 + let taskActivity = new RefreshTaskData(activity, roleCreateTime, serverCreateTime); + let taskArray = taskActivity.findTaskByType(taskType); + for (let task of taskArray) { + if(!taskActivity.canShow()) { + continue; + } + let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { + let data = await ActivityRefreshTaskModel.findDataById(serverId, activityId, roleId, taskActivity.roundIndex, task.pageIndex, task.id, task.getRefTime()); + return data?.records ?? []; + }); + if(taskUpdateParam) { + let rec = await ActivityRefreshTaskModel.setOrIncTask(serverId, activityId, roleId, taskActivity.roundIndex, task.pageIndex, task.id, task.getRefTime(), taskType, taskUpdateParam); + if(!rec) continue; + this.addActivityTaskPushMessage({...task, totalCount: rec.totalCount, receiveRewardCount: rec.receiveRewardCount||0, activityId }); + } + } + break; + } + case ACTIVITY_TYPE.TREASURE_HUNT: + { + // 寻宝奇兵任务 + let playerData = new TreasureHuntData(activity, roleCreateTime, serverCreateTime); + let taskArray = playerData.tasks.findItemByTaskType(taskType); + for (let task of taskArray) { + if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !playerData.canShow()) { + continue; + } + let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { + let data = await ActivityTreasureHuntTaskModel.findDataByCellIndex(serverId, activityId, roleId, playerData.roundIndex, task.cellIndex); + return data?.records ?? []; + }); + if(taskUpdateParam) { + let rec = await ActivityTreasureHuntTaskModel.setOrIncTask(serverId, activityId, roleId, playerData.roundIndex, task.cellIndex, taskType, taskUpdateParam); + if(!rec) continue; + this.addActivityTaskPushMessage({ ...task, isReceive: rec.receiveRewardCount > 0? true: false, totalCount: rec.totalCount, activityId }); + } + } + break; + } + case ACTIVITY_TYPE.THIRTY_DAYS: + { + //30天任务统计 + let thirtyDaysActivity = new ThirtyDaysData(activity, roleCreateTime, serverCreateTime); + let taskArray = thirtyDaysActivity.findTaskByType(taskType); + for (let task of taskArray) { + if(dicTaskTypeDesc.sumType == TASK_SUM_TYPE.DO && !thirtyDaysActivity.canShow()) { + continue; + } + let taskUpdateParam = await this.checkIsMatch(task.taskParamArray, async () => { + let data = await ActivityThirtyDaysModel.findDataByCellIndex(serverId, thirtyDaysActivity.activityId, roleId, task.pageIndex, task.cellIndex, task.tab); + return data?.records ?? []; + }); + if(taskUpdateParam) { + let rec = await ActivityThirtyDaysModel.setOrIncTask(serverId, thirtyDaysActivity.activityId, roleId, task.pageIndex, task.cellIndex, task.tab, taskType, taskUpdateParam); + if(!rec) continue; + task.setPlayerRecord(rec); + this.addActivityTaskPushMessage({ ...task, totalCount: rec.totalCount, activityId }); + } + } + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN: + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_VIP: + { + //主线成长基金 + if(taskType != TASK_TYPE.BATTLE_MAIN) continue; + let dicWar = gameData.war.get(param.warId); + if(!dicWar || dicWar.warType != WAR_TYPE.NORMAL) continue; + await this.checkFundAcctivityTask(activity, param.warId); + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_TOWER: + case ACTIVITY_TYPE.GROWTH_FUND_TOWER_VIP: + { + //镇念塔成长基金 + if(taskType != TASK_TYPE.BATTLE_TOWER_LV) continue; + await this.checkFundAcctivityTask(activity, param.towerLv); + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE: + case ACTIVITY_TYPE.GROWTH_FUND_MAIN_ELITE_VIP: + { + //精英成长基金 + if(taskType != TASK_TYPE.BATTLE_MAIN_ELITE) continue; + let dicWar = gameData.war.get(param.warId); + if(!dicWar || dicWar.warType != WAR_TYPE.MAIN_ELITE) continue; + await this.checkFundAcctivityTask(activity, param.warId); + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE: + case ACTIVITY_TYPE.GROWTH_FUND_ROUGE_VIP: + { + //学宫成长基金 + if (taskType != TASK_TYPE.FUND_ROUGE) continue; + await this.checkFundAcctivityTask(activity, param.rougeId); + break; + } + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR: + case ACTIVITY_TYPE.GROWTH_FUND_AUTHOR_VIP: + { + //列传成长基金 + if (taskType != TASK_TYPE.FUND_AUTHOR) continue; + await this.checkFundAcctivityTask(activity, param.authorProgress); + break; + } + } + } + + } + + private async checkFundAcctivityTask(activity: ActivityModelType, unlockParam: number) { + let serverCreateTime = await this.getServerCreateTime(); + let roleCreateTime = await this.getRoleCreateTime(); + let growthFundActivity = new GrowthFundData(activity, roleCreateTime, serverCreateTime); + let playerRecords = await ActivityGrowthFundModel.findData(activity.activityId, this.roleId); + growthFundActivity.setPlayerRecords(playerRecords); + if (growthFundActivity.isVipActivity()) {//vip高阶需要购买 + let buyRecords = await ActivityBuyRecordsModel.findRecordsByActivityId(activity.activityId, this.roleId); + growthFundActivity.initBuyRecords(buyRecords); + } + let taskArray = growthFundActivity.unLockItem(unlockParam); + //推送 + this.addActivityTaskPushMessage(...taskArray); + } + + public async checkIsMatch(dicTaskParam: number[], getRecord: () => Promise) { + let param = this.param; + let result: UpdateTaskParam = null; + + if(this.param.debugInfo) { + return { set: this.param.debugInfo.condition } + } + + switch(this.taskType) { + case TASK_TYPE.LOGIN_SUM: // 1. 累计登录 x 天 + { + let records = await getRecord(); + let today = `${getZeroPoint()}`; + if (records.indexOf(today) == -1) { + result = { inc: 1, records: [...records, today] } + } + break; + } + case TASK_TYPE.LOGIN_SERIES: // 2. 连续登录 x 天 + { + let records = await getRecord(); + let today = `${getZeroPoint()}`; + let yesterday = `${getZeroPoint() - 24 * 60 * 60}` + if (records.indexOf(today) == -1) { + if (records.indexOf(yesterday) == -1) { + result = { set: 1, records: [...records, today] } + } else { + result = { inc: 1, records: [...records, today] } + } + } + break; + } + case TASK_TYPE.ROLE_LV: // 3. 主公达x级 + { + let { lv, oldLv } = param; + if(lv > oldLv) { + result = { set: lv } + } + break; + } + case TASK_TYPE.GACHA: // 4. 招募x次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.HERO_NUM: // 5. 拥有x名武将 + { + let { heroNum } = param; + result = { inc: heroNum }; + break; + } + case TASK_TYPE.HERO_STAR_UP: // 6. x名武将升星x次 + { + let { hero } = param; + let records = await getRecord(); + let count = 0, index = -1; + for(let i = 0; i < records.length; i++) { + let arr = records[i].split('_'); + if(parseInt(arr[0]) == hero.hid) { + count = parseInt(arr[1]); + index = i; + break; + } + } + if(index == -1) { + records.push(`${hero.hid}_${count + 1}`); + } else { + records[index] = `${hero.hid}_${count + 1}`; + } + if(count + 1 >= dicTaskParam[1]) { + result = { inc: 1, records } + } else { + result = { records } + } + break; + } + case TASK_TYPE.HERO_QUALITY: // 7. 拥有x名初始x品质武将 + { + let { heroes } = param; + let num = 0; + for(let { hid } of heroes) { + let dicHero = gameData.hero.get(hid); + if(dicHero.quality == dicTaskParam[1] ) { + num ++; + } + } + result = { inc: num }; + break; + } + case TASK_TYPE.HERO_QUALITY_STAR_UP: // 8. x名x品质升至x星 + { + let { heroes, hero, oldStar, oldColorStar } = param; + if(param.heroes) { // 创建武将的时候 + let records = await getRecord(); + let num = 0; + for(let { hid, star, colorStar } of heroes) { + let dicHero = gameData.hero.get(hid); + if(dicHero.quality == dicTaskParam[1] && (star + colorStar) == dicTaskParam[2] && records.indexOf(`${hid}`) == -1) { + records.push(`${hid}`); + num ++; + } + } + result = { records, inc: num }; + } else { // 武将升星的时候 + let hid = hero.hid; + let dicHero = gameData.hero.get(hid); + if(dicHero.quality == dicTaskParam[1] && (hero.star + hero.colorStar) >= dicTaskParam[2] && (oldStar + oldColorStar) < dicTaskParam[2] ) { + let records = await getRecord(); + if(records.indexOf(`${hid}`) == -1) { + records.push(`${hid}`); + result = { records, inc: 1 } + } + } + } + break; + } + case TASK_TYPE.HERO_LV: // 9. x名武将升至x级 + { + let { heroes, hero, oldLv } = param; + if(heroes) { // 创建武将的时候 + let num = 0; + for(let { lv } of heroes) { + if(lv >= dicTaskParam[1]) { + num ++; + } + } + result = { inc: num }; + } else { // 武将升级的时候 + if(hero.lv >= dicTaskParam[1] && oldLv < dicTaskParam[1]) { + result = { inc: 1 } + } + } + break; + } + case TASK_TYPE.HERO_TRAIN: // 10. x名武将各训练x次 + { + let { hero, trainCount } = param; + let records = await getRecord(); + let count = 0, index = -1; + for(let i = 0; i < records.length; i++) { + let arr = records[i].split('_'); + if(parseInt(arr[0]) == hero.hid) { + count = parseInt(arr[1]); + index = i; + break; + } + } + if(index == -1) { + records[index] = `${hero.hid}_${count + trainCount}`; + } else { + records.push(`${hero.hid}_${count + trainCount}`); + } + if( count < dicTaskParam[1] && count + trainCount >= dicTaskParam[1]) { + result = { inc: 1, records } + } else { + result = { records } + } + break; + } + case TASK_TYPE.HERO_QUALITY_UP: // 11. x名武将进行升品 + { + let { hero } = param; + let records = await getRecord(); + if(records.indexOf(`${hero.hid}`) == -1) { + records.push(`${hero.hid}`); + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.HERO_WAKE_UP: // 12.武将觉醒x次 + { + let { hero, oldColorStar } = param; + if(oldColorStar == 0 && hero.colorStar > 0) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.HERO_TRAIN_SUM: // 13. 训练x次 + { + let { trainCount } = param; + result = { inc: trainCount }; + break; + } + case TASK_TYPE.HERO_STAGE_UP: // 14. x名武将各兵种进阶x次 + { + let { hero, stageUpCnt } = param; + let records = await getRecord(); + let count = 0, index = -1; + for(let i = 0; i < records.length; i++) { + let arr = records[i].split('_'); + if(parseInt(arr[0]) == hero.hid) { + count = parseInt(arr[1]); + index = i; + break; + } + } + if(index == -1) { + records.push(`${hero.hid}_${count + stageUpCnt}`); + } else { + records[index] = `${hero.hid}_${count + stageUpCnt}`; + } + if( count < dicTaskParam[1] && count + stageUpCnt >= dicTaskParam[1]) { + result = { inc: 1, records } + } else { + result = { records } + } + break; + } + // case TASK_TYPE.HERO_FAVOUR_LV: // 15. + // { + // let { hero, oldFavourLv } = param; + // if(dicTaskParam[1] > oldFavourLv && dicTaskParam[1] <= hero.favourLv) { + // result = { inc: 1 }; + // } + // break; + // } + case TASK_TYPE.HERO_CONNECT: // 16. 激活x次 x星 武将羁绊 + { + let { shipId, connections, oldConnections } = param; + let oldConnectLv = oldConnections.find(cur => cur.shipId == shipId)?.level||0; + let connectLv = connections.find(cur => cur.shipId == shipId)?.level||0; + if(dicTaskParam[1] <= connectLv && dicTaskParam[1] > oldConnectLv) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.ROLE_SCHOOL_UNLOCK: // 17. 百家学宫解锁x个安置位 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.ROLE_SCHOOL_PUT_HERO: // 18. 百家学宫放置x个武将 + { + let records = await getRecord(); + let { hid } = param; + if(records.indexOf(`${hid}`) == -1) { + records.push(`${hid}`) + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.ROLE_TITLE: // 19. 爵位升至x + { + let { title, oldTitle } = param; + if(title > oldTitle) { + result = { set: title }; + } + break; + } + case TASK_TYPE.ROLE_TERAPH_STRENGTHEN: // 20. 神像强化x次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.ROLE_SCROLL_ACTIVE: // 21. 名将谱激活x武将 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.FRIEND_NUM: // 34. 拥有x名好友 + { + let role = this.getRole(); + result = { set: role.friendCnt }; + break; + } + case TASK_TYPE.FRIEND_SEND_HEART: // 35. 赠送x次友情点 + { + let { count } = param; + if(count > 0) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.CHAT: // 36. 聊天频道发言x次 + { + let { chatType, count = 1 } = param; + if (dicTaskParam[0] == 0 || dicTaskParam[0] == chatType) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_COST_AP: // 37. 消耗体力 + { + let { count } = param; + if(count > 0) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_WITH_HERO: // 38. 使用hId武将挑战x关卡x次 + { + let { warId, battleHeroes } = param; + if(this.checkIdList(dicTaskParam, 2, warId) && battleHeroes.indexOf(dicTaskParam[0]) != -1) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.BATTLE_MAIN: // 39. 主线通关第x关 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.NORMAL && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_MAIN_SWEEP: // 40. 主线扫荡X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.NORMAL) { + result = { inc: count } + } + break; + } + case TASK_TYPE.BATTLE_EVENT: // 41. 奇遇(答题/解救百姓/劫匪) x 次 + { + let { eventType } = param; + if(dicTaskParam[0] == 0|| dicTaskParam[0] == eventType) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.BATTLE_DAILY_STAR: // 42. 每日x星通关 x 次 + { + let { warId, battleStar, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0|| battleStar >= dicTaskParam[0]) && this.checkIdList(dicTaskParam, 2, warId)) { + result = { inc: count||1 } + } + break; + } + case TASK_TYPE.BATTLE_DAILY: // 43. 每日关卡挑战x次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if(dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0 || dicTaskParam[0] == dicWar.dailyType)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_DUNGEON: // 44. 参与秘境x次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if(dicWar.warType == WAR_TYPE.MYSTERY) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_DUNGEON_WAR: // 45. 秘境通关x关x难度 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if ((dicWar.warType == WAR_TYPE.MYSTERY) && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_TOWER_LV: // 46. 通关镇念塔x层 + { + let { towerLv } = param; + result = { set: towerLv }; + break; + } + case TASK_TYPE.BATTLE_TOWER: // 47. 通关镇念塔x次 + { + let { warId, count = 1, skipTower } = param; + let dicWar = gameData.war.get(warId); + // console.log('##### skipTower', skipTower) + if (skipTower || dicWar.warType == WAR_TYPE.TOWER) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_VESTIGE: // 48. 挑战遗迹x次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.VESTIGE && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_EXPEDITION: // 49. 开启远征x次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.EXPEDITION) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_EXPEDITION_BOX: // 50. 领取x次远征 x宝箱 + { + let { point } = param; + if(dicTaskParam[1] == 0 || dicTaskParam[1] == point) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.COM_BATTLE_CREATE_TEAM: // 51. 寻宝招募队友x次 + { + result = { inc: 1 }; + break; + } + + case TASK_TYPE.COM_BATTLE_ASSIST_TEAM: // 53. 协助寻宝x次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.COM_BATTLE: // 54. 组队寻宝 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.PVP: // 57. pvp挑战 x 次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.PVP_WIN: // 58. pvp胜利 x 次 + { + let { isSuccess } = param; + if(isSuccess) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.PVP_RECEIVE_BOX: // 59. 领取x次pvp巅峰之路宝箱 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.PVP_WIN_SERIES: // 60. pvp连胜x次 + { + let { isSuccess } = param; + if (isSuccess) { + result = { inc: 1 }; + } else { + result = { set: 0 }; + } + break; + } + case TASK_TYPE.PVP_HERO_SCORE: // 61. pvp拥有x个积分达到x的武将 + { + let { heroScores } = param; + let count = 0; + for (let { score } of heroScores) { + if (score >= dicTaskParam[0]) { + count++; + } + } + if (count > 0) { + result = { set: count }; + } + break; + + } + case TASK_TYPE.PVP_RANK: // 62. pvp赛季排名达到 x 名 + { + let { pvpRank } = param; + + let records = await getRecord(); + let oldPvpRank = parseInt(records[0]); + if(isNaN(oldPvpRank)) oldPvpRank = 0; + if(pvpRank > oldPvpRank) { + records[0] = `${pvpRank}`; + result = { set: pvpRank, records } + } + break; + } + case TASK_TYPE.GUILD_JOB: // 63. 军团官职晋升为x + { + let { guildJob } = param; + + let records = await getRecord(); + let oldGuildJob = parseInt(records[0]); + if(isNaN(oldGuildJob)) oldGuildJob = 0; + if(guildJob > oldGuildJob) { + records[0] = `${guildJob}`; + result = { set: guildJob, records } + } + break; + } + case TASK_TYPE.GUILD_DONATE: // 64. 军团捐献x次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.GUILD_RECEIVE_BOX: //65. 领取x次军团活跃宝箱 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.GUILD_ASSIST_REFINE: // 67. 助力炼器堂研发加速x次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.GUILD_TRAIN_SUCESS: // 68. 练兵场军团成功压制x次 + { + let { isSuccess } = param; + if(isSuccess) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.GUILD_BOSS: // 69. 演武台军团挑战x次boss + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.GUILD_TRAIN: // 70. 挑战练兵场X次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.GUILD_ACTIVITY: // 71. 参与 xxx 军团活动 x 次 + { + let { aid } = param; + if (dicTaskParam[0] == 0 || aid == dicTaskParam[0]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.GUILD_JOIN: // 72. 加入军团 + { + result = { set: 1 }; + break; + } + case TASK_TYPE.BATTLE_MAIN_ELITE: // 73. 精英通关第x关 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.MAIN_ELITE && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.HERO_QUALITY_TO_QUALITY_COUNT: // 74. x名初始x品质武将升至X品质 + { + let { hero } = param; + let dicHero = gameData.hero.get(hero.hid); + if(dicHero.quality == dicTaskParam[1] && hero.quality == dicTaskParam[2]) { + let records = await getRecord(); + if(records.indexOf(`${hero.hid}`) == -1) { + records.push(`${hero.hid}`) + result = { records, inc: 1 }; + } + } + break; + } + case TASK_TYPE.HERO_QUALITY_WAKE_UP_COUNT: // 75. x名初始x品质武将觉醒 + { + let { hero, oldColorStar } = param; + let dicHero = gameData.hero.get(hero.hid); + if(dicTaskParam[1] == dicHero.quality && oldColorStar == 0 && hero.colorStar > 0) { + let records = await getRecord(); + if(records.indexOf(`${hero.hid}`) == -1) { + records.push(`${hero.hid}`) + result = { records, inc: 1 }; + } + } + break; + } + case TASK_TYPE.HERO_WAKE_UP_STAR_UP_COUNT: // 76. x名武将觉醒后升至x星 + { + let { hero, oldColorStar } = param; + if(dicTaskParam[1] > oldColorStar && hero.colorStar >= dicTaskParam[1]) { + let records = await getRecord(); + if(records.indexOf(`${hero.hid}`) == -1) { + records.push(`${hero.hid}`) + result = { records, inc: 1 }; + } + } + break; + } + case TASK_TYPE.GUILD_TRAIN_COUNT: // 79. 练兵场通关x关x次 + { + let { warId, isComplete } = param; + if(isComplete && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.HERO_UNLOCK: // 80. 名将谱x阵营全部激活 + { + let { hero } = param; + let dicHero = gameData.hero.get(hero.hid); + if(dicHero && dicHero.camp == dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.GACHA_QUALITY_COUNT: // 81. 抽到*次品质*武将 + { + let { heroes } = param; + let count = 0; + for (let hero of heroes) { + let dicHero = gameData.hero.get(hero.hid); + if(dicHero.quality == dicTaskParam[1]) count++; + } + if(count > 0) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.ROLE_TERAPH_STAGE_UP: // 82. 神像进阶 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.HERO_WAKE_UP_COUNT: // 84. x名武将觉醒 + { + let { hero, oldColorStar } = param; + if(oldColorStar == 0 && hero.colorStar > 0) { + let records = await getRecord(); + if(records.indexOf(`${hero.hid}`) == -1) { + records.push(`${hero.hid}`); + result = { records, inc: 1 }; + } + } + break; + } + case TASK_TYPE.ACTIVITY_RMB: // 86. 某个活动充值*元 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.EQUIP_LV_TO: // 87. x件装备强化至x级 + { + let { oldEplace, newEplace, ePlaceIds } = param; + let addCount = 0; + for(let eplaceId of ePlaceIds) { + let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, eplaceId); + // console.log('##### oldEquip', oldEquip.lv, newEquip.lv, dicTaskParam[1]) + if(oldEquip.lv < dicTaskParam[1] && newEquip.lv >= dicTaskParam[1]) { + addCount += 1; + } + } + if(addCount != 0) { + result = { inc: addCount }; + } + break; + } + case TASK_TYPE.EQUIP_PUT_JEWEL: // 88. x件装备镶嵌X阶天晶石 + { + let { hid, newEquip, jewels } = param; + if(!newEquip) break; + + let jewel = getJewelByEquip(newEquip, jewels); + let lv = gameData.jewel.get(jewel?.id)?.lv || 0; + if(lv < dicTaskParam[1]) break; + + let records = await getRecord(); + if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { + records.push(`${hid}_${newEquip.id}`) + result = { records, inc: 1 }; + } + + break; + } + case TASK_TYPE.EQUIP_PUT_STONE: // 89. x件装备镶嵌X个地玉石 + { + let { hid, newEquip } = param; + if(!newEquip) break; + let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; + if(newStoneCnt < dicTaskParam[1]) break; + + let records = await getRecord(); + if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { + records.push(`${hid}_${newEquip.id}`); + result = { records, inc: 1 }; + } + + break; + } + case TASK_TYPE.EQUIP_STAR_UP_TO: // 90. x件装备升至X星 + { + let { oldEquip, newEquip } = param; + let oldStar = oldEquip?.star||0; + let star = newEquip?.star||0 + if(oldStar < dicTaskParam[1] && star >= dicTaskParam[1]) { + result = { inc: 1 }; + }; + break; + } + case TASK_TYPE.EQUIP_STAR_UP_CNT: // 91. x件装备升星X次 + { + let { hid, ePlaceId, count: paramCount } = param; + let records = await getRecord(); + let count = 0, index = -1; + for(let i = 0; i < records.length; i++) { + let arr = records[i].split('_'); + if(parseInt(arr[0]) == hid && parseInt(arr[1]) == ePlaceId) { + count = parseInt(arr[2]); + index = i; + break; + } + } + + if(index == -1) { + records.push(`${hid}_${ePlaceId}_${count + paramCount}`); + } else { + records[index] = `${hid}_${ePlaceId}_${count + paramCount}`; + } + if(count < dicTaskParam[1] && count + paramCount >= dicTaskParam[1]) { + result = { inc: 1, records } + } else { + result = { records } + } + break; + } + case TASK_TYPE.EQUIP_SUIT_SEID_NUM: // 92. x名武将激活X条套装属性 + { + let { oldEplace, newEplace, skinId } = param; + let dicEquipSuit = getEquipSuitByHero(skinId); + let oldSuitStars: number[] = [], newSuitStars: number[] = []; + for(let equipId of dicEquipSuit.equips) { + let oldEquip = oldEplace.find(cur => cur.equipId == equipId); + oldSuitStars.push(oldEquip? oldEquip.star: 0); + let newEquip = newEplace.find(cur => cur.equipId == equipId); + newSuitStars.push(newEquip? newEquip.star: 0); + } + let oldStar = Math.min(...oldSuitStars); + let newStar = Math.min(...newSuitStars); + let oldCount = 0, count = 0; + for(let { star } of dicEquipSuit.effect) { + if(oldStar >= star) oldCount++; + if(newStar >= star) count++; + } + if(oldCount < dicTaskParam[1] && count >= dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_QUALITY_UP: // 93. x件装备进行升品 + { + let { hid, ePlaceId } = param; + let records = await getRecord(); + if(records.indexOf(`${hid}_${ePlaceId}`) == -1) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_QUALITY_UP_CNT: // 94. 装备升品X次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.EQUIP_QUALITY_UP_TO: // 95. X件装备升品至Y品质 + { + let { oldEquip, newEquip } = param; + let oldQuality = oldEquip?.quality||0; + let quality = newEquip?.quality||0; + if(oldQuality < dicTaskParam[1] && quality >= dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_COMPOSE: // 96. 装备X件装备 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.EQUIP_COMPOSE_CNT: // 97. x名武将各装备x件装备 + { + let { oldEplace, newEplace } = param; + if(oldEplace.length < dicTaskParam[1] && newEplace.length >= dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_LV_UP: // 98. 装备强化X次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.EQUIP_PUT_JEWEL_CNT: // 99. X件装备镶嵌天晶 + { + let { newEquip } = param; + if(!newEquip || !newEquip.jewel) break; + let records = await getRecord(); + if(records.indexOf(`${newEquip.jewel}`) == -1) { + records.push(`${newEquip.jewel}`); + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_PUT_STONE_CNT: // 100. X件装备镶嵌地玉 + { + let { hid, newEquip } = param; + if(!newEquip) break; + let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; + if(newStoneCnt <= 0) break; + let records = await getRecord(); + + if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { + records.push(`${hid}_${newEquip.id}`); + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_STONE_CNT: // 101. 镶嵌X个地玉 + { + let { oldEquip, newEquip } = param; + let oldStoneCnt = oldEquip.stones.filter(cur => cur.stone != 0).length; + let newStoneCnt = newEquip.stones.filter(cur => cur.stone != 0).length; + result = { inc: newStoneCnt - oldStoneCnt }; + break; + } + case TASK_TYPE.EQUIP_STONE_CNT_LV: // 102. X件装备镶嵌X个大于等于X阶地玉 + { + let { hid, newEquip } = param; + if(!newEquip) break; + let newStoneLvs = newEquip.stones.map(cur => { + let dicStone = gameData.stone.get(cur.stone); + return dicStone?dicStone.lv: 0; + }); + let newCount = newStoneLvs.filter(lv => lv >= dicTaskParam[2]).length; + if(newCount < dicTaskParam[1]) break; + + let records = await getRecord(); + if(records.indexOf(`${hid}_${newEquip.id}`) == -1) { + records.push(`${hid}_${newEquip.id}`); + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT: // 103.X个天晶的Y条特性词条被激活 + { + let { newEquip, jewels } = param; + let newJewel = getJewelByEquip(newEquip, jewels); + if(!newJewel) break; + + let newRandSe = newJewel?.randSe||[]; + let newUnlockSeCnt = newRandSe.filter(se => { + return isRandSeUnLock(newJewel.id, se.id, newEquip.stones); + }).length; + + if(newUnlockSeCnt < dicTaskParam[1]) break; + let records = await getRecord(); + if(records.indexOf(`${newJewel.seqId}`) == -1) { + records.push(`${newJewel.seqId}`); + result = { records, inc: 1 }; + } + break; + } + case TASK_TYPE.STONE_COMPOSE: // 104. 地玉合成X次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.JEWEL_RESET: // 105. 天晶洗炼X次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.JEWEL_QUENCH: // 106. 天晶淬炼X次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.JEWEL_QUENCH_SUCCESS: // 107. 天晶成功淬炼X次 + { + let { isSuccess } = param; + if(isSuccess) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.COM_BATTLE_LV: // 108. 寻宝x品阶x次 + { + let { gid } = param; + let dicJewel = getDicBlueprtById(gid); + if(dicTaskParam[0] == dicJewel.lv) { + result = { inc: 1 }; + } + break + } + case TASK_TYPE.GUILD_REFINE: // 109. 炼器堂兑换X品阶天晶X次 + { + let { quality, count } = param; + if(dicTaskParam[0] == quality) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.EQUIP_STAR_UP_CNT_SUM: // 110. 装备总共升星x次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.BATTLE_MAIN_START: // 111. 挑战主线X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.NORMAL) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_TOWER_START: // 112. 挑战镇念塔X次 + { + let { warId, count = 1, skipTower } = param; + let dicWar = gameData.war.get(warId); + if (skipTower || dicWar.warType == WAR_TYPE.TOWER ) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_VESTIGE_START: // 113. 挑战遗迹X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.VESTIGE) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_DAILY_START: // 114. 挑战每日关卡X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if(dicWar.warType == WAR_TYPE.DAILY && (dicTaskParam[0] == 0 || dicTaskParam[0] == dicWar.dailyType)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.COM_BATTLE_CREATE_TEAM_WIN: // 115. 寻宝招募队友x次 + { + result = { inc: 1 }; + break; + } + + case TASK_TYPE.COM_BATTLE_ASSIST_TEAM_WIN: // 116. 协助寻宝x次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.COM_BATTLE_WIN: // 117. 组队寻宝 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.BATTLE_EXPEDITION_START: // 118. 远征挑战X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.EXPEDITION) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.BATTLE_DUNGEON_START: // 119. 秘境挑战X次 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if(dicWar.warType == WAR_TYPE.MYSTERY) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.GUILD_GOLD_DONATE: // 120. 军团元宝捐献x次 + { + result = { inc: 1 }; + break; + } + case TASK_TYPE.LADDER_CNT: // 121. 名将擂台挑战x次 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.LADDER_SUCCESS_CNT: // 122. 名将擂台挑战胜利x次 + { + let { isSuccess, count } = param; + if(isSuccess) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.LADDER_RANK: // 123. 名将擂台排名 + { + let { oldLadderRank, ladderRank } = param; + if(ladderRank < oldLadderRank && dicTaskParam[0] >= ladderRank) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.CONNECT_ONE_HERO_MAX_LV: // 124. 单个武将其中最高等级的羁绊达X级 + { + let { connections } = param; + let records = await getRecord(); + let oldLv = records.length > 0? parseInt(records[0]): 0; + + let maxLv = Math.max(...connections.map(cur => cur.level))||0; + // console.log('##### TASK_TYPE.CONNECT_ONE_HERO_MAX_LV', oldLv, maxLv ) + if(oldLv < maxLv) { + result = { set: maxLv, records: [`${maxLv}`] }; + } + break; + } + case TASK_TYPE.CONNECT_ONE_HERO_SUM_LV: // 125. 单个武将3条羁绊总共提升X级 + { + let { connections } = param; + let records = await getRecord(); + let oldLv = records.length > 0? parseInt(records[0]): 0; + let sumLv = connections.reduce((pre, cur) => pre + cur.level, 0); + if(oldLv < sumLv) { + result = { set: sumLv, records: [`${sumLv}`] }; + } + break; + } + case TASK_TYPE.ARTIFACT_LV: // 127. 强化X件宝物至X级 + { + let { artifacts } = param; + let records = await getRecord(); + for(let { seqId, lv, hid } of artifacts) { + if(hid > 0 && lv >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) { + records.push(`${seqId}`); + } + } + result = { records, set: records.length }; + break; + } + case TASK_TYPE.ARTIFACT_QUALITY_EQUIP: // 128. 穿戴X件品质为X的宝物 + { + let { artifacts } = param; + let records = await getRecord(); + for(let { seqId, quality, hid } of artifacts) { + if(hid > 0 && quality >= dicTaskParam[1] && records.indexOf(`${seqId}`) == -1) { + records.push(`${seqId}`); + } + } + result = { records, set: records.length }; + break; + } + case TASK_TYPE.ARTIFACT_COMPOSE: // 129. 合成X次宝物 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.STAR_UP_SUM: // 130. 升星总和 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.BATTLE_BRANCH_ELITE: // 131. 主线梦魇支线 + { + let { warId, count } = param; + let dicWar = gameData.war.get(warId); + if (dicWar.warType == WAR_TYPE.BRANCH_ELITE && this.checkIdList(dicTaskParam, 0, warId)) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.GVG_FARM: // 132. 农庄种植/矿山采集/木堆砍柴 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.GVG_VESTIGE: // 133. 中原遗迹挑战 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.GVG_TECH: // 134. 千机阁捐献 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.MINI_GAME_SHOOT: // 135. 单局射箭获得X分 + case TASK_TYPE.MINI_GAME_EAT_ZONGZI: // 137. 单局接粽子获得X分(大于等于均可) + case TASK_TYPE.MINI_GAME_CATCH_ZONGZI: // 138. 单局吃粽子获得X分(大于等于均可) + { + let { score } = param; + if(score >= dicTaskParam[0]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.MINI_GAME_ERASE: // 136. 单局翻牌不超出X步 + { + let { step } = param; + if(step <= dicTaskParam[0]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.MINI_GAME_SCORE: // 139. 小游戏超过X分 + { + let { gameType, score } = param; + if(gameType == dicTaskParam[0] && score >= dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.MINI_GAME_STEP: // 140. 小游戏小于X步 + { + let { gameType, step } = param; + if(gameType == dicTaskParam[0] && step <= dicTaskParam[1]) { + result = { inc: 1 }; + } + break; + } + case TASK_TYPE.FUND_ROUGE: //143 通关XX试炼几 + { + let { rougeId, count } = param; + if (rougeId == dicTaskParam[0]) { + result = { inc: count }; + } + break; + } + case TASK_TYPE.FUND_AUTHOR: //144 列传收集进度 + { + let { authorProgress } = param; + result = { set: authorProgress }; + break; + } + case TASK_TYPE.ROUGE_GET_COIN: // 145. 学宫积累x个试炼币 + { + let { addCoin } = param; + result = { inc: addCoin } + break; + } + case TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT: // 146.流派卡收集 + { + let records = await getRecord(); + let { authorType, cardType, cardIds } = param; + if (authorType == dicTaskParam[0] && cardType == dicTaskParam[1]) { + for (let cardId of cardIds) { + if (records.indexOf(`${cardId}`) == -1) { + records.push(`${cardId}`); + } + } + result = { records, set: records.length }; + } + break;; + } + case TASK_TYPE.ROUGE_HOLY_COLLECT: // 147.圣物卡收集 + { + let records = await getRecord(); + let { cardIds } = param; + for (let cardId of cardIds) { + if (records.indexOf(`${cardId}`) == -1) { + records.push(`${cardId}`); + } + } + result = { records, set: records.length }; + + break; + } + case TASK_TYPE.ROUGE_EVENT_COLLECT: // 148.事件收集 + { + let records = await getRecord(); + let { eventGroups } = param; + for (let eventGroup of eventGroups){ + records.push(`${eventGroup}`); + } + result = { records, set: records.length }; + break; + } + case TASK_TYPE.ROUGE_TECH_OPEN: // 149.法阵开启数量 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.ROUGE_GAME_COUNT: // 150.肉鸽次数 + { + let { count } = param; + result = { inc: count }; + break; + } + case TASK_TYPE.ROUGE_BOSS_PASS: // 151.试炼通过boss关 + { + let { authorType, count } = param; + if (authorType == dicTaskParam[0]) { + result = { inc: count }; + } + break; + } + } + return result + } + + private checkIdList(taskParam: number[], index: number, id: number) { + let count = taskParam[index]; + if (!count) return false; + let idList = taskParam.slice(index + 1, index + 1 + count); + return idList.indexOf(id) != -1; + } + +} diff --git a/game-server/app/services/task/taskService.ts b/game-server/app/services/task/taskService.ts index f4cfbe6db..cdb4438f8 100644 --- a/game-server/app/services/task/taskService.ts +++ b/game-server/app/services/task/taskService.ts @@ -1,494 +1,494 @@ -import { RoleModel, RoleType } from '../../db/Role'; -import { pinus, FrontendOrBackendSession } from 'pinus'; -import { resResult, shouldRefresh } from '../../pubUtils/util'; -import { STATUS, TASK_TYPE, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, WAR_TYPE, PUSH_ROUTE, POP_UP_SHOP_CONDITION_TYPE } from '../../consts'; -import { TaskParamInter, TaskListReturn } from '../../domain/roleField/task'; -import { Connect, EPlace, HeroType } from '../../db/Hero'; -import { HeroScores } from '../../db/PvpHistoryOpp'; -import { ItemInter, RewardInter } from '../../pubUtils/interface'; -import { UserTaskModel, UserTaskType } from '../../db/UserTask'; -import { UserTaskRecModel } from '../../db/UserTaskRec'; -import { UserTaskHistoryModel } from '../../db/UserTaskHistory'; -import { gameData } from '../../pubUtils/data'; -import { getSeconds, getZeroPointD } from '../../pubUtils/timeUtil'; -import { RoleStatus } from '../../db/ComBattleTeam'; -import { getActivities } from '../activity/activityService'; -import { CheckTask } from './taskObj'; -import { getEquipById } from '../equipService'; -import { JewelType } from '../../db/Jewel'; -import { checkPopUpCondition, checkPopUpConditionInCreateHero, checkPopUpConditionInEntry } from '../activity/popUpShopService'; -import { sendMessageToUserWithSuc } from '../pushService'; -import { getGoldId } from '../role/rewardService'; -import { GachaResultIndb } from '../../domain/activityField/gachaField'; - -export async function checkTaskWithRoles(roleId: string, sid: string, taskType: TASK_TYPE, roles: RoleType[]) { - for (let role of roles) { - if (role) { - await checkTaskWithRole(role.serverId, role.roleId, role.roleId == roleId ? sid : null, taskType, role); - } - } -} - -export async function checkTaskWithRole(serverId: number, roleId: string, sid: string, taskType: TASK_TYPE, role: RoleType, args?: TaskParamInter) { - let task = new CheckTask(serverId, roleId); - task.setRole(role); - task.setParam(taskType, args); - await task.saveAndPush(sid); -} - -export async function checkTask(serverId: number, roleId: string, sid: string, taskType: TASK_TYPE, args?: TaskParamInter) { - let task = new CheckTask(serverId, roleId); - task.setParam(taskType, args); - await task.saveAndPush(sid); -} - -export async function checkGVGTask(serverId: number, roleId: string, sid: string, configId: number, leagueCode: string, taskType: TASK_TYPE, args?: TaskParamInter) { - let task = new CheckTask(serverId, roleId); - task.setParam(taskType, args); - task.setLeague(configId, leagueCode); - await task.saveAndPush(sid); -} - -export async function checkTaskInEntry(serverId: number, roleId: string, sid: string, role: RoleType) { - let task = new CheckTask(serverId, roleId); - task.setRole(role); - task.setParam(TASK_TYPE.LOGIN_SUM, {}); - task.setParam(TASK_TYPE.LOGIN_SERIES, {}); - await task.saveAndPush(sid); - checkPopUpConditionInEntry(serverId, roleId, sid); -} - -export async function checkTaskInCreateHero(serverId: number, roleId: string, sid: string, heroNum: number, heroes: HeroType[]) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_NUM, { heroNum }); - task.setParam(TASK_TYPE.HERO_QUALITY, { heroes }); - task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { heroes }); - task.setParam(TASK_TYPE.HERO_LV, { heroes }); - await task.saveAndPush(sid); -} - -export async function checkTaskInHeroStarUp(serverId: number, roleId: string, sid: string, hero: HeroType, oldStar: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_STAR_UP, { hero }); - task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { hero, oldStar, oldColorStar: 0 }); - task.setParam(TASK_TYPE.STAR_UP_SUM, { count: hero.star - oldStar }); - await task.saveAndPush(sid); -} - -export async function checkTaskInHeroWakeUp(serverId: number, roleId: string, sid: string, hero: HeroType, oldColorStar: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_STAR_UP, { hero }); - task.setParam(TASK_TYPE.HERO_WAKE_UP, { hero, oldColorStar }); - task.setParam(TASK_TYPE.HERO_QUALITY_WAKE_UP_COUNT, { hero, oldColorStar }); - task.setParam(TASK_TYPE.HERO_WAKE_UP_COUNT, { hero, oldColorStar }); - task.setParam(TASK_TYPE.HERO_WAKE_UP_STAR_UP_COUNT, { hero, oldColorStar }); - task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { hero, oldStar: 6, oldColorStar }); - task.setParam(TASK_TYPE.STAR_UP_SUM, { count: hero.colorStar - oldColorStar }); - await task.saveAndPush(sid); -} - -export async function checkTaskInHeroQUalityUp(serverId: number, roleId: string, sid: string, hero: HeroType) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_QUALITY_UP, { hero }); - task.setParam(TASK_TYPE.HERO_QUALITY_TO_QUALITY_COUNT, { hero }); - await task.saveAndPush(sid); -} - -export async function checkTaskInHeroTrain(serverId: number, roleId: string, sid: string, hero: HeroType, trainCount: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_TRAIN, { hero, trainCount }); - task.setParam(TASK_TYPE.HERO_TRAIN_SUM, { hero, trainCount }); - await task.saveAndPush(sid); -} - -export async function checkTaskInActiveScroll(serverId: number, roleId: string, sid: string, scrollActive: boolean, hero: HeroType) { - if (!scrollActive) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_UNLOCK, { hero }); - task.setParam(TASK_TYPE.ROLE_SCROLL_ACTIVE, { scrollActive }); - await task.saveAndPush(sid); - } -} - -export async function checkTaskInGuildTrain(serverId: number, roleId: string, sid: string, warId: number, isSuccess: boolean, isComplete: boolean) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.GUILD_TRAIN_SUCESS, { isSuccess }); - task.setParam(TASK_TYPE.GUILD_TRAIN, {}); - task.setParam(TASK_TYPE.GUILD_TRAIN_COUNT, { isComplete, warId }); - await task.saveAndPush(sid); -} - -export async function checkTaskInBattleStart(serverId: number, roleId: string, sid: string, warId: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.BATTLE_MAIN_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_TOWER_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_VESTIGE_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DAILY_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON_START, { warId, count: 1 }); - await task.saveAndPush(sid); -} - -/** - * battle.normalBattleHandler.battleEnd 中会触发的任务,因为有点多提出来了 - */ - export async function checkTaskInBattleEnd(serverId: number, roleId: string, sid: string, warId: number, battleHeroes: number[], battleStar: number, isSuccess: boolean) { - if(isSuccess) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.BATTLE_WITH_HERO, { warId, battleHeroes }); - task.setParam(TASK_TYPE.BATTLE_MAIN, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DAILY_STAR, { warId, battleStar, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DAILY, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON_WAR, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_TOWER, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_VESTIGE, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_MAIN_ELITE, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_BRANCH_ELITE, { warId, count: 1 }); - await task.saveAndPush(sid); - let dicWar = gameData.war.get(warId); - if(dicWar && dicWar.warType == WAR_TYPE.NORMAL) { - checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.MAIN_BATTLE, { warId }, sid); - } - } -} - -export async function checkTaskInSkipExpedition(serverId: number, roleId: string, sid: string, warId: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count: 1 }); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count: 1 }); - await task.saveAndPush(sid); -} - -export async function checkTaskInSkipTower(serverId: number, roleId: string, sid: string, towerLv: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.BATTLE_TOWER_LV, { towerLv: towerLv - 1 }); - task.setParam(TASK_TYPE.BATTLE_TOWER_START, { skipTower: true }); - task.setParam(TASK_TYPE.BATTLE_TOWER, { skipTower: true }); - await task.saveAndPush(sid); -} - - -export async function checkTaskInBattleSweep(serverId: number, roleId: string, sid: string, warId: number, count: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.BATTLE_MAIN_SWEEP, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_MAIN, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DAILY, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON_WAR, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_TOWER, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_VESTIGE, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_MAIN_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_TOWER_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_VESTIGE_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DAILY_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DUNGEON_START, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_BRANCH_ELITE, { warId, count }); - task.setParam(TASK_TYPE.BATTLE_DAILY_STAR, { warId, battleStar: 3, count }); - await task.saveAndPush(sid); -} - - -export async function checkTaskInComBattleStart(roleStatus: RoleStatus[], capId: string, blueprtId: number) { - console.log('********', JSON.stringify(roleStatus), capId, blueprtId) - for (let { roleId, isRobot } of roleStatus) { - if (!isRobot) { - let role = await RoleModel.findByRoleId(roleId); - let task = new CheckTask(role.serverId, roleId); - task.setRole(role); - if (roleId == capId && roleStatus.length > 1) { // 招募队友 - task.setParam(TASK_TYPE.COM_BATTLE_CREATE_TEAM, {}); - } else if (roleId !== capId) { // 协助寻宝 - task.setParam(TASK_TYPE.COM_BATTLE_ASSIST_TEAM, {}); - } - task.setParam(TASK_TYPE.COM_BATTLE, {}); - task.setParam(TASK_TYPE.COM_BATTLE_LV, { gid: blueprtId }); - await task.saveAndPush(); - } - } -} - -export async function checkTaskInComBattleEnd(roleStatus: RoleStatus[], capId: string) { - for (let { roleId, isRobot } of roleStatus) { - if (!isRobot) { - let role = await RoleModel.findByRoleId(roleId); - let task = new CheckTask(role.serverId, roleId); - task.setRole(role); - if (roleId == capId && roleStatus.length > 1) { // 招募队友 - task.setParam(TASK_TYPE.COM_BATTLE_CREATE_TEAM_WIN, {}); - } else if (roleId !== capId) { // 协助寻宝 - task.setParam(TASK_TYPE.COM_BATTLE_ASSIST_TEAM_WIN, {}); - } - task.setParam(TASK_TYPE.COM_BATTLE_WIN, {}); - await task.saveAndPush(); - } - } -} - -export async function checkTaskInPvpEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, heroScores: HeroScores[], seasonWinNum: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.PVP_WIN, { isSuccess }); - task.setParam(TASK_TYPE.PVP_WIN_SERIES, { isSuccess }); - task.setParam(TASK_TYPE.PVP_HERO_SCORE, { heroScores }); - await task.saveAndPush(sid); - if(seasonWinNum) { - checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.PVP, { seasonWinNum }, sid); - } -} - -export async function checkTaskInGacha(serverId: number, roleId: string, sid: string, count: number, heroes: HeroType[], result: GachaResultIndb[], isGuide: boolean) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.GACHA, { count }); - task.setParam(TASK_TYPE.GACHA_QUALITY_COUNT, { heroes }); - await task.saveAndPush(sid); - if(!isGuide) checkPopUpConditionInCreateHero(serverId, roleId, result); -} - - -export async function checkTaskInComposeEquip(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[]) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.EQUIP_COMPOSE, { count: newEplace.length - oldEplace.length }); - task.setParam(TASK_TYPE.EQUIP_COMPOSE_CNT, { oldEplace, newEplace }); - await task.saveAndPush(sid); -} - -export async function checkTaskInEquipLvUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceIds: number[]) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.EQUIP_LV_TO, { oldEplace, newEplace, ePlaceIds }); - task.setParam(TASK_TYPE.EQUIP_LV_UP, { count: ePlaceIds.length }); - await task.saveAndPush(sid); -} - -export async function checkTaskInPutJewel(serverId: number, roleId: string, sid: string, hid: number, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, originJewel: JewelType, curJewel: JewelType) { - let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.EQUIP_PUT_JEWEL, { hid, newEquip, jewels: [originJewel, curJewel ] }); - task.setParam(TASK_TYPE.EQUIP_PUT_JEWEL_CNT, { newEquip }); - task.setParam(TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT, { newEquip, jewels: [originJewel, curJewel ] }); - await task.saveAndPush(sid); -} - -export async function checkTaskInPutStone(serverId: number, roleId: string, sid: string, hid: number, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, jewel: JewelType) { - let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.EQUIP_PUT_STONE, { hid, newEquip }); - task.setParam(TASK_TYPE.EQUIP_PUT_STONE_CNT, { hid, newEquip }); - task.setParam(TASK_TYPE.EQUIP_STONE_CNT, { oldEquip, newEquip }); - task.setParam(TASK_TYPE.EQUIP_STONE_CNT_LV, { hid, newEquip }); - task.setParam(TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT, { newEquip, jewels: [jewel ] }); - await task.saveAndPush(sid); -} - -export async function checkTaskInEquipStarUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpStar: boolean, count: number, skinId: number) { - let task = new CheckTask(serverId, roleId); - if(isUpStar) { - let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); - task.setParam(TASK_TYPE.EQUIP_STAR_UP_TO, { oldEquip, newEquip }); - task.setParam(TASK_TYPE.EQUIP_SUIT_SEID_NUM, { oldEplace, newEplace, ePlaceId, skinId }); - } - task.setParam(TASK_TYPE.EQUIP_STAR_UP_CNT, { hid, ePlaceId, count }); - task.setParam(TASK_TYPE.EQUIP_STAR_UP_CNT_SUM, { count }); - await task.saveAndPush(sid); - if(isUpStar) { - checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR, { equipStar: count }, sid); - } -} - -export async function checkTaskInEquipQualityUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpQuality: boolean, count: number) { - let task = new CheckTask(serverId, roleId); - if(isUpQuality) { - let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); - task.setParam(TASK_TYPE.EQUIP_QUALITY_UP, { hid, ePlaceId }); - task.setParam(TASK_TYPE.EQUIP_QUALITY_UP_TO, { oldEquip, newEquip }) - } - task.setParam(TASK_TYPE.EQUIP_QUALITY_UP_CNT, { count }); - await task.saveAndPush(sid); -} - -export async function checkTaskInEquipReset(serverId: number, roleId: string, sid: string) { - await checkTask(serverId, roleId, sid, TASK_TYPE.JEWEL_RESET); -} - -export async function checkTaskInEquipQuench(serverId: number, roleId: string, sid: string, isSuccess: boolean) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.JEWEL_QUENCH, {}); - if(isSuccess) { - task.setParam(TASK_TYPE.JEWEL_QUENCH_SUCCESS, { isSuccess }); - } - await task.saveAndPush(sid); -} - -export async function checkTaskInComposeStone(serverId: number, roleId: string, sid: string, count: number) { - await checkTask(serverId, roleId, sid, TASK_TYPE.STONE_COMPOSE, { count }); -} - -export async function checkTaskInDonate(serverId: number, roleId: string, sid: string, cosume: RewardInter) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.GUILD_DONATE, {}); - if(cosume.id == getGoldId()) { - task.setParam(TASK_TYPE.GUILD_GOLD_DONATE, {}); - } - await task.saveAndPush(sid); -} - -// 名将擂台 -export async function checkTaskInLadderStart(serverId: number, roleId: string, sid: string) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.LADDER_CNT, { count: 1 }); - await task.saveAndPush(sid); -} - -export async function checkTaskInLadderEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, oldHistoryRank: number, newHistoryRank: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.LADDER_SUCCESS_CNT, { isSuccess, count: 1 }); - task.setParam(TASK_TYPE.LADDER_RANK, { oldLadderRank: oldHistoryRank, ladderRank: newHistoryRank }) - await task.saveAndPush(sid); -} - -export async function checkTaskInLadderSweep(serverId: number, roleId: string, sid: string, count: number) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.LADDER_CNT, { count }); - task.setParam(TASK_TYPE.LADDER_SUCCESS_CNT, { isSuccess: true, count }); - await task.saveAndPush(sid); -} - -export async function checkTaskInHeroGiveFavor(serverId: number, roleId: string, sid: string, shipId: number, connections: Connect[], oldConnections: Connect[]) { - let task = new CheckTask(serverId, roleId); - task.setParam(TASK_TYPE.HERO_CONNECT, { shipId, connections, oldConnections }); - task.setParam(TASK_TYPE.CONNECT_ONE_HERO_MAX_LV, { connections, oldConnections }); - task.setParam(TASK_TYPE.CONNECT_ONE_HERO_SUM_LV, { connections, oldConnections }); - await task.saveAndPush(sid); -} - -// 获取task状态 -export async function getCurTask(roleId: string, session: FrontendOrBackendSession) { - let userTask = await UserTaskModel.findByRole(roleId); - - let { dailyTaskRefWeekly, dailyTaskRef } = userTask; - let curWeekStart = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); - if (dailyTaskRefWeekly < curWeekStart) { // 刷新周宝箱 - dailyTaskRefWeekly = curWeekStart; - } - session.set('refWeekly', getSeconds(dailyTaskRefWeekly)); - session.push('refWeekly', () => { }); - - if (shouldRefresh(dailyTaskRef, new Date())) { - dailyTaskRef = new Date(); - userTask = await UserTaskModel.updateInfo(roleId, { dailyTaskRef }); - await removeHistoryTask(roleId, TASK_FUN_TYPE.DAILY); - } - session.set('refDaily', getSeconds(dailyTaskRef)); - session.push('refDaily', () => { }); - - let mainTask = await getMainTask(roleId, userTask); - let dailyTask = await getDailyTask(roleId, userTask); - let achievement = await getAchievement(roleId, userTask); - return { mainTask, dailyTask, achievement }; -} - -export async function getMainTask(roleId: string, userTask: UserTaskType) { - let type = TASK_FUN_TYPE.MAIN; - let { mainTaskStage: stage } = userTask; - let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec - - let taskList: TaskListReturn[] = []; - for (let [id, dic] of gameData.mainTask) { - if (dic.taskStage == stage) { - let dbRec = recMap.get(dic.taskType)?.get(dic.group); - if (dbRec) { - taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); - } else { - taskList.push({ type, id, count: 0, received: false }); - } - } - } - return { stage, taskList } -} - -export async function getDailyTask(roleId: string, userTask: UserTaskType) { - let type = TASK_FUN_TYPE.DAILY; - let { dailyTaskPoint: point, dailyTaskRefWeekly, dailyTaskPointWeekly: weeklyPoint, dailyTaskBox: box } = userTask; - let curWeekStart = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); - if (dailyTaskRefWeekly < curWeekStart) { // 刷新 - dailyTaskRefWeekly = curWeekStart; - weeklyPoint = 0; - box = []; - } - let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec - - let taskList: TaskListReturn[] = []; - for (let [id, dic] of gameData.dailyTask) { - let dbRec = recMap.get(dic.taskType)?.get(dic.group); - if (dbRec) { - taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); - } else { - taskList.push({ type, id, count: 0, received: false }); - } - } - return { point, weeklyPoint, taskList, box } -} - -export async function getAchievement(roleId: string, userTask: UserTaskType) { - let type = TASK_FUN_TYPE.ACHIEVEMENT; - let { achievementBox: box, achievementPoint: point } = userTask; - let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec - - let taskList: TaskListReturn[] = []; - for (let [id, dic] of gameData.achievement) { - let dbRec = recMap.get(dic.taskType)?.get(dic.group); - if (dbRec) { - taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); - } else { - taskList.push({ type, id, count: 0, received: false }); - } - } - return { point, taskList, box } -} - -export async function getPvpTask(roleId: string) { - let type = TASK_FUN_TYPE.PVP; - let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec - - let taskList: TaskListReturn[] = []; - for (let [id, dic] of gameData.pvpDailyTask) { - let dbRec = recMap.get(dic.taskType)?.get(dic.group); - if (dbRec) { - taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); - } else { - taskList.push({ type, id, count: 0, received: false }); - } - } - return { taskList } -} - -// 刷新每日任务 -export async function refDailyTask(roleId: string, sid: string) { - let userTask = await UserTaskModel.findByRole(roleId); - let taskList = await getDailyTask(roleId, userTask); - - // 转移每日任务 - await removeHistoryTask(roleId, TASK_FUN_TYPE.DAILY); - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.DAILY_TASK_REFRESH, { taskList }, sid); -} - -export async function removeHistoryTask(roleId: string, type: number, today?: Date) { - - // 转移每日任务 - let history = await UserTaskRecModel.getHistoryRec(roleId, type, today); - if (history.length > 0) { - await UserTaskHistoryModel.pushUserTask(roleId, history); - await UserTaskRecModel.deleteHistory(history); - } -} - -// 刷新每日宝箱数量 -export async function refDailyTaskBox(roleId: string, sid: string, debug = false) { - let userTask = await UserTaskModel.refreshWeekly(roleId, debug); - if (userTask) { - let { dailyTaskPoint: point, dailyTaskPointWeekly: weeklyPoint, dailyTaskBox: box } = userTask; - sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TASK_BOX_REFRESH, { type: TASK_FUN_TYPE.DAILY, point, weeklyPoint, box }, sid); - } -} \ No newline at end of file +import { RoleModel, RoleType } from '@db/Role'; +import { pinus, FrontendOrBackendSession } from 'pinus'; +import { resResult, shouldRefresh } from '@pubUtils/util'; +import { STATUS, TASK_TYPE, TASK_FUN_TYPE, SHOP_REFRESH_TYPE, WAR_TYPE, PUSH_ROUTE, POP_UP_SHOP_CONDITION_TYPE } from '@consts'; +import { TaskParamInter, TaskListReturn } from '@domain/roleField/task'; +import { Connect, EPlace, HeroType } from '@db/Hero'; +import { HeroScores } from '@db/PvpHistoryOpp'; +import { ItemInter, RewardInter } from '@pubUtils/interface'; +import { UserTaskModel, UserTaskType } from '@db/UserTask'; +import { UserTaskRecModel } from '@db/UserTaskRec'; +import { UserTaskHistoryModel } from '@db/UserTaskHistory'; +import { gameData } from '@pubUtils/data'; +import { getSeconds, getZeroPointD } from '@pubUtils/timeUtil'; +import { RoleStatus } from '@db/ComBattleTeam'; +import { getActivities } from '../activity/activityService'; +import { CheckTask } from './taskObj'; +import { getEquipById } from '../equipService'; +import { JewelType } from '@db/Jewel'; +import { checkPopUpCondition, checkPopUpConditionInCreateHero, checkPopUpConditionInEntry } from '../activity/popUpShopService'; +import { sendMessageToUserWithSuc } from '../pushService'; +import { getGoldId } from '../role/rewardService'; +import { GachaResultIndb } from '@domain/activityField/gachaField'; + +export async function checkTaskWithRoles(roleId: string, sid: string, taskType: TASK_TYPE, roles: RoleType[]) { + for (let role of roles) { + if (role) { + await checkTaskWithRole(role.serverId, role.roleId, role.roleId == roleId ? sid : null, taskType, role); + } + } +} + +export async function checkTaskWithRole(serverId: number, roleId: string, sid: string, taskType: TASK_TYPE, role: RoleType, args?: TaskParamInter) { + let task = new CheckTask(serverId, roleId); + task.setRole(role); + task.setParam(taskType, args); + await task.saveAndPush(sid); +} + +export async function checkTask(serverId: number, roleId: string, sid: string, taskType: TASK_TYPE, args?: TaskParamInter) { + let task = new CheckTask(serverId, roleId); + task.setParam(taskType, args); + await task.saveAndPush(sid); +} + +export async function checkGVGTask(serverId: number, roleId: string, sid: string, configId: number, leagueCode: string, taskType: TASK_TYPE, args?: TaskParamInter) { + let task = new CheckTask(serverId, roleId); + task.setParam(taskType, args); + task.setLeague(configId, leagueCode); + await task.saveAndPush(sid); +} + +export async function checkTaskInEntry(serverId: number, roleId: string, sid: string, role: RoleType) { + let task = new CheckTask(serverId, roleId); + task.setRole(role); + task.setParam(TASK_TYPE.LOGIN_SUM, {}); + task.setParam(TASK_TYPE.LOGIN_SERIES, {}); + await task.saveAndPush(sid); + checkPopUpConditionInEntry(serverId, roleId, sid); +} + +export async function checkTaskInCreateHero(serverId: number, roleId: string, sid: string, heroNum: number, heroes: HeroType[]) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_NUM, { heroNum }); + task.setParam(TASK_TYPE.HERO_QUALITY, { heroes }); + task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { heroes }); + task.setParam(TASK_TYPE.HERO_LV, { heroes }); + await task.saveAndPush(sid); +} + +export async function checkTaskInHeroStarUp(serverId: number, roleId: string, sid: string, hero: HeroType, oldStar: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_STAR_UP, { hero }); + task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { hero, oldStar, oldColorStar: 0 }); + task.setParam(TASK_TYPE.STAR_UP_SUM, { count: hero.star - oldStar }); + await task.saveAndPush(sid); +} + +export async function checkTaskInHeroWakeUp(serverId: number, roleId: string, sid: string, hero: HeroType, oldColorStar: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_STAR_UP, { hero }); + task.setParam(TASK_TYPE.HERO_WAKE_UP, { hero, oldColorStar }); + task.setParam(TASK_TYPE.HERO_QUALITY_WAKE_UP_COUNT, { hero, oldColorStar }); + task.setParam(TASK_TYPE.HERO_WAKE_UP_COUNT, { hero, oldColorStar }); + task.setParam(TASK_TYPE.HERO_WAKE_UP_STAR_UP_COUNT, { hero, oldColorStar }); + task.setParam(TASK_TYPE.HERO_QUALITY_STAR_UP, { hero, oldStar: 6, oldColorStar }); + task.setParam(TASK_TYPE.STAR_UP_SUM, { count: hero.colorStar - oldColorStar }); + await task.saveAndPush(sid); +} + +export async function checkTaskInHeroQUalityUp(serverId: number, roleId: string, sid: string, hero: HeroType) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_QUALITY_UP, { hero }); + task.setParam(TASK_TYPE.HERO_QUALITY_TO_QUALITY_COUNT, { hero }); + await task.saveAndPush(sid); +} + +export async function checkTaskInHeroTrain(serverId: number, roleId: string, sid: string, hero: HeroType, trainCount: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_TRAIN, { hero, trainCount }); + task.setParam(TASK_TYPE.HERO_TRAIN_SUM, { hero, trainCount }); + await task.saveAndPush(sid); +} + +export async function checkTaskInActiveScroll(serverId: number, roleId: string, sid: string, scrollActive: boolean, hero: HeroType) { + if (!scrollActive) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_UNLOCK, { hero }); + task.setParam(TASK_TYPE.ROLE_SCROLL_ACTIVE, { scrollActive }); + await task.saveAndPush(sid); + } +} + +export async function checkTaskInGuildTrain(serverId: number, roleId: string, sid: string, warId: number, isSuccess: boolean, isComplete: boolean) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.GUILD_TRAIN_SUCESS, { isSuccess }); + task.setParam(TASK_TYPE.GUILD_TRAIN, {}); + task.setParam(TASK_TYPE.GUILD_TRAIN_COUNT, { isComplete, warId }); + await task.saveAndPush(sid); +} + +export async function checkTaskInBattleStart(serverId: number, roleId: string, sid: string, warId: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.BATTLE_MAIN_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_TOWER_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_VESTIGE_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DAILY_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON_START, { warId, count: 1 }); + await task.saveAndPush(sid); +} + +/** + * battle.normalBattleHandler.battleEnd 中会触发的任务,因为有点多提出来了 + */ + export async function checkTaskInBattleEnd(serverId: number, roleId: string, sid: string, warId: number, battleHeroes: number[], battleStar: number, isSuccess: boolean) { + if(isSuccess) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.BATTLE_WITH_HERO, { warId, battleHeroes }); + task.setParam(TASK_TYPE.BATTLE_MAIN, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DAILY_STAR, { warId, battleStar, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DAILY, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON_WAR, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_TOWER, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_VESTIGE, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_MAIN_ELITE, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_BRANCH_ELITE, { warId, count: 1 }); + await task.saveAndPush(sid); + let dicWar = gameData.war.get(warId); + if(dicWar && dicWar.warType == WAR_TYPE.NORMAL) { + checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.MAIN_BATTLE, { warId }, sid); + } + } +} + +export async function checkTaskInSkipExpedition(serverId: number, roleId: string, sid: string, warId: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count: 1 }); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count: 1 }); + await task.saveAndPush(sid); +} + +export async function checkTaskInSkipTower(serverId: number, roleId: string, sid: string, towerLv: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.BATTLE_TOWER_LV, { towerLv: towerLv - 1 }); + task.setParam(TASK_TYPE.BATTLE_TOWER_START, { skipTower: true }); + task.setParam(TASK_TYPE.BATTLE_TOWER, { skipTower: true }); + await task.saveAndPush(sid); +} + + +export async function checkTaskInBattleSweep(serverId: number, roleId: string, sid: string, warId: number, count: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.BATTLE_MAIN_SWEEP, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_MAIN, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DAILY, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON_WAR, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_TOWER, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_VESTIGE, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_MAIN_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_TOWER_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_VESTIGE_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DAILY_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_EXPEDITION_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DUNGEON_START, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_BRANCH_ELITE, { warId, count }); + task.setParam(TASK_TYPE.BATTLE_DAILY_STAR, { warId, battleStar: 3, count }); + await task.saveAndPush(sid); +} + + +export async function checkTaskInComBattleStart(roleStatus: RoleStatus[], capId: string, blueprtId: number) { + console.log('********', JSON.stringify(roleStatus), capId, blueprtId) + for (let { roleId, isRobot } of roleStatus) { + if (!isRobot) { + let role = await RoleModel.findByRoleId(roleId); + let task = new CheckTask(role.serverId, roleId); + task.setRole(role); + if (roleId == capId && roleStatus.length > 1) { // 招募队友 + task.setParam(TASK_TYPE.COM_BATTLE_CREATE_TEAM, {}); + } else if (roleId !== capId) { // 协助寻宝 + task.setParam(TASK_TYPE.COM_BATTLE_ASSIST_TEAM, {}); + } + task.setParam(TASK_TYPE.COM_BATTLE, {}); + task.setParam(TASK_TYPE.COM_BATTLE_LV, { gid: blueprtId }); + await task.saveAndPush(); + } + } +} + +export async function checkTaskInComBattleEnd(roleStatus: RoleStatus[], capId: string) { + for (let { roleId, isRobot } of roleStatus) { + if (!isRobot) { + let role = await RoleModel.findByRoleId(roleId); + let task = new CheckTask(role.serverId, roleId); + task.setRole(role); + if (roleId == capId && roleStatus.length > 1) { // 招募队友 + task.setParam(TASK_TYPE.COM_BATTLE_CREATE_TEAM_WIN, {}); + } else if (roleId !== capId) { // 协助寻宝 + task.setParam(TASK_TYPE.COM_BATTLE_ASSIST_TEAM_WIN, {}); + } + task.setParam(TASK_TYPE.COM_BATTLE_WIN, {}); + await task.saveAndPush(); + } + } +} + +export async function checkTaskInPvpEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, heroScores: HeroScores[], seasonWinNum: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.PVP_WIN, { isSuccess }); + task.setParam(TASK_TYPE.PVP_WIN_SERIES, { isSuccess }); + task.setParam(TASK_TYPE.PVP_HERO_SCORE, { heroScores }); + await task.saveAndPush(sid); + if(seasonWinNum) { + checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.PVP, { seasonWinNum }, sid); + } +} + +export async function checkTaskInGacha(serverId: number, roleId: string, sid: string, count: number, heroes: HeroType[], result: GachaResultIndb[], isGuide: boolean) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.GACHA, { count }); + task.setParam(TASK_TYPE.GACHA_QUALITY_COUNT, { heroes }); + await task.saveAndPush(sid); + if(!isGuide) checkPopUpConditionInCreateHero(serverId, roleId, result); +} + + +export async function checkTaskInComposeEquip(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[]) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.EQUIP_COMPOSE, { count: newEplace.length - oldEplace.length }); + task.setParam(TASK_TYPE.EQUIP_COMPOSE_CNT, { oldEplace, newEplace }); + await task.saveAndPush(sid); +} + +export async function checkTaskInEquipLvUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceIds: number[]) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.EQUIP_LV_TO, { oldEplace, newEplace, ePlaceIds }); + task.setParam(TASK_TYPE.EQUIP_LV_UP, { count: ePlaceIds.length }); + await task.saveAndPush(sid); +} + +export async function checkTaskInPutJewel(serverId: number, roleId: string, sid: string, hid: number, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, originJewel: JewelType, curJewel: JewelType) { + let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.EQUIP_PUT_JEWEL, { hid, newEquip, jewels: [originJewel, curJewel ] }); + task.setParam(TASK_TYPE.EQUIP_PUT_JEWEL_CNT, { newEquip }); + task.setParam(TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT, { newEquip, jewels: [originJewel, curJewel ] }); + await task.saveAndPush(sid); +} + +export async function checkTaskInPutStone(serverId: number, roleId: string, sid: string, hid: number, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, jewel: JewelType) { + let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.EQUIP_PUT_STONE, { hid, newEquip }); + task.setParam(TASK_TYPE.EQUIP_PUT_STONE_CNT, { hid, newEquip }); + task.setParam(TASK_TYPE.EQUIP_STONE_CNT, { oldEquip, newEquip }); + task.setParam(TASK_TYPE.EQUIP_STONE_CNT_LV, { hid, newEquip }); + task.setParam(TASK_TYPE.EQUIP_JEWEL_RANDSE_CNT, { newEquip, jewels: [jewel ] }); + await task.saveAndPush(sid); +} + +export async function checkTaskInEquipStarUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpStar: boolean, count: number, skinId: number) { + let task = new CheckTask(serverId, roleId); + if(isUpStar) { + let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); + task.setParam(TASK_TYPE.EQUIP_STAR_UP_TO, { oldEquip, newEquip }); + task.setParam(TASK_TYPE.EQUIP_SUIT_SEID_NUM, { oldEplace, newEplace, ePlaceId, skinId }); + } + task.setParam(TASK_TYPE.EQUIP_STAR_UP_CNT, { hid, ePlaceId, count }); + task.setParam(TASK_TYPE.EQUIP_STAR_UP_CNT_SUM, { count }); + await task.saveAndPush(sid); + if(isUpStar) { + checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.EQUIP_STAR, { equipStar: count }, sid); + } +} + +export async function checkTaskInEquipQualityUp(serverId: number, roleId: string, sid: string, oldEplace: EPlace[], newEplace: EPlace[], ePlaceId: number, hid: number, isUpQuality: boolean, count: number) { + let task = new CheckTask(serverId, roleId); + if(isUpQuality) { + let { oldEquip, newEquip } = getEquipById(oldEplace, newEplace, ePlaceId); + task.setParam(TASK_TYPE.EQUIP_QUALITY_UP, { hid, ePlaceId }); + task.setParam(TASK_TYPE.EQUIP_QUALITY_UP_TO, { oldEquip, newEquip }) + } + task.setParam(TASK_TYPE.EQUIP_QUALITY_UP_CNT, { count }); + await task.saveAndPush(sid); +} + +export async function checkTaskInEquipReset(serverId: number, roleId: string, sid: string) { + await checkTask(serverId, roleId, sid, TASK_TYPE.JEWEL_RESET); +} + +export async function checkTaskInEquipQuench(serverId: number, roleId: string, sid: string, isSuccess: boolean) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.JEWEL_QUENCH, {}); + if(isSuccess) { + task.setParam(TASK_TYPE.JEWEL_QUENCH_SUCCESS, { isSuccess }); + } + await task.saveAndPush(sid); +} + +export async function checkTaskInComposeStone(serverId: number, roleId: string, sid: string, count: number) { + await checkTask(serverId, roleId, sid, TASK_TYPE.STONE_COMPOSE, { count }); +} + +export async function checkTaskInDonate(serverId: number, roleId: string, sid: string, cosume: RewardInter) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.GUILD_DONATE, {}); + if(cosume.id == getGoldId()) { + task.setParam(TASK_TYPE.GUILD_GOLD_DONATE, {}); + } + await task.saveAndPush(sid); +} + +// 名将擂台 +export async function checkTaskInLadderStart(serverId: number, roleId: string, sid: string) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.LADDER_CNT, { count: 1 }); + await task.saveAndPush(sid); +} + +export async function checkTaskInLadderEnd(serverId: number, roleId: string, sid: string, isSuccess: boolean, oldHistoryRank: number, newHistoryRank: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.LADDER_SUCCESS_CNT, { isSuccess, count: 1 }); + task.setParam(TASK_TYPE.LADDER_RANK, { oldLadderRank: oldHistoryRank, ladderRank: newHistoryRank }) + await task.saveAndPush(sid); +} + +export async function checkTaskInLadderSweep(serverId: number, roleId: string, sid: string, count: number) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.LADDER_CNT, { count }); + task.setParam(TASK_TYPE.LADDER_SUCCESS_CNT, { isSuccess: true, count }); + await task.saveAndPush(sid); +} + +export async function checkTaskInHeroGiveFavor(serverId: number, roleId: string, sid: string, shipId: number, connections: Connect[], oldConnections: Connect[]) { + let task = new CheckTask(serverId, roleId); + task.setParam(TASK_TYPE.HERO_CONNECT, { shipId, connections, oldConnections }); + task.setParam(TASK_TYPE.CONNECT_ONE_HERO_MAX_LV, { connections, oldConnections }); + task.setParam(TASK_TYPE.CONNECT_ONE_HERO_SUM_LV, { connections, oldConnections }); + await task.saveAndPush(sid); +} + +// 获取task状态 +export async function getCurTask(roleId: string, session: FrontendOrBackendSession) { + let userTask = await UserTaskModel.findByRole(roleId); + + let { dailyTaskRefWeekly, dailyTaskRef } = userTask; + let curWeekStart = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); + if (dailyTaskRefWeekly < curWeekStart) { // 刷新周宝箱 + dailyTaskRefWeekly = curWeekStart; + } + session.set('refWeekly', getSeconds(dailyTaskRefWeekly)); + session.push('refWeekly', () => { }); + + if (shouldRefresh(dailyTaskRef, new Date())) { + dailyTaskRef = new Date(); + userTask = await UserTaskModel.updateInfo(roleId, { dailyTaskRef }); + await removeHistoryTask(roleId, TASK_FUN_TYPE.DAILY); + } + session.set('refDaily', getSeconds(dailyTaskRef)); + session.push('refDaily', () => { }); + + let mainTask = await getMainTask(roleId, userTask); + let dailyTask = await getDailyTask(roleId, userTask); + let achievement = await getAchievement(roleId, userTask); + return { mainTask, dailyTask, achievement }; +} + +export async function getMainTask(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.MAIN; + let { mainTaskStage: stage } = userTask; + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for (let [id, dic] of gameData.mainTask) { + if (dic.taskStage == stage) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if (dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + } + return { stage, taskList } +} + +export async function getDailyTask(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.DAILY; + let { dailyTaskPoint: point, dailyTaskRefWeekly, dailyTaskPointWeekly: weeklyPoint, dailyTaskBox: box } = userTask; + let curWeekStart = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY); + if (dailyTaskRefWeekly < curWeekStart) { // 刷新 + dailyTaskRefWeekly = curWeekStart; + weeklyPoint = 0; + box = []; + } + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for (let [id, dic] of gameData.dailyTask) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if (dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + return { point, weeklyPoint, taskList, box } +} + +export async function getAchievement(roleId: string, userTask: UserTaskType) { + let type = TASK_FUN_TYPE.ACHIEVEMENT; + let { achievementBox: box, achievementPoint: point } = userTask; + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for (let [id, dic] of gameData.achievement) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if (dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + return { point, taskList, box } +} + +export async function getPvpTask(roleId: string) { + let type = TASK_FUN_TYPE.PVP; + let recMap = await UserTaskRecModel.findByRoleAndType(roleId, type); // group=>userTaskRec + + let taskList: TaskListReturn[] = []; + for (let [id, dic] of gameData.pvpDailyTask) { + let dbRec = recMap.get(dic.taskType)?.get(dic.group); + if (dbRec) { + taskList.push({ type, id, count: dbRec.count, received: dbRec.received.includes(id) }); + } else { + taskList.push({ type, id, count: 0, received: false }); + } + } + return { taskList } +} + +// 刷新每日任务 +export async function refDailyTask(roleId: string, sid: string) { + let userTask = await UserTaskModel.findByRole(roleId); + let taskList = await getDailyTask(roleId, userTask); + + // 转移每日任务 + await removeHistoryTask(roleId, TASK_FUN_TYPE.DAILY); + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.DAILY_TASK_REFRESH, { taskList }, sid); +} + +export async function removeHistoryTask(roleId: string, type: number, today?: Date) { + + // 转移每日任务 + let history = await UserTaskRecModel.getHistoryRec(roleId, type, today); + if (history.length > 0) { + await UserTaskHistoryModel.pushUserTask(roleId, history); + await UserTaskRecModel.deleteHistory(history); + } +} + +// 刷新每日宝箱数量 +export async function refDailyTaskBox(roleId: string, sid: string, debug = false) { + let userTask = await UserTaskModel.refreshWeekly(roleId, debug); + if (userTask) { + let { dailyTaskPoint: point, dailyTaskPointWeekly: weeklyPoint, dailyTaskBox: box } = userTask; + sendMessageToUserWithSuc(roleId, PUSH_ROUTE.TASK_BOX_REFRESH, { type: TASK_FUN_TYPE.DAILY, point, weeklyPoint, box }, sid); + } +} diff --git a/game-server/app/services/timeTaskService.ts b/game-server/app/services/timeTaskService.ts index cb7e96bd0..23038fe9b 100644 --- a/game-server/app/services/timeTaskService.ts +++ b/game-server/app/services/timeTaskService.ts @@ -1,1048 +1,1048 @@ - -import { scheduleJob, Job, scheduledJobs, } from 'node-schedule'; -import { PVPConfigModel, PVPConfigType } from '../db/PvpConfig'; -import { nowSeconds, getTimeFun, getSeconds } from '../pubUtils/timeUtil'; -import { getTodayGuildActivity, gameData } from '../pubUtils/data'; -import { pvpSeasonEnd } from './pvpService'; -import { getAllOnlineRoles, getAllServers, delGuildActivityRank, getServerCreateTime, redisClient } from './redisService'; -import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_TIMER, ACTIVITY_TYPE, PUSH_ROUTE, STATUS, LADDER_STATUS, LADDER_SERVER_GAP_TIME, GVG_PERIOD, SDK_PUSH_MSG_TYPE, MAIL_TYPE } from '../consts'; -import { pinus } from 'pinus'; -import { settleGuildWeekly } from './guildService'; -import { sendMailByContent, SendMailFun, sendMailsByGmMail, } from './mailService'; -import { sendEndMsgToAllServer, sendGuildActivityStatus, setPreDayActiveData, incCurGuildActivityIndex } from './guildActivity/guildActivityService'; -import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction, startDividend } from './auctionService'; -import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity'; -import { dispatch } from '../pubUtils/dispatcher'; -import { initMarquee, setServerMainten } from './gmService'; -import moment = require('moment'); -import { reportOneOnline } from './authenticateService'; -import { GVG, LADDER, PVP } from '../pubUtils/dicParam'; -import { fetch37Words } from './sdkService'; -import { GMMailModel, GMMailType } from '../db/GMMail'; -import { Maintenance, ServerlistModel, ServerlistType } from '../db/Serverlist'; -import { createMarqueeMsg, pushMarqueeMsg } from './sysChatService'; -import { RegionModel, RegionType } from '../db/Region'; -import { CreateServerParam } from '../domain/backEndField/params'; -import { infologger, errlogger } from '../util/logger'; -import { MailModel, MailType } from '../db/Mail'; -import { GroupMailModel, GroupMailType } from '../db/GroupMail'; -import { ServerMailModel, ServerMailType } from '../db/ServerMail'; -import { ActivityModel, ActivityModelType } from '../db/Activity'; -import { TimeLimitRankData } from '../domain/activityField/timeLimitRankField'; -import { sendRankMail, takeSnapshot } from './activity/timeLimitRankService'; -import { ActivityGroupModel } from '../db/ActivityGroup'; -import { pushClientMsg, sendMessageToServer } from './pushService'; -import { getRandEelm, getRandSingleEelm, resResult } from '../pubUtils/util'; -import { checkPopUpConditionWhenGuildActivityEnd } from './activity/popUpShopService'; -import { pushRefreshTime } from './connectorService'; -import { sendUnReceivedActivityDailyCoin } from './activity/dailyCoinService'; -import { ladderTimeout, ladderTimeWillout, sendLadderDailyReward } from './ladderService'; -import { LadderMatchRecModel } from '../db/LadderMatchRec'; -import { LadderMatchModel } from '../db/LadderMatch'; -import { getGroupShopTimers, refundGroupShop, setGroupShopToSetSum } from './activity/groupShopService'; -import { HiddenDataModel, HiddenDataModelType } from '../db/HiddenData'; -import { setHiddenDataToMemory } from './dataService'; -import { GVGConfigModel } from '../db/GVGConfig'; -import { createNewGVGConfig, initLeaguePrepare } from './gvg/gvgService'; -import { getFightTimeByPeriod, saveVestigeRankSchedule, gvgBattlePeriodSchedule } from './gvg/gvgFightService'; -import { gvgBattleEnd } from './gvg/gvgBattleService'; -import { ActivityMonthlyFundModel } from '../db/ActivityMonthlyFund'; -import { getActivityById } from './activity/activityService'; -import { MonthlyFundData } from "../domain/activityField/monthlyFundField"; -import { RewardInter } from '../pubUtils/interface'; -import { stringToRewardInter } from './activity/giftPackageService'; -import { autoCreateServerSchedule } from './serverService'; -import { setHiddenData } from './memoryCache/hiddenData'; -import { SignInData } from '../domain/activityField/signInField'; -import * as util from 'util'; -import { ActivitySignInModel } from '../db/ActivitySignIn'; -import { repairSignInMail } from './activity/signInService'; - - -const PER_SECOND = 1 * 1000; -const PER_DAY = 24 * 60 * 60; -const PER_HOUR = 1 * 60 * 60; -const PER_MINUTE = 1 * 60; -var seasonEndJob: Job; -var seasonMakeRewardTimJobId: Job; -var seasonRefreshTimeJobId: Job; -let guildWeeklyJobId: Job; -let guildActStartJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 -let guildActSecondsJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 -let guildActEndJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 - -/** - * 初始定时器 - */ -export async function init() { - - console.log('******* init systimer *******') - - // pvp赛季 - await setPvpSeasonSchedule(); - - // 周功勋结算任务 - guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 5 * * 1', settleGuildWeekly); - - // 每5分钟汇报在线玩家在线情况 - scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule); - - // 每天拉取37词库 - scheduleJob('fetchWord', '0 0 4 * * ?', fetch37Words); - - // 每天邮件 - checkCircleMail(); - // 每小时查询邮件推送 - checkMailByHour(); - - // 军团活动排行榜 - guildActivitySchedule(); - - // 拍卖行刷新:拍卖阶段刷新,分红发放 - auctionSchedule(); - - // 每天5点推送刷新时间消息 - // 顺便每天0点计算前一天活跃玩家中位数战力 - scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh); - - // 跑马灯 - await initMarquee(); - - // 自动开服 - await initAutoCreateServer(); - - // 限时排行榜 - await initTimeLimitRank(); - - // 名将擂台每日奖励 - await ladderDailyReward(); - - // 团购定时器 - initGroupShopSchedule(); - - // 隐藏数据定时器 - initHiddenDataSchedule(true); - - // gvg每周日 - initGVGConfigSchedule(); - - // 定时推送消息 - initPushMsgSchedule(); - - // 月基金每月未领取 - initMonthlyFundSchedule(); - - // 节日活动高级签到补发 - initVipSignInMailSchedule() -} - -// 每日刷新 -export async function everydayRefresh() { - let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - pushRefreshTime(); - setPreDayActiveData(servers); - sendUngotDividendJob(); - sendUnReceivedActivityDailyCoin(servers); - pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); -} - - -// —————————————— PVP 及赛季相关 —————————————— // - -export async function setPvpSeasonSchedule(fromBackend = false) { - let pvpConfig = await PVPConfigModel.setCurrentPvp(); - await setSeasonEndJob(pvpConfig); - await setPvpSeasonMakeRewardJob(pvpConfig); // 发送奖励定时器 - await setNextSeasonJob(pvpConfig); // 赛季开始定时器 - if(fromBackend) { - setPvpSeasonNumToRemote(pvpConfig); - setPvpSettleSeasonNumToRemote(); - } else { - setPvpSeasonNum(pvpConfig); - setPvpSettleSeasonNum(); - } -} - -async function setSeasonEndJob(pvpConfig: PVPConfigType) { - if (!!seasonEndJob) { - seasonEndJob.cancel(); - } - - if(!pvpConfig || pvpConfig.seasonEndTime < nowSeconds()) { - pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); - if(!pvpConfig) return; - } - console.log('####### setSeasonEndJob', JSON.stringify(pvpConfig)) - - seasonEndJob = scheduleJob('seasonEndJob', pvpConfig.seasonEndTime * 1000, async () => { - console.log('************ setSeasonEndJob *********'); - setPvpSeasonNumToRemote(pvpConfig); - let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); - await setSeasonEndJob(nextPvpConfig); - }); -} - -async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) { - if (!!seasonMakeRewardTimJobId) { - seasonMakeRewardTimJobId.cancel(); - } - if(!pvpConfig || pvpConfig.seasonRewardTime - 60 < nowSeconds()) { - pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); - if(!pvpConfig) return; - } - console.log('####### setPvpSeasonMakeRewardJob', JSON.stringify(pvpConfig)) - seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime * 1000 - 60 * 1000, async () => { - console.log('************ seasonMakeRewardTimJobId *********'); - await pvpSeasonEnd(pvpConfig.seasonNum); - let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); - await setPvpSeasonMakeRewardJob(nextPvpConfig); - }); -} - -async function setNextSeasonJob(pvpConfig: PVPConfigType) { - if (!!seasonRefreshTimeJobId) { - seasonRefreshTimeJobId.cancel(); - } - if(!pvpConfig || pvpConfig.seasonStartTime < nowSeconds()) { - pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); - if(!pvpConfig) return; - } - console.log('####### setNextSeasonJob', JSON.stringify(pvpConfig)) - - seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', pvpConfig.seasonStartTime * 1000, async () => { - console.log('************ setNextSeasonJob *********'); - setPvpSeasonNumToRemote(pvpConfig); - await PVPConfigModel.setNextPvp(pvpConfig.seasonNum); - let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); - await setNextSeasonJob(nextPvpConfig); - }); -} - -export async function setPvpSeasonNumToRemote(pvpConfig: PVPConfigType) { - await setPvpSeasonNum(pvpConfig); - await pinus.app.rpc.battle.battleRemote.setPvpSeasonNum.broadcast(pvpConfig); - await pinus.app.rpc.role.roleRemote.setPvpSeasonNum.broadcast(pvpConfig); - await pinus.app.rpc.connector.connectorRemote.setPvpSeasonNum.broadcast(pvpConfig); - - await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); - await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); - await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); - await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); - await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); - await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); -} - -export async function setPvpSeasonNum(pvpConfig?: PVPConfigType) { - if(!pvpConfig) { - pvpConfig = await PVPConfigModel.findCurPVPConfig(); - } - - let now = nowSeconds(); - pinus.app.set('pvpSeasonNum', pvpConfig?.seasonNum||0); - pinus.app.set('pvpSeasonStartTime', pvpConfig?.seasonStartTime||0); - pinus.app.set('pvpSeasonEndTime', pvpConfig?.seasonEndTime||0); - pinus.app.set('pvpSeasonRewardTime', pvpConfig?.seasonRewardTime||0); - if(!pvpConfig || pvpConfig.seasonEndTime <= now) { // 赛季结束,需要显示下一赛季的倒计时 - let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); - if(nextPvpConfig) { - pinus.app.set('pvpSeasonStartTime', nextPvpConfig.seasonStartTime); - } - } -} - -export async function setPvpSettleSeasonNumToRemote(settledPvpConfig?: PVPConfigType) { - setPvpSettleSeasonNum(settledPvpConfig); - await pinus.app.rpc.battle.battleRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); - await pinus.app.rpc.role.roleRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); - await pinus.app.rpc.connector.connectorRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); -} - -export async function setPvpSettleSeasonNum(settledPvpConfig?: PVPConfigType) { - if(!settledPvpConfig) { - settledPvpConfig = await PVPConfigModel.getSettledConfig(); - if(!settledPvpConfig) return; - } - pinus.app.set('pvpSettleSeasonNum', settledPvpConfig.seasonNum); -} - -export async function reportOnlineSchedule() { - let allRoles = await getAllOnlineRoles(); - infologger.info('reportOnlineSchedule all roles count: ', allRoles.length); - console.log('reportOnlineSchedule all roles count: ', allRoles.length) - for (let { roleId, userCode, sid } of allRoles) { - let result = reportOneOnline(roleId, userCode, sid, false); - if (!result) continue; - } -} - -// —————————————— PVP 及赛季相关 end —————————————— // - -// —————————————— 军团活动 —————————————— // -/** - * 军团活动,每晚8点开启 - */ -export async function guildActivitySchedule() { - /***********guildActivitySchedule***********/ - if (guildActStartJobId) { - guildActStartJobId.cancel(); - } - - let dicGuildActivity = getTodayGuildActivity(); - // console.log(dicGuildActivity) - - guildActStartJobId = scheduleJob('guildActivityStart', `${dicGuildActivity.startSeconds} ${dicGuildActivity.startMinute} ${dicGuildActivity.startTime} * * ?`, guildActivityStartSchedule); -} - -// 军团晚间活动,每天8点开始 -async function guildActivityStartSchedule() { - await guildActivityStart(); -} - -export async function guildActivityStart(dicGuildActivity?: DicGuildActivity) { - console.log('*******开始军团晚间活动****') - if (!dicGuildActivity) dicGuildActivity = getTodayGuildActivity(); - if (!dicGuildActivity) return; - - console.log('********', dicGuildActivity.id, Date.now() + dicGuildActivity.duringTime * 1000) - let servers = await getAllServers(); // 玩家serverId列表 - console.log('****** guildActSecondsJobId', guildActSecondsJobId) - if (guildActSecondsJobId) { - guildActSecondsJobId.cancel(); - guildActSecondsJobId = undefined; - } - if (guildActEndJobId) { - guildActEndJobId.cancel(); - guildActEndJobId = undefined; - } - - let aid = dicGuildActivity.id; - await incCurGuildActivityIndex(aid); - await pinus.app.rpc.guild.guildActivityRemote.guildActivityStart.broadcast(aid); - - if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { - guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', gateActivitySeconds); - // 结束时间 - guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, gateActivityEnd); - } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { - guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', cityActivitySeconds); - // 结束时间 - guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, cityActivityEnd); - } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { - - // 开始活动 - let guildServers = pinus.app.getServersByType('guild'); - for (let serverId of servers) { - let sid = await dispatch(redisClient(), serverId.toString(), guildServers, 'guild'); - await pinus.app.rpc.guild.guildActivityRemote.raceActivityStart.toServer(sid.id, serverId); - } - - guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/2 * * * * *', raceActivitySeconds); - // 结束时间 - guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, raceActivityEnd); - } - - for (let serverId of servers) { - await sendGuildActivityStatus(serverId); - } - pushClientMsg(SDK_PUSH_MSG_TYPE.GUILD_ACTIVITY_START); - return true; -} - -// 蛮夷入侵 -// 结束军团活动 -export async function gateActivityEnd() { - - console.log('*****gateActivityEnd'); - await sendEndMsgToAllServer(); - await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); - - if (guildActSecondsJobId) { - guildActSecondsJobId.cancel(); - guildActSecondsJobId = undefined; - } - if (guildActEndJobId) { - guildActEndJobId.cancel(); - guildActEndJobId = undefined; - } - checkPopUpConditionWhenGuildActivityEnd(); -} - -// 每10秒下发一次的任务 -export async function gateActivitySeconds() { - console.log('*****gateActivitySeconds') - await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); -} - -// 诸侯混战 -// 结束军团活动 -export async function cityActivityEnd() { - console.log('*****cityActivityEnd'); - await sendEndMsgToAllServer(); - await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); - - // 发完之后再做下周自动宣战 - // await autoDeclare(); - if (guildActSecondsJobId) { - guildActSecondsJobId.cancel(); - guildActSecondsJobId = undefined; - } - if (guildActEndJobId) { - guildActEndJobId.cancel(); - guildActEndJobId = undefined; - } - checkPopUpConditionWhenGuildActivityEnd(); -} - -// 每10秒下发一次的任务 -export async function cityActivitySeconds() { - console.log('*****cityActivitySeconds') - await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); -} - -// 粮草先行 -// 结束军团活动 -export async function raceActivityEnd() { - console.log('*****raceActivityEnd'); - await sendEndMsgToAllServer(); - await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); - - if (guildActSecondsJobId) { - guildActSecondsJobId.cancel(); - guildActSecondsJobId = undefined; - } - if (guildActEndJobId) { - guildActEndJobId.cancel(); - guildActEndJobId = undefined; - } - checkPopUpConditionWhenGuildActivityEnd(); -} - -// 每10秒下发一次的任务 -export async function raceActivitySeconds() { - console.log('*****raveActivitySeconds') - let servers = await getAllServers(); // 玩家serverId列表 - let guildServers = pinus.app.getServersByType('guild'); - for (let serverId of servers) { - let sid = await dispatch(redisClient(), serverId.toString(), guildServers, 'guild'); - await pinus.app.rpc.guild.guildActivityRemote.calWoodenHorseAndSend.toServer(sid.id, serverId); - } -} - -// —————————————— 军团活动 end —————————————— // - -// —————————————— 拍卖行 —————————————— // - -let startGuildAuctionJobId: Job; -let startWorldAuctionJobId: Job; -let stopAuctionJobId: Job; -let startDividendJobId: Job; - -export async function auctionSchedule() { - clearAuctionSchedule(); - let guildOpen = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); - let worldOpen = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN); - let worldClose = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); - let dividendStart = gameData.auctionTime.get(AUCTION_TIME.DIVIDEND_START); - - // console.log('***** auctionSchedule', guildOpen.hour, guildOpen.minute, guildOpen.seconds); - // console.log('***** auctionSchedule', worldOpen.hour, worldOpen.minute, worldOpen.seconds); - // console.log('***** auctionSchedule', worldClose.hour, worldClose.minute, worldClose.seconds); - startGuildAuctionJobId = scheduleJob('startGuildAuction', `${guildOpen.seconds} ${guildOpen.minute} ${guildOpen.hour} * * ?`, startGuildAuction); - startWorldAuctionJobId = scheduleJob('startWorldAuction', `${worldOpen.seconds} ${worldOpen.minute} ${worldOpen.hour} * * ?`, startWorldAuction); - startDividendJobId = scheduleJob('startDividend', `${dividendStart.seconds} ${dividendStart.minute} ${dividendStart.hour} * * ?`, startDividend); - stopAuctionJobId = scheduleJob('stopAuction', `${worldClose.seconds} ${worldClose.minute} ${worldClose.hour} * * ?`, stopAuction); - -} - -function clearAuctionSchedule() { - if (startGuildAuctionJobId) { - startGuildAuctionJobId.cancel(); - startGuildAuctionJobId = undefined; - } - if (startWorldAuctionJobId) { - startWorldAuctionJobId.cancel(); - startWorldAuctionJobId = undefined; - } - if (stopAuctionJobId) { - stopAuctionJobId.cancel(); - stopAuctionJobId = undefined; - } -} - -// —————————————— 拍卖行 end —————————————— // - -// —————————————— 邮件 —————————————— // -let circleMailJob: Job; -async function checkCircleMail() { - if(circleMailJob) { - circleMailJob.cancel(); - } - circleMailJob = scheduleJob('circleMail', '0 0 20 * * ?', scheduleSendCircleMail); - // scheduleSendCircleMail(); -} - -async function scheduleSendCircleMail() { - let gmmails = await GMMailModel.findCircleMails(pinus.app.get('env')); - await sendMailsByGmMail(gmmails); -} - - -let mailByHourJob: Job; -async function checkMailByHour() { - if(mailByHourJob) { - mailByHourJob.cancel(); - } - // 每小时一次,为了和每天循环邮件任务不重复,设在每小时05分 - mailByHourJob = scheduleJob('setMailTimerByHour', '0 5 0/1 * * ?', async () => { - await setMailSchedule(false) - }); - setMailSchedule(true); // 初始时候启动一次 -} - -async function setMailSchedule(isInit: boolean) { - let minuteNow = moment().minute(); - let beforeTime = minuteNow >= 5? moment().minute(5).unix(): moment().minute(5).add(-1, 'h').unix(); - let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix(); - - let mails = await MailModel.findByTimeGap(beforeTime, time); - let groupMails = await GroupMailModel.findByTimeGap(beforeTime, time); - let serverMails = await ServerMailModel.findByTimeGap(beforeTime, time); - - let times: number[] = []; - for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) { - if(times.indexOf(sendTime) == -1) times.push(sendTime); - } - - for(let time of times) { - if(Date.now() > time * 1000) { - if(!isInit) await pushMailSchedule(time); - } else { - scheduleJob(`mailPush${time}`, time * 1000, async () => { - await pushMailSchedule(time); - }); - } - } -} - -// 当前时间到下一次定时器之间的定时器 -export async function addMailsToSchedule(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { - let minuteNow = moment().minute(); - let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix(); - - let times: number[] = []; - for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) { - if(sendTime * 1000 > Date.now() && sendTime < time && times.indexOf(sendTime) == -1) times.push(sendTime); - } - - for(let time of times) { - if(!scheduledJobs[`mailPush${time}`]) { - scheduleJob(`mailPush${time}`, time * 1000, async () => { - await pushMailSchedule(time); - }) - } - } -} - -async function pushMailSchedule(time: number) { - if(scheduledJobs[`mailPush${time}`]) scheduledJobs[`mailPush${time}`].cancel(); - - let mails = await MailModel.findBySendTime(time); - let groupMails = await GroupMailModel.findBySendTime(time); - let serverMails = await ServerMailModel.findBySendTime(time); - - let f = new SendMailFun(); - f.setMails(mails, groupMails, serverMails); - await f.pushToUsers(); -} - -// —————————————— 邮件 end —————————————— // - -// —————————————— 维护 —————————————— // -let maintenInfos = new Map(); // batchCode => {servers, maintenance} -export async function initMaintenance(servers?: ServerlistType[], fromApp = false) { - if(!servers) servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - - for(let server of servers) { - let { maintenance } = server; - if(maintenance && maintenance.isOpen) { - if(!maintenInfos.has(maintenance.batchCode)) { - maintenInfos.set(maintenance.batchCode, { servers: [], maintenance }); - } - maintenInfos.get(maintenance.batchCode).servers.push(server); - } - } - for(let [batchCode] of maintenInfos) { - await setMaintenance(batchCode, fromApp); - } -} - -export async function initMaintenanaceInOtherServers() { - const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - - for(let server of servers) { - let { id, maintenance } = server; - if(maintenance && maintenance.isOpen) { - setServerMainten([id], maintenance.startTime, maintenance.endTime, maintenance.version) - } - } -} - -// 设置维护 -async function setMaintenance(batchCode: string, fromApp: boolean) { - let { maintenance } = maintenInfos.get(batchCode); - - console.log('***** maintenance', maintenance); - - let now = nowSeconds(); - // 发送消息 - if(maintenance.hasNotify && now < maintenance.startTime) { // 提前5分钟发通知 - if(now > maintenance.startTime - 5 * 60) { - maintenanceNotifySchedule(batchCode); - } else { - if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); - scheduleJob(`maintenNotify${batchCode}`, (maintenance.startTime - 5 * 60) * 1000, () => { - maintenanceNotifySchedule(batchCode); - }) - } - } else { - if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); - } - // 开始维护 - console.log('******* setMaintenance', now, now < maintenance.endTime, now > maintenance.startTime) - if(now < maintenance.endTime) { - if(now > maintenance.startTime) { - if(!fromApp) await startMaintenanceSchedule(batchCode); - } else { - scheduleJob(`startMainten${batchCode}`, maintenance.startTime * 1000, async () => { - await startMaintenanceSchedule(batchCode); - }); - } - } else { - if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); - } - -} - -// 维护前通知 -async function maintenanceNotifySchedule(batchCode: string) { - let { servers, maintenance } = maintenInfos.get(batchCode); - if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); - if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); - - scheduleJob(`maintenSec${batchCode}`, `0 */1 * * * *`, async () => { - for(let { id: serverId } of servers) { - let msgData = await createMarqueeMsg('', '系统', serverId, '服务器即将维护,请玩家提前退出游戏'); - await pushMarqueeMsg(msgData); - } - }) -} - -// 开始维护 -async function startMaintenanceSchedule(batchCode: string) { - let { servers, maintenance } = maintenInfos.get(batchCode); - let serverIds = servers.map(cur => cur.id); - if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); - if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); - if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); - - // 向全服发送 - for(let { id: serverId } of servers) { - await sendMessageToServer(serverId, PUSH_ROUTE.SERVER_MAINTENANCE, resResult(STATUS.SERVER_MAINTENANCE)); - } - - // 更新connectorRemote里面的维护服务器 - console.log('******** startMaintenanceSchedule', batchCode, serverIds, maintenance.startTime, maintenance.endTime) - pinus.app.rpc.connector.connectorRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.activity.activityRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.battle.battleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.comBattle.comBattleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.chat.chatRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.guild.guildRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.order.orderRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - pinus.app.rpc.role.roleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); - // 数数flush - pinus.app.rpc.activity.activityRemote.taflush.broadcast(); - pinus.app.rpc.battle.battleRemote.taflush.broadcast(); - pinus.app.rpc.chat.chatRemote.taflush.broadcast(); - pinus.app.rpc.connector.connectorRemote.taflush.broadcast(); - pinus.app.rpc.guild.guildRemote.taflush.broadcast(); - pinus.app.rpc.order.orderRemote.taflush.broadcast(); - pinus.app.rpc.role.roleRemote.taflush.broadcast(); - pinus.app.rpc.systimer.systimerRemote.taflush.broadcast(); -} - -// 提前结束维护 -export async function stopMaintenance(batchCode: string, serverIds: number[]) { - // console.log('***********', serverIds) - let { servers = [], maintenance = {} as Maintenance } = maintenInfos.get(batchCode)||{}; - for(let id of serverIds) { - let index = servers.findIndex(cur => cur.id == id); - if(index != -1) servers.splice(index); - } - if(servers.length == 0) { - if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); - if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); - if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); - maintenInfos.delete(batchCode); - } - - // 更新connectorRemote里面的维护服务器 - pinus.app.rpc.connector.connectorRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.activity.activityRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.battle.battleRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.comBattle.comBattleRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.chat.chatRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.guild.guildRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.order.orderRemote.stopServerMainten.broadcast(serverIds); - pinus.app.rpc.role.roleRemote.stopServerMainten.broadcast(serverIds); -} - -// —————————————— 维护 end —————————————— // -// —————————————— 自动开服 —————————————— // -export async function initAutoCreateServer() { - scheduleJob('autoServer', '0 0 */1 * * ?', autoCreateServerSchedule) -} - -// —————————————— 自动开服 end —————————————— // - -// —————————————— 活动 start —————————————— // -async function initTimeLimitRank() { - let activities = await ActivityModel.findActivityByType(ACTIVITY_TYPE.TIME_LIMIT_RANK); - await updateTimeLimitRank(activities); -} - -export async function updateTimeLimitRank(activities: ActivityModelType[]) { - for(let activity of activities) { - let { activityId } = activity - let group = await ActivityGroupModel.findByActivity(activityId); - for(let { serverIds } of group) { - let servers = await ServerlistModel.findByServerIds(serverIds); - for(let { env, openTime, id: serverId } of servers) { - if(env == pinus.app.get('env')) { - let data = new TimeLimitRankData(activity, 0, openTime); - if(data.sendMailTime > Date.now()) { - await setSendRankMailSchedule(activityId, serverId, data); - } - if(data.rankEndTime > Date.now() && data.needSnapshot()) { - await setTakeRankSnapshotSchedule(activityId, serverId, data); - } - } - } - } - } -} - -async function setSendRankMailSchedule(activityId: number, serverId: number, data: TimeLimitRankData) { - console.log('########### setSendRankMailSchedule1 ########', activityId, serverId, data.sendMailTime) - if(scheduledJobs[`rankMail_${serverId}_${activityId}`]) { - scheduledJobs[`rankMail_${serverId}_${activityId}`].cancel(); - } - - scheduleJob(`rankMail_${serverId}_${activityId}`, data.sendMailTime, async () => { - console.log('########### setSendRankMailSchedule2 ########') - await sendRankMail(data, serverId); - }); -} - - -async function setTakeRankSnapshotSchedule(activityId: number, serverId: number, data: TimeLimitRankData) { - console.log('########### setTakeRankSnapshotSchedule1 ########', activityId, serverId, data.rankEndTime) - - if(scheduledJobs[`snapshot_${serverId}_${activityId}`]) { - scheduledJobs[`snapshot_${serverId}_${activityId}`].cancel(); - } - - scheduleJob(`snapshot_${serverId}_${activityId}`, data.rankEndTime, async () => { - console.log('########### setTakeRankSnapshotSchedule2 ########') - await takeSnapshot(data, serverId); - }) -} -// —————————————— 活动 end —————————————— // - -// —————————————— 名将擂台 start —————————————— // -export async function setLadderCountDown(battleCode: string, time: number, status: LADDER_STATUS) { - if(scheduledJobs[`ladder${battleCode}`]) { - scheduledJobs[`ladder${battleCode}`].cancel(); - } - let endTime = time + (status == LADDER_STATUS.CHECK? LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN: LADDER.LADDER_BATTLE_COUNTDOWN) * 1000; - scheduleJob(`ladder${battleCode}`, endTime, async () => { - await ladderTimeWillout(battleCode, status); - - scheduledJobs[`ladder${battleCode}`].cancel(); - scheduleJob(`ladder${battleCode}`, endTime + LADDER_SERVER_GAP_TIME * 1000, async () => { - await ladderTimeout(battleCode, status); - scheduledJobs[`ladder${battleCode}`].cancel(); - }); - }) -} - -export async function cancelLadderCountDown(battleCode: string) { - if(scheduledJobs[`ladder${battleCode}`]) { - scheduledJobs[`ladder${battleCode}`].cancel(); - } -} - -async function ladderDailyReward() { - scheduleJob('ladderDailyReward', '0 0 22 * * ?', async () => { - let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - for(let { id } of servers) { - await sendLadderDailyReward(id); - } - }); - let recs = await LadderMatchRecModel.getUncompleteData(); - let battleCodes: string[] = []; - for(let { battleCode, checkTime, battleTime, status, serverId, defenseInfo } of recs) { - if(status == LADDER_STATUS.CHECK) { - if(Date.now() > checkTime + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN * 1000) { - battleCodes.push(battleCode); - await LadderMatchModel.unlock(serverId, defenseInfo?.roleId); - } else { - await setLadderCountDown(battleCode, checkTime, status) - } - } else if (status == LADDER_STATUS.BATTLE) { - if(Date.now() > battleTime + LADDER.LADDER_BATTLE_COUNTDOWN * 1000 ) { - battleCodes.push(battleCode); - await LadderMatchModel.unlock(serverId, defenseInfo?.roleId); - } else { - await setLadderCountDown(battleCode, battleTime, status) - } - } - } - await LadderMatchRecModel.timeoutMany(battleCodes); -} -// —————————————— 名将擂台 end —————————————— // - -// —————————————— 团购定时器 start —————————————— // -async function initGroupShopSchedule() { - initSumSchedule(); - scheduleJob('groupShopRefund', '0 30 5 * * ?', () => { - refundGroupShop(); - }); -} - -let initSumJobs = []; -export async function initSumSchedule() { - let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); - let groupIds: number[] = []; - for(let { id } of servers) { - let groups = await ActivityGroupModel.findByServerId(id); - for(let { groupId } of groups) { - groupIds.push(groupId); - } - } - - let activities = await ActivityModel.findOpenActivityByType(groupIds, ACTIVITY_TYPE.GROUP_SHOP); - let scheduleMap = new Map(); // 时间 => data - for(let activity of activities) { - let timers = await getGroupShopTimers(activity); - for(let { time, itemId, sum } of timers) { - if(time < Date.now()) continue; - if(!scheduleMap.has(time)) { - scheduleMap.set(time, []); - } - scheduleMap.get(time).push({ activityId: activity.activityId, itemId, sum }); - } - } - - console.log('#### initSumJobs', initSumJobs.length); - console.log('#### scheduleMap', scheduleMap); - for(let job of initSumJobs) { - job.cancel(); - } - for(let [time, arr] of scheduleMap) { - if(scheduledJobs[`groupShopSetSum${time}`]) { - scheduledJobs[`groupShopSetSum${time}`].cancel(); - } - let job = scheduleJob(`groupShopSetSum${time}`, time, async () => { - await setGroupShopToSetSum(arr); - }); - initSumJobs.push(job); - } -} - -// —————————————— 团购定时器 end —————————————— // - -// —————————————— 配表兼容 start —————————————— // -let hiddenDataJob: Job; -export async function initHiddenData(data?: HiddenDataModelType, nextData?: HiddenDataModelType) { - let now = nowSeconds(); - if(!data) data = await HiddenDataModel.findCurData(now); - if(!nextData) nextData = await HiddenDataModel.findNextData(now); - setHiddenData(data?.heroes, data?.goods, nextData?.refTime); -} - -export async function initHiddenDataSchedule(isInit: boolean) { - if(hiddenDataJob) hiddenDataJob.cancel(); - let now = nowSeconds(); - let data = await HiddenDataModel.findCurData(now); - let nextData = await HiddenDataModel.findNextData(data?.refTime??now); - - if(isInit) { - await initHiddenData(data, nextData) - } else { - await setHiddenDataToMemory(data, nextData); - } - console.log('######## initHiddenDataSchedule', nextData); - if(nextData) { - if(scheduledJobs['hiddenData']) scheduledJobs['hiddenData'].cancel(); - scheduleJob(`hiddenData`, nextData.refTime * 1000, async () => { - console.log('######## hiddenDataSchedule', nextData); - - await initHiddenDataSchedule(false); - }); - } -} -// —————————————— 配表兼容 end —————————————— // - -// —————————————— gvg start —————————————— // -let gvgBattleSecondJob: Job; // gvg每5秒的定时器 -let gvgBattleCatapultJob: Job; // gvg投石车定时器 - -export async function initGVGConfigSchedule() { - let config = await GVGConfigModel.findConfig(); - if(!config || nowSeconds() > config.scheduleTime) { - config = await createNewGVGConfig(); - } - - if(scheduledJobs[`gvgTeam`]) scheduledJobs[`gvgTeam`].cancel(); - scheduleJob(`gvgTeam`, config.teamTime * 1000, async () => { - await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); - }) - if(scheduledJobs[`gvgConfig`]) scheduledJobs[`gvgConfig`].cancel(); - scheduleJob(`gvgConfig`, config.scheduleTime * 1000, createNewGVGConfig); - - if(nowSeconds() > config.prepareTime) { - initLeaguePrepare(); - } else { - if(scheduledJobs[`gvgPrepare`]) scheduledJobs[`gvgPrepare`].cancel(); - scheduleJob(`gvgPrepare`, config.prepareTime * 1000, initLeaguePrepare); - } - - if(scheduledJobs[`gvgFight`]) scheduledJobs[`gvgFight`].cancel(); - scheduleJob(`gvgFight`, '0 30 22 * * ?', saveVestigeRankSchedule); - - if(scheduledJobs[`gvgBattle`]) scheduledJobs[`gvgBattle`].cancel(); - scheduleJob(`gvgBattle`, config.battleTime * 1000, gvgBattlePeriodSchedule); - - let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.BATTLE, config.battleTime); - - if(nowSeconds() > startFightTime - GVG.GVG_GUARD_START_TIME && nowSeconds() < endFightTime) { - if(gvgBattleSecondJob) gvgBattleSecondJob.cancel(); - gvgBattleSecondJob = scheduleJob('gvgBattleSecond', '*/5 * * * * *', gvgBattleSecondSchedule); - if(gvgBattleCatapultJob) gvgBattleCatapultJob.cancel(); - gvgBattleCatapultJob = scheduleJob('gvgBattleCatapult', `*/${GVG.GVG_CATAPULT_TIME} * * * * *`, gvgBattleCatapult); - } else { - scheduleJob(`gvgBattleStartSchedule`, (startFightTime - GVG.GVG_GUARD_START_TIME) * 1000, gvgBattleStartSchedule); - } - if(scheduledJobs[`gvgBattleEndSchedule`]) scheduledJobs[`gvgBattleEndSchedule`].cancel(); - scheduleJob(`gvgBattleEndSchedule`, endFightTime * 1000, gvgBattleEndSchedule); -} - -// gvg激战期开始定时器 -export async function gvgBattleStartSchedule() { - console.log('##### gvgBattleStartSchedule', Date.now()) - if(gvgBattleSecondJob) gvgBattleSecondJob.cancel(); - gvgBattleSecondJob = scheduleJob('gvgBattleSecond', '*/5 * * * * *', gvgBattleSecondSchedule); - - // 初始化投石车 - let guildServers = pinus.app.getServersByType('guild'); - if(guildServers.length > 0) { - pinus.app.rpc.guild.guildRemote.gvgBattleStart.toServer(getRandSingleEelm(guildServers).id); - } - if(gvgBattleCatapultJob) gvgBattleCatapultJob.cancel(); - gvgBattleCatapultJob = scheduleJob('gvgBattleCatapult', `*/${GVG.GVG_CATAPULT_TIME} * * * * *`, gvgBattleCatapult); - - setTimeout(() => { - pushClientMsg(SDK_PUSH_MSG_TYPE.GVG_BATTLE_START); - }, GVG.GVG_GUARD_START_TIME * 1000); -} - -// 每隔5秒的积分计算定时器 -async function gvgBattleSecondSchedule() { - console.log('********** gvgBattleSecondJob *************'); - pinus.app.rpc.guild.guildRemote.gvgBattleSeconds.broadcast(); -} - -// 每隔10秒的投石车投机定时器 -async function gvgBattleCatapult() { - console.log('********** gvgBattleCatapultJob *************'); - pinus.app.rpc.guild.guildRemote.catapultHurt.broadcast(); -} - -// gvg激战期结束定时器 -export async function gvgBattleEndSchedule() { - let guildServers = pinus.app.getServersByType('guild'); - if(guildServers.length > 0) { - pinus.app.rpc.guild.guildRemote.gvgBattleEnd.toServer(getRandSingleEelm(guildServers).id); - } - // 定时器关闭 - if(gvgBattleSecondJob) { - gvgBattleSecondJob.cancel(); - gvgBattleSecondJob = undefined; - } - if(gvgBattleCatapultJob) { - gvgBattleCatapultJob.cancel(); - gvgBattleCatapultJob = undefined; - } - -} -// —————————————— gvg end —————————————— // - -async function initPushMsgSchedule() { - scheduleJob('sendDinner', '0 0 19 * * ?', async () => { - // pushClientMsg(SDK_PUSH_MSG_TYPE.AFK_ATTENTION); - pushClientMsg(SDK_PUSH_MSG_TYPE.AP_DINNER); - }); - scheduleJob('sendLunch', '0 0 12 * * ?', async () => { - pushClientMsg(SDK_PUSH_MSG_TYPE.AP_LUNCH); - }); -} - -// 月基金未领取的发送到邮件,每月发送 -async function initMonthlyFundSchedule() { - scheduleJob('initMonthlyFundSchedule', '0 0 5 1 * ?', async () => { - let roundIndex = parseInt(moment().add(-1, 'M').format('YYYYMM')); - await monthlyFundSchedule(roundIndex); - }); -} - -// 高级签到自动补发 -export async function initVipSignInMailSchedule() { - let activities = await ActivityModel.findOpenTypeByTime(ACTIVITY_TYPE.COMMON_SIGN_IN); - for(let activityData of activities) { - let playerData = new SignInData(activityData, 0, 0); - if(!playerData || playerData.productID == '&') continue; - - const jobKey = `vipSignMailJob${playerData.activityId}`; - if(scheduledJobs[jobKey]) scheduledJobs[jobKey].cancel(); - scheduleJob(jobKey, playerData.endTime, async () => { - await repairSignInMail(playerData); - }); - } -} - -export async function monthlyFundSchedule(roundIndex: number) { - let activityMap = new Map(); - let playerDatas = await ActivityMonthlyFundModel.findNotReceivedReward(roundIndex); - let _ids: string[] = []; - for(let playerData of playerDatas) { - if(!activityMap.has(playerData.activityId)) { - let activity = await getActivityById(playerData.activityId); - activityMap.set(playerData.activityId, activity); - } - let activityData = activityMap.get(playerData.activityId); - if(!activityData) continue; - let data = new MonthlyFundData(activityData, 0, 0); - let page = data.findPage(playerData.pageIndex); - page.setPlayerRecord(playerData); - let rewards: RewardInter[] = []; - for(let { reward, hasReceived } of page.rewards) { - if(!hasReceived) rewards.push(...stringToRewardInter(reward)); - } - if(rewards.length > 0) { - await sendMailByContent(MAIL_TYPE.MONTHLY_FUND, playerData.roleId, { goods: rewards }); - } - _ids.push(playerData._id); - } - await ActivityMonthlyFundModel.updateHasReceivedAll(_ids); -} \ No newline at end of file + +import { scheduleJob, Job, scheduledJobs, } from 'node-schedule'; +import { PVPConfigModel, PVPConfigType } from '@db/PvpConfig'; +import { nowSeconds, getTimeFun, getSeconds } from '@pubUtils/timeUtil'; +import { getTodayGuildActivity, gameData } from '@pubUtils/data'; +import { pvpSeasonEnd } from './pvpService'; +import { getAllOnlineRoles, getAllServers, delGuildActivityRank, getServerCreateTime, redisClient } from './redisService'; +import { GUILD_ACTIVITY_TYPE, REFRESH_TIME, COUNTER, AUCTION_TIME, GM_MAIL_TYPE, SERVER_TIMER, ACTIVITY_TYPE, PUSH_ROUTE, STATUS, LADDER_STATUS, LADDER_SERVER_GAP_TIME, GVG_PERIOD, SDK_PUSH_MSG_TYPE, MAIL_TYPE } from '@consts'; +import { pinus } from 'pinus'; +import { settleGuildWeekly } from './guildService'; +import { sendMailByContent, SendMailFun, sendMailsByGmMail, } from './mailService'; +import { sendEndMsgToAllServer, sendGuildActivityStatus, setPreDayActiveData, incCurGuildActivityIndex } from './guildActivity/guildActivityService'; +import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction, startDividend } from './auctionService'; +import { DicGuildActivity } from '@pubUtils/dictionary/DicGuildActivity'; +import { dispatch } from '@pubUtils/dispatcher'; +import { initMarquee, setServerMainten } from './gmService'; +import moment = require('moment'); +import { reportOneOnline } from './authenticateService'; +import { GVG, LADDER, PVP } from '@pubUtils/dicParam'; +import { fetch37Words } from './sdkService'; +import { GMMailModel, GMMailType } from '@db/GMMail'; +import { Maintenance, ServerlistModel, ServerlistType } from '@db/Serverlist'; +import { createMarqueeMsg, pushMarqueeMsg } from './sysChatService'; +import { RegionModel, RegionType } from '@db/Region'; +import { CreateServerParam } from '@domain/backEndField/params'; +import { infologger, errlogger } from '../util/logger'; +import { MailModel, MailType } from '@db/Mail'; +import { GroupMailModel, GroupMailType } from '@db/GroupMail'; +import { ServerMailModel, ServerMailType } from '@db/ServerMail'; +import { ActivityModel, ActivityModelType } from '@db/Activity'; +import { TimeLimitRankData } from '@domain/activityField/timeLimitRankField'; +import { sendRankMail, takeSnapshot } from './activity/timeLimitRankService'; +import { ActivityGroupModel } from '@db/ActivityGroup'; +import { pushClientMsg, sendMessageToServer } from './pushService'; +import { getRandEelm, getRandSingleEelm, resResult } from '@pubUtils/util'; +import { checkPopUpConditionWhenGuildActivityEnd } from './activity/popUpShopService'; +import { pushRefreshTime } from './connectorService'; +import { sendUnReceivedActivityDailyCoin } from './activity/dailyCoinService'; +import { ladderTimeout, ladderTimeWillout, sendLadderDailyReward } from './ladderService'; +import { LadderMatchRecModel } from '@db/LadderMatchRec'; +import { LadderMatchModel } from '@db/LadderMatch'; +import { getGroupShopTimers, refundGroupShop, setGroupShopToSetSum } from './activity/groupShopService'; +import { HiddenDataModel, HiddenDataModelType } from '@db/HiddenData'; +import { setHiddenDataToMemory } from './dataService'; +import { GVGConfigModel } from '@db/GVGConfig'; +import { createNewGVGConfig, initLeaguePrepare } from './gvg/gvgService'; +import { getFightTimeByPeriod, saveVestigeRankSchedule, gvgBattlePeriodSchedule } from './gvg/gvgFightService'; +import { gvgBattleEnd } from './gvg/gvgBattleService'; +import { ActivityMonthlyFundModel } from '@db/ActivityMonthlyFund'; +import { getActivityById } from './activity/activityService'; +import { MonthlyFundData } from "@domain/activityField/monthlyFundField"; +import { RewardInter } from '@pubUtils/interface'; +import { stringToRewardInter } from './activity/giftPackageService'; +import { autoCreateServerSchedule } from './serverService'; +import { setHiddenData } from './memoryCache/hiddenData'; +import { SignInData } from '@domain/activityField/signInField'; +import * as util from 'util'; +import { ActivitySignInModel } from '@db/ActivitySignIn'; +import { repairSignInMail } from './activity/signInService'; + + +const PER_SECOND = 1 * 1000; +const PER_DAY = 24 * 60 * 60; +const PER_HOUR = 1 * 60 * 60; +const PER_MINUTE = 1 * 60; +var seasonEndJob: Job; +var seasonMakeRewardTimJobId: Job; +var seasonRefreshTimeJobId: Job; +let guildWeeklyJobId: Job; +let guildActStartJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 +let guildActSecondsJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 +let guildActEndJobId: Job; // 军团活动开启后每10(or 1)秒循环的定时任务,到结束活动清除 + +/** + * 初始定时器 + */ +export async function init() { + + console.log('******* init systimer *******') + + // pvp赛季 + await setPvpSeasonSchedule(); + + // 周功勋结算任务 + guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 5 * * 1', settleGuildWeekly); + + // 每5分钟汇报在线玩家在线情况 + scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule); + + // 每天拉取37词库 + scheduleJob('fetchWord', '0 0 4 * * ?', fetch37Words); + + // 每天邮件 + checkCircleMail(); + // 每小时查询邮件推送 + checkMailByHour(); + + // 军团活动排行榜 + guildActivitySchedule(); + + // 拍卖行刷新:拍卖阶段刷新,分红发放 + auctionSchedule(); + + // 每天5点推送刷新时间消息 + // 顺便每天0点计算前一天活跃玩家中位数战力 + scheduleJob('everyDayRefresh', `0 0 ${REFRESH_TIME} * * ?`, everydayRefresh); + + // 跑马灯 + await initMarquee(); + + // 自动开服 + await initAutoCreateServer(); + + // 限时排行榜 + await initTimeLimitRank(); + + // 名将擂台每日奖励 + await ladderDailyReward(); + + // 团购定时器 + initGroupShopSchedule(); + + // 隐藏数据定时器 + initHiddenDataSchedule(true); + + // gvg每周日 + initGVGConfigSchedule(); + + // 定时推送消息 + initPushMsgSchedule(); + + // 月基金每月未领取 + initMonthlyFundSchedule(); + + // 节日活动高级签到补发 + initVipSignInMailSchedule() +} + +// 每日刷新 +export async function everydayRefresh() { + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + pushRefreshTime(); + setPreDayActiveData(servers); + sendUngotDividendJob(); + sendUnReceivedActivityDailyCoin(servers); + pinus.app.rpc.guild.guildActivityRemote.clearActivityObj.broadcast(); +} + + +// —————————————— PVP 及赛季相关 —————————————— // + +export async function setPvpSeasonSchedule(fromBackend = false) { + let pvpConfig = await PVPConfigModel.setCurrentPvp(); + await setSeasonEndJob(pvpConfig); + await setPvpSeasonMakeRewardJob(pvpConfig); // 发送奖励定时器 + await setNextSeasonJob(pvpConfig); // 赛季开始定时器 + if(fromBackend) { + setPvpSeasonNumToRemote(pvpConfig); + setPvpSettleSeasonNumToRemote(); + } else { + setPvpSeasonNum(pvpConfig); + setPvpSettleSeasonNum(); + } +} + +async function setSeasonEndJob(pvpConfig: PVPConfigType) { + if (!!seasonEndJob) { + seasonEndJob.cancel(); + } + + if(!pvpConfig || pvpConfig.seasonEndTime < nowSeconds()) { + pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); + if(!pvpConfig) return; + } + console.log('####### setSeasonEndJob', JSON.stringify(pvpConfig)) + + seasonEndJob = scheduleJob('seasonEndJob', pvpConfig.seasonEndTime * 1000, async () => { + console.log('************ setSeasonEndJob *********'); + setPvpSeasonNumToRemote(pvpConfig); + let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); + await setSeasonEndJob(nextPvpConfig); + }); +} + +async function setPvpSeasonMakeRewardJob(pvpConfig: PVPConfigType) { + if (!!seasonMakeRewardTimJobId) { + seasonMakeRewardTimJobId.cancel(); + } + if(!pvpConfig || pvpConfig.seasonRewardTime - 60 < nowSeconds()) { + pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); + if(!pvpConfig) return; + } + console.log('####### setPvpSeasonMakeRewardJob', JSON.stringify(pvpConfig)) + seasonMakeRewardTimJobId = scheduleJob('seasonMakeRewardTimJobId', pvpConfig.seasonRewardTime * 1000 - 60 * 1000, async () => { + console.log('************ seasonMakeRewardTimJobId *********'); + await pvpSeasonEnd(pvpConfig.seasonNum); + let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); + await setPvpSeasonMakeRewardJob(nextPvpConfig); + }); +} + +async function setNextSeasonJob(pvpConfig: PVPConfigType) { + if (!!seasonRefreshTimeJobId) { + seasonRefreshTimeJobId.cancel(); + } + if(!pvpConfig || pvpConfig.seasonStartTime < nowSeconds()) { + pvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); + if(!pvpConfig) return; + } + console.log('####### setNextSeasonJob', JSON.stringify(pvpConfig)) + + seasonRefreshTimeJobId = scheduleJob('seasonRefreshTimeJobId', pvpConfig.seasonStartTime * 1000, async () => { + console.log('************ setNextSeasonJob *********'); + setPvpSeasonNumToRemote(pvpConfig); + await PVPConfigModel.setNextPvp(pvpConfig.seasonNum); + let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig.seasonNum + 1); + await setNextSeasonJob(nextPvpConfig); + }); +} + +export async function setPvpSeasonNumToRemote(pvpConfig: PVPConfigType) { + await setPvpSeasonNum(pvpConfig); + await pinus.app.rpc.battle.battleRemote.setPvpSeasonNum.broadcast(pvpConfig); + await pinus.app.rpc.role.roleRemote.setPvpSeasonNum.broadcast(pvpConfig); + await pinus.app.rpc.connector.connectorRemote.setPvpSeasonNum.broadcast(pvpConfig); + + await pinus.app.rpc.guild.guildRemote.setServerGroup.broadcast(); + await pinus.app.rpc.chat.chatRemote.setServerGroup.broadcast(); + await pinus.app.rpc.connector.connectorRemote.setServerGroup.broadcast(); + await pinus.app.rpc.gm.gmRemote.setServerGroup.broadcast(); + await pinus.app.rpc.systimer.systimerRemote.setServerGroup.broadcast(); + await pinus.app.rpc.battle.battleRemote.setServerGroup.broadcast(); +} + +export async function setPvpSeasonNum(pvpConfig?: PVPConfigType) { + if(!pvpConfig) { + pvpConfig = await PVPConfigModel.findCurPVPConfig(); + } + + let now = nowSeconds(); + pinus.app.set('pvpSeasonNum', pvpConfig?.seasonNum||0); + pinus.app.set('pvpSeasonStartTime', pvpConfig?.seasonStartTime||0); + pinus.app.set('pvpSeasonEndTime', pvpConfig?.seasonEndTime||0); + pinus.app.set('pvpSeasonRewardTime', pvpConfig?.seasonRewardTime||0); + if(!pvpConfig || pvpConfig.seasonEndTime <= now) { // 赛季结束,需要显示下一赛季的倒计时 + let nextPvpConfig = await PVPConfigModel.findPVPConfig(pvpConfig? pvpConfig.seasonNum + 1: 1); + if(nextPvpConfig) { + pinus.app.set('pvpSeasonStartTime', nextPvpConfig.seasonStartTime); + } + } +} + +export async function setPvpSettleSeasonNumToRemote(settledPvpConfig?: PVPConfigType) { + setPvpSettleSeasonNum(settledPvpConfig); + await pinus.app.rpc.battle.battleRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); + await pinus.app.rpc.role.roleRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); + await pinus.app.rpc.connector.connectorRemote.setPvpSettleSeasonNum.broadcast(settledPvpConfig); +} + +export async function setPvpSettleSeasonNum(settledPvpConfig?: PVPConfigType) { + if(!settledPvpConfig) { + settledPvpConfig = await PVPConfigModel.getSettledConfig(); + if(!settledPvpConfig) return; + } + pinus.app.set('pvpSettleSeasonNum', settledPvpConfig.seasonNum); +} + +export async function reportOnlineSchedule() { + let allRoles = await getAllOnlineRoles(); + infologger.info('reportOnlineSchedule all roles count: ', allRoles.length); + console.log('reportOnlineSchedule all roles count: ', allRoles.length) + for (let { roleId, userCode, sid } of allRoles) { + let result = reportOneOnline(roleId, userCode, sid, false); + if (!result) continue; + } +} + +// —————————————— PVP 及赛季相关 end —————————————— // + +// —————————————— 军团活动 —————————————— // +/** + * 军团活动,每晚8点开启 + */ +export async function guildActivitySchedule() { + /***********guildActivitySchedule***********/ + if (guildActStartJobId) { + guildActStartJobId.cancel(); + } + + let dicGuildActivity = getTodayGuildActivity(); + // console.log(dicGuildActivity) + + guildActStartJobId = scheduleJob('guildActivityStart', `${dicGuildActivity.startSeconds} ${dicGuildActivity.startMinute} ${dicGuildActivity.startTime} * * ?`, guildActivityStartSchedule); +} + +// 军团晚间活动,每天8点开始 +async function guildActivityStartSchedule() { + await guildActivityStart(); +} + +export async function guildActivityStart(dicGuildActivity?: DicGuildActivity) { + console.log('*******开始军团晚间活动****') + if (!dicGuildActivity) dicGuildActivity = getTodayGuildActivity(); + if (!dicGuildActivity) return; + + console.log('********', dicGuildActivity.id, Date.now() + dicGuildActivity.duringTime * 1000) + let servers = await getAllServers(); // 玩家serverId列表 + console.log('****** guildActSecondsJobId', guildActSecondsJobId) + if (guildActSecondsJobId) { + guildActSecondsJobId.cancel(); + guildActSecondsJobId = undefined; + } + if (guildActEndJobId) { + guildActEndJobId.cancel(); + guildActEndJobId = undefined; + } + + let aid = dicGuildActivity.id; + await incCurGuildActivityIndex(aid); + await pinus.app.rpc.guild.guildActivityRemote.guildActivityStart.broadcast(aid); + + if (aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { + guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', gateActivitySeconds); + // 结束时间 + guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, gateActivityEnd); + } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { + guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/10 * * * * *', cityActivitySeconds); + // 结束时间 + guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, cityActivityEnd); + } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { + + // 开始活动 + let guildServers = pinus.app.getServersByType('guild'); + for (let serverId of servers) { + let sid = await dispatch(redisClient(), serverId.toString(), guildServers, 'guild'); + await pinus.app.rpc.guild.guildActivityRemote.raceActivityStart.toServer(sid.id, serverId); + } + + guildActSecondsJobId = scheduleJob('guildActivitySeconds', '*/2 * * * * *', raceActivitySeconds); + // 结束时间 + guildActEndJobId = scheduleJob('guildActivityEnd', Date.now() + dicGuildActivity.duringTime * 1000, raceActivityEnd); + } + + for (let serverId of servers) { + await sendGuildActivityStatus(serverId); + } + pushClientMsg(SDK_PUSH_MSG_TYPE.GUILD_ACTIVITY_START); + return true; +} + +// 蛮夷入侵 +// 结束军团活动 +export async function gateActivityEnd() { + + console.log('*****gateActivityEnd'); + await sendEndMsgToAllServer(); + await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); + + if (guildActSecondsJobId) { + guildActSecondsJobId.cancel(); + guildActSecondsJobId = undefined; + } + if (guildActEndJobId) { + guildActEndJobId.cancel(); + guildActEndJobId = undefined; + } + checkPopUpConditionWhenGuildActivityEnd(); +} + +// 每10秒下发一次的任务 +export async function gateActivitySeconds() { + console.log('*****gateActivitySeconds') + await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.GATE_ACTIVITY); +} + +// 诸侯混战 +// 结束军团活动 +export async function cityActivityEnd() { + console.log('*****cityActivityEnd'); + await sendEndMsgToAllServer(); + await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); + + // 发完之后再做下周自动宣战 + // await autoDeclare(); + if (guildActSecondsJobId) { + guildActSecondsJobId.cancel(); + guildActSecondsJobId = undefined; + } + if (guildActEndJobId) { + guildActEndJobId.cancel(); + guildActEndJobId = undefined; + } + checkPopUpConditionWhenGuildActivityEnd(); +} + +// 每10秒下发一次的任务 +export async function cityActivitySeconds() { + console.log('*****cityActivitySeconds') + await pinus.app.rpc.guild.guildActivityRemote.sendRankToGuilds.broadcast(GUILD_ACTIVITY_TYPE.CITY_ACTIVITY); +} + +// 粮草先行 +// 结束军团活动 +export async function raceActivityEnd() { + console.log('*****raceActivityEnd'); + await sendEndMsgToAllServer(); + await pinus.app.rpc.guild.guildActivityRemote.guildActivityEnd.broadcast(GUILD_ACTIVITY_TYPE.RACE_ACTIVITY); + + if (guildActSecondsJobId) { + guildActSecondsJobId.cancel(); + guildActSecondsJobId = undefined; + } + if (guildActEndJobId) { + guildActEndJobId.cancel(); + guildActEndJobId = undefined; + } + checkPopUpConditionWhenGuildActivityEnd(); +} + +// 每10秒下发一次的任务 +export async function raceActivitySeconds() { + console.log('*****raveActivitySeconds') + let servers = await getAllServers(); // 玩家serverId列表 + let guildServers = pinus.app.getServersByType('guild'); + for (let serverId of servers) { + let sid = await dispatch(redisClient(), serverId.toString(), guildServers, 'guild'); + await pinus.app.rpc.guild.guildActivityRemote.calWoodenHorseAndSend.toServer(sid.id, serverId); + } +} + +// —————————————— 军团活动 end —————————————— // + +// —————————————— 拍卖行 —————————————— // + +let startGuildAuctionJobId: Job; +let startWorldAuctionJobId: Job; +let stopAuctionJobId: Job; +let startDividendJobId: Job; + +export async function auctionSchedule() { + clearAuctionSchedule(); + let guildOpen = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN); + let worldOpen = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN); + let worldClose = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE); + let dividendStart = gameData.auctionTime.get(AUCTION_TIME.DIVIDEND_START); + + // console.log('***** auctionSchedule', guildOpen.hour, guildOpen.minute, guildOpen.seconds); + // console.log('***** auctionSchedule', worldOpen.hour, worldOpen.minute, worldOpen.seconds); + // console.log('***** auctionSchedule', worldClose.hour, worldClose.minute, worldClose.seconds); + startGuildAuctionJobId = scheduleJob('startGuildAuction', `${guildOpen.seconds} ${guildOpen.minute} ${guildOpen.hour} * * ?`, startGuildAuction); + startWorldAuctionJobId = scheduleJob('startWorldAuction', `${worldOpen.seconds} ${worldOpen.minute} ${worldOpen.hour} * * ?`, startWorldAuction); + startDividendJobId = scheduleJob('startDividend', `${dividendStart.seconds} ${dividendStart.minute} ${dividendStart.hour} * * ?`, startDividend); + stopAuctionJobId = scheduleJob('stopAuction', `${worldClose.seconds} ${worldClose.minute} ${worldClose.hour} * * ?`, stopAuction); + +} + +function clearAuctionSchedule() { + if (startGuildAuctionJobId) { + startGuildAuctionJobId.cancel(); + startGuildAuctionJobId = undefined; + } + if (startWorldAuctionJobId) { + startWorldAuctionJobId.cancel(); + startWorldAuctionJobId = undefined; + } + if (stopAuctionJobId) { + stopAuctionJobId.cancel(); + stopAuctionJobId = undefined; + } +} + +// —————————————— 拍卖行 end —————————————— // + +// —————————————— 邮件 —————————————— // +let circleMailJob: Job; +async function checkCircleMail() { + if(circleMailJob) { + circleMailJob.cancel(); + } + circleMailJob = scheduleJob('circleMail', '0 0 20 * * ?', scheduleSendCircleMail); + // scheduleSendCircleMail(); +} + +async function scheduleSendCircleMail() { + let gmmails = await GMMailModel.findCircleMails(pinus.app.get('env')); + await sendMailsByGmMail(gmmails); +} + + +let mailByHourJob: Job; +async function checkMailByHour() { + if(mailByHourJob) { + mailByHourJob.cancel(); + } + // 每小时一次,为了和每天循环邮件任务不重复,设在每小时05分 + mailByHourJob = scheduleJob('setMailTimerByHour', '0 5 0/1 * * ?', async () => { + await setMailSchedule(false) + }); + setMailSchedule(true); // 初始时候启动一次 +} + +async function setMailSchedule(isInit: boolean) { + let minuteNow = moment().minute(); + let beforeTime = minuteNow >= 5? moment().minute(5).unix(): moment().minute(5).add(-1, 'h').unix(); + let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix(); + + let mails = await MailModel.findByTimeGap(beforeTime, time); + let groupMails = await GroupMailModel.findByTimeGap(beforeTime, time); + let serverMails = await ServerMailModel.findByTimeGap(beforeTime, time); + + let times: number[] = []; + for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) { + if(times.indexOf(sendTime) == -1) times.push(sendTime); + } + + for(let time of times) { + if(Date.now() > time * 1000) { + if(!isInit) await pushMailSchedule(time); + } else { + scheduleJob(`mailPush${time}`, time * 1000, async () => { + await pushMailSchedule(time); + }); + } + } +} + +// 当前时间到下一次定时器之间的定时器 +export async function addMailsToSchedule(mails: MailType[], groupMails: GroupMailType[], serverMails: ServerMailType[]) { + let minuteNow = moment().minute(); + let time = minuteNow >= 5? moment().minute(5).add(1, 'h').unix(): moment().minute(5).unix(); + + let times: number[] = []; + for(let { sendTime } of [...mails, ...groupMails, ...serverMails]) { + if(sendTime * 1000 > Date.now() && sendTime < time && times.indexOf(sendTime) == -1) times.push(sendTime); + } + + for(let time of times) { + if(!scheduledJobs[`mailPush${time}`]) { + scheduleJob(`mailPush${time}`, time * 1000, async () => { + await pushMailSchedule(time); + }) + } + } +} + +async function pushMailSchedule(time: number) { + if(scheduledJobs[`mailPush${time}`]) scheduledJobs[`mailPush${time}`].cancel(); + + let mails = await MailModel.findBySendTime(time); + let groupMails = await GroupMailModel.findBySendTime(time); + let serverMails = await ServerMailModel.findBySendTime(time); + + let f = new SendMailFun(); + f.setMails(mails, groupMails, serverMails); + await f.pushToUsers(); +} + +// —————————————— 邮件 end —————————————— // + +// —————————————— 维护 —————————————— // +let maintenInfos = new Map(); // batchCode => {servers, maintenance} +export async function initMaintenance(servers?: ServerlistType[], fromApp = false) { + if(!servers) servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + + for(let server of servers) { + let { maintenance } = server; + if(maintenance && maintenance.isOpen) { + if(!maintenInfos.has(maintenance.batchCode)) { + maintenInfos.set(maintenance.batchCode, { servers: [], maintenance }); + } + maintenInfos.get(maintenance.batchCode).servers.push(server); + } + } + for(let [batchCode] of maintenInfos) { + await setMaintenance(batchCode, fromApp); + } +} + +export async function initMaintenanaceInOtherServers() { + const servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + + for(let server of servers) { + let { id, maintenance } = server; + if(maintenance && maintenance.isOpen) { + setServerMainten([id], maintenance.startTime, maintenance.endTime, maintenance.version) + } + } +} + +// 设置维护 +async function setMaintenance(batchCode: string, fromApp: boolean) { + let { maintenance } = maintenInfos.get(batchCode); + + console.log('***** maintenance', maintenance); + + let now = nowSeconds(); + // 发送消息 + if(maintenance.hasNotify && now < maintenance.startTime) { // 提前5分钟发通知 + if(now > maintenance.startTime - 5 * 60) { + maintenanceNotifySchedule(batchCode); + } else { + if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); + scheduleJob(`maintenNotify${batchCode}`, (maintenance.startTime - 5 * 60) * 1000, () => { + maintenanceNotifySchedule(batchCode); + }) + } + } else { + if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); + } + // 开始维护 + console.log('******* setMaintenance', now, now < maintenance.endTime, now > maintenance.startTime) + if(now < maintenance.endTime) { + if(now > maintenance.startTime) { + if(!fromApp) await startMaintenanceSchedule(batchCode); + } else { + scheduleJob(`startMainten${batchCode}`, maintenance.startTime * 1000, async () => { + await startMaintenanceSchedule(batchCode); + }); + } + } else { + if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); + } + +} + +// 维护前通知 +async function maintenanceNotifySchedule(batchCode: string) { + let { servers, maintenance } = maintenInfos.get(batchCode); + if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); + if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); + + scheduleJob(`maintenSec${batchCode}`, `0 */1 * * * *`, async () => { + for(let { id: serverId } of servers) { + let msgData = await createMarqueeMsg('', '系统', serverId, '服务器即将维护,请玩家提前退出游戏'); + await pushMarqueeMsg(msgData); + } + }) +} + +// 开始维护 +async function startMaintenanceSchedule(batchCode: string) { + let { servers, maintenance } = maintenInfos.get(batchCode); + let serverIds = servers.map(cur => cur.id); + if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); + if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); + if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); + + // 向全服发送 + for(let { id: serverId } of servers) { + await sendMessageToServer(serverId, PUSH_ROUTE.SERVER_MAINTENANCE, resResult(STATUS.SERVER_MAINTENANCE)); + } + + // 更新connectorRemote里面的维护服务器 + console.log('******** startMaintenanceSchedule', batchCode, serverIds, maintenance.startTime, maintenance.endTime) + pinus.app.rpc.connector.connectorRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.activity.activityRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.battle.battleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.comBattle.comBattleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.chat.chatRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.guild.guildRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.order.orderRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + pinus.app.rpc.role.roleRemote.setServerMainten.broadcast(serverIds, maintenance.startTime, maintenance.endTime, maintenance.version); + // 数数flush + pinus.app.rpc.activity.activityRemote.taflush.broadcast(); + pinus.app.rpc.battle.battleRemote.taflush.broadcast(); + pinus.app.rpc.chat.chatRemote.taflush.broadcast(); + pinus.app.rpc.connector.connectorRemote.taflush.broadcast(); + pinus.app.rpc.guild.guildRemote.taflush.broadcast(); + pinus.app.rpc.order.orderRemote.taflush.broadcast(); + pinus.app.rpc.role.roleRemote.taflush.broadcast(); + pinus.app.rpc.systimer.systimerRemote.taflush.broadcast(); +} + +// 提前结束维护 +export async function stopMaintenance(batchCode: string, serverIds: number[]) { + // console.log('***********', serverIds) + let { servers = [], maintenance = {} as Maintenance } = maintenInfos.get(batchCode)||{}; + for(let id of serverIds) { + let index = servers.findIndex(cur => cur.id == id); + if(index != -1) servers.splice(index); + } + if(servers.length == 0) { + if(scheduledJobs[`maintenNotify${batchCode}`]) scheduledJobs[`maintenNotify${batchCode}`].cancel(); + if(scheduledJobs[`maintenSec${batchCode}`]) scheduledJobs[`maintenSec${batchCode}`].cancel(); + if(scheduledJobs[`startMainten${batchCode}`]) scheduledJobs[`startMainten${batchCode}`].cancel(); + maintenInfos.delete(batchCode); + } + + // 更新connectorRemote里面的维护服务器 + pinus.app.rpc.connector.connectorRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.activity.activityRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.battle.battleRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.comBattle.comBattleRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.chat.chatRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.guild.guildRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.order.orderRemote.stopServerMainten.broadcast(serverIds); + pinus.app.rpc.role.roleRemote.stopServerMainten.broadcast(serverIds); +} + +// —————————————— 维护 end —————————————— // +// —————————————— 自动开服 —————————————— // +export async function initAutoCreateServer() { + scheduleJob('autoServer', '0 0 */1 * * ?', autoCreateServerSchedule) +} + +// —————————————— 自动开服 end —————————————— // + +// —————————————— 活动 start —————————————— // +async function initTimeLimitRank() { + let activities = await ActivityModel.findActivityByType(ACTIVITY_TYPE.TIME_LIMIT_RANK); + await updateTimeLimitRank(activities); +} + +export async function updateTimeLimitRank(activities: ActivityModelType[]) { + for(let activity of activities) { + let { activityId } = activity + let group = await ActivityGroupModel.findByActivity(activityId); + for(let { serverIds } of group) { + let servers = await ServerlistModel.findByServerIds(serverIds); + for(let { env, openTime, id: serverId } of servers) { + if(env == pinus.app.get('env')) { + let data = new TimeLimitRankData(activity, 0, openTime); + if(data.sendMailTime > Date.now()) { + await setSendRankMailSchedule(activityId, serverId, data); + } + if(data.rankEndTime > Date.now() && data.needSnapshot()) { + await setTakeRankSnapshotSchedule(activityId, serverId, data); + } + } + } + } + } +} + +async function setSendRankMailSchedule(activityId: number, serverId: number, data: TimeLimitRankData) { + console.log('########### setSendRankMailSchedule1 ########', activityId, serverId, data.sendMailTime) + if(scheduledJobs[`rankMail_${serverId}_${activityId}`]) { + scheduledJobs[`rankMail_${serverId}_${activityId}`].cancel(); + } + + scheduleJob(`rankMail_${serverId}_${activityId}`, data.sendMailTime, async () => { + console.log('########### setSendRankMailSchedule2 ########') + await sendRankMail(data, serverId); + }); +} + + +async function setTakeRankSnapshotSchedule(activityId: number, serverId: number, data: TimeLimitRankData) { + console.log('########### setTakeRankSnapshotSchedule1 ########', activityId, serverId, data.rankEndTime) + + if(scheduledJobs[`snapshot_${serverId}_${activityId}`]) { + scheduledJobs[`snapshot_${serverId}_${activityId}`].cancel(); + } + + scheduleJob(`snapshot_${serverId}_${activityId}`, data.rankEndTime, async () => { + console.log('########### setTakeRankSnapshotSchedule2 ########') + await takeSnapshot(data, serverId); + }) +} +// —————————————— 活动 end —————————————— // + +// —————————————— 名将擂台 start —————————————— // +export async function setLadderCountDown(battleCode: string, time: number, status: LADDER_STATUS) { + if(scheduledJobs[`ladder${battleCode}`]) { + scheduledJobs[`ladder${battleCode}`].cancel(); + } + let endTime = time + (status == LADDER_STATUS.CHECK? LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN: LADDER.LADDER_BATTLE_COUNTDOWN) * 1000; + scheduleJob(`ladder${battleCode}`, endTime, async () => { + await ladderTimeWillout(battleCode, status); + + scheduledJobs[`ladder${battleCode}`].cancel(); + scheduleJob(`ladder${battleCode}`, endTime + LADDER_SERVER_GAP_TIME * 1000, async () => { + await ladderTimeout(battleCode, status); + scheduledJobs[`ladder${battleCode}`].cancel(); + }); + }) +} + +export async function cancelLadderCountDown(battleCode: string) { + if(scheduledJobs[`ladder${battleCode}`]) { + scheduledJobs[`ladder${battleCode}`].cancel(); + } +} + +async function ladderDailyReward() { + scheduleJob('ladderDailyReward', '0 0 22 * * ?', async () => { + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + for(let { id } of servers) { + await sendLadderDailyReward(id); + } + }); + let recs = await LadderMatchRecModel.getUncompleteData(); + let battleCodes: string[] = []; + for(let { battleCode, checkTime, battleTime, status, serverId, defenseInfo } of recs) { + if(status == LADDER_STATUS.CHECK) { + if(Date.now() > checkTime + LADDER.LADDER_BATTLE_PREPARE_COUNTDOWN * 1000) { + battleCodes.push(battleCode); + await LadderMatchModel.unlock(serverId, defenseInfo?.roleId); + } else { + await setLadderCountDown(battleCode, checkTime, status) + } + } else if (status == LADDER_STATUS.BATTLE) { + if(Date.now() > battleTime + LADDER.LADDER_BATTLE_COUNTDOWN * 1000 ) { + battleCodes.push(battleCode); + await LadderMatchModel.unlock(serverId, defenseInfo?.roleId); + } else { + await setLadderCountDown(battleCode, battleTime, status) + } + } + } + await LadderMatchRecModel.timeoutMany(battleCodes); +} +// —————————————— 名将擂台 end —————————————— // + +// —————————————— 团购定时器 start —————————————— // +async function initGroupShopSchedule() { + initSumSchedule(); + scheduleJob('groupShopRefund', '0 30 5 * * ?', () => { + refundGroupShop(); + }); +} + +let initSumJobs = []; +export async function initSumSchedule() { + let servers = await ServerlistModel.findByEnv(pinus.app.get('env')); + let groupIds: number[] = []; + for(let { id } of servers) { + let groups = await ActivityGroupModel.findByServerId(id); + for(let { groupId } of groups) { + groupIds.push(groupId); + } + } + + let activities = await ActivityModel.findOpenActivityByType(groupIds, ACTIVITY_TYPE.GROUP_SHOP); + let scheduleMap = new Map(); // 时间 => data + for(let activity of activities) { + let timers = await getGroupShopTimers(activity); + for(let { time, itemId, sum } of timers) { + if(time < Date.now()) continue; + if(!scheduleMap.has(time)) { + scheduleMap.set(time, []); + } + scheduleMap.get(time).push({ activityId: activity.activityId, itemId, sum }); + } + } + + console.log('#### initSumJobs', initSumJobs.length); + console.log('#### scheduleMap', scheduleMap); + for(let job of initSumJobs) { + job.cancel(); + } + for(let [time, arr] of scheduleMap) { + if(scheduledJobs[`groupShopSetSum${time}`]) { + scheduledJobs[`groupShopSetSum${time}`].cancel(); + } + let job = scheduleJob(`groupShopSetSum${time}`, time, async () => { + await setGroupShopToSetSum(arr); + }); + initSumJobs.push(job); + } +} + +// —————————————— 团购定时器 end —————————————— // + +// —————————————— 配表兼容 start —————————————— // +let hiddenDataJob: Job; +export async function initHiddenData(data?: HiddenDataModelType, nextData?: HiddenDataModelType) { + let now = nowSeconds(); + if(!data) data = await HiddenDataModel.findCurData(now); + if(!nextData) nextData = await HiddenDataModel.findNextData(now); + setHiddenData(data?.heroes, data?.goods, nextData?.refTime); +} + +export async function initHiddenDataSchedule(isInit: boolean) { + if(hiddenDataJob) hiddenDataJob.cancel(); + let now = nowSeconds(); + let data = await HiddenDataModel.findCurData(now); + let nextData = await HiddenDataModel.findNextData(data?.refTime??now); + + if(isInit) { + await initHiddenData(data, nextData) + } else { + await setHiddenDataToMemory(data, nextData); + } + console.log('######## initHiddenDataSchedule', nextData); + if(nextData) { + if(scheduledJobs['hiddenData']) scheduledJobs['hiddenData'].cancel(); + scheduleJob(`hiddenData`, nextData.refTime * 1000, async () => { + console.log('######## hiddenDataSchedule', nextData); + + await initHiddenDataSchedule(false); + }); + } +} +// —————————————— 配表兼容 end —————————————— // + +// —————————————— gvg start —————————————— // +let gvgBattleSecondJob: Job; // gvg每5秒的定时器 +let gvgBattleCatapultJob: Job; // gvg投石车定时器 + +export async function initGVGConfigSchedule() { + let config = await GVGConfigModel.findConfig(); + if(!config || nowSeconds() > config.scheduleTime) { + config = await createNewGVGConfig(); + } + + if(scheduledJobs[`gvgTeam`]) scheduledJobs[`gvgTeam`].cancel(); + scheduleJob(`gvgTeam`, config.teamTime * 1000, async () => { + await pinus.app.rpc.guild.guildRemote.setGVGConfig.broadcast(config); + }) + if(scheduledJobs[`gvgConfig`]) scheduledJobs[`gvgConfig`].cancel(); + scheduleJob(`gvgConfig`, config.scheduleTime * 1000, createNewGVGConfig); + + if(nowSeconds() > config.prepareTime) { + initLeaguePrepare(); + } else { + if(scheduledJobs[`gvgPrepare`]) scheduledJobs[`gvgPrepare`].cancel(); + scheduleJob(`gvgPrepare`, config.prepareTime * 1000, initLeaguePrepare); + } + + if(scheduledJobs[`gvgFight`]) scheduledJobs[`gvgFight`].cancel(); + scheduleJob(`gvgFight`, '0 30 22 * * ?', saveVestigeRankSchedule); + + if(scheduledJobs[`gvgBattle`]) scheduledJobs[`gvgBattle`].cancel(); + scheduleJob(`gvgBattle`, config.battleTime * 1000, gvgBattlePeriodSchedule); + + let { startFightTime, endFightTime } = getFightTimeByPeriod(GVG_PERIOD.BATTLE, config.battleTime); + + if(nowSeconds() > startFightTime - GVG.GVG_GUARD_START_TIME && nowSeconds() < endFightTime) { + if(gvgBattleSecondJob) gvgBattleSecondJob.cancel(); + gvgBattleSecondJob = scheduleJob('gvgBattleSecond', '*/5 * * * * *', gvgBattleSecondSchedule); + if(gvgBattleCatapultJob) gvgBattleCatapultJob.cancel(); + gvgBattleCatapultJob = scheduleJob('gvgBattleCatapult', `*/${GVG.GVG_CATAPULT_TIME} * * * * *`, gvgBattleCatapult); + } else { + scheduleJob(`gvgBattleStartSchedule`, (startFightTime - GVG.GVG_GUARD_START_TIME) * 1000, gvgBattleStartSchedule); + } + if(scheduledJobs[`gvgBattleEndSchedule`]) scheduledJobs[`gvgBattleEndSchedule`].cancel(); + scheduleJob(`gvgBattleEndSchedule`, endFightTime * 1000, gvgBattleEndSchedule); +} + +// gvg激战期开始定时器 +export async function gvgBattleStartSchedule() { + console.log('##### gvgBattleStartSchedule', Date.now()) + if(gvgBattleSecondJob) gvgBattleSecondJob.cancel(); + gvgBattleSecondJob = scheduleJob('gvgBattleSecond', '*/5 * * * * *', gvgBattleSecondSchedule); + + // 初始化投石车 + let guildServers = pinus.app.getServersByType('guild'); + if(guildServers.length > 0) { + pinus.app.rpc.guild.guildRemote.gvgBattleStart.toServer(getRandSingleEelm(guildServers).id); + } + if(gvgBattleCatapultJob) gvgBattleCatapultJob.cancel(); + gvgBattleCatapultJob = scheduleJob('gvgBattleCatapult', `*/${GVG.GVG_CATAPULT_TIME} * * * * *`, gvgBattleCatapult); + + setTimeout(() => { + pushClientMsg(SDK_PUSH_MSG_TYPE.GVG_BATTLE_START); + }, GVG.GVG_GUARD_START_TIME * 1000); +} + +// 每隔5秒的积分计算定时器 +async function gvgBattleSecondSchedule() { + console.log('********** gvgBattleSecondJob *************'); + pinus.app.rpc.guild.guildRemote.gvgBattleSeconds.broadcast(); +} + +// 每隔10秒的投石车投机定时器 +async function gvgBattleCatapult() { + console.log('********** gvgBattleCatapultJob *************'); + pinus.app.rpc.guild.guildRemote.catapultHurt.broadcast(); +} + +// gvg激战期结束定时器 +export async function gvgBattleEndSchedule() { + let guildServers = pinus.app.getServersByType('guild'); + if(guildServers.length > 0) { + pinus.app.rpc.guild.guildRemote.gvgBattleEnd.toServer(getRandSingleEelm(guildServers).id); + } + // 定时器关闭 + if(gvgBattleSecondJob) { + gvgBattleSecondJob.cancel(); + gvgBattleSecondJob = undefined; + } + if(gvgBattleCatapultJob) { + gvgBattleCatapultJob.cancel(); + gvgBattleCatapultJob = undefined; + } + +} +// —————————————— gvg end —————————————— // + +async function initPushMsgSchedule() { + scheduleJob('sendDinner', '0 0 19 * * ?', async () => { + // pushClientMsg(SDK_PUSH_MSG_TYPE.AFK_ATTENTION); + pushClientMsg(SDK_PUSH_MSG_TYPE.AP_DINNER); + }); + scheduleJob('sendLunch', '0 0 12 * * ?', async () => { + pushClientMsg(SDK_PUSH_MSG_TYPE.AP_LUNCH); + }); +} + +// 月基金未领取的发送到邮件,每月发送 +async function initMonthlyFundSchedule() { + scheduleJob('initMonthlyFundSchedule', '0 0 5 1 * ?', async () => { + let roundIndex = parseInt(moment().add(-1, 'M').format('YYYYMM')); + await monthlyFundSchedule(roundIndex); + }); +} + +// 高级签到自动补发 +export async function initVipSignInMailSchedule() { + let activities = await ActivityModel.findOpenTypeByTime(ACTIVITY_TYPE.COMMON_SIGN_IN); + for(let activityData of activities) { + let playerData = new SignInData(activityData, 0, 0); + if(!playerData || playerData.productID == '&') continue; + + const jobKey = `vipSignMailJob${playerData.activityId}`; + if(scheduledJobs[jobKey]) scheduledJobs[jobKey].cancel(); + scheduleJob(jobKey, playerData.endTime, async () => { + await repairSignInMail(playerData); + }); + } +} + +export async function monthlyFundSchedule(roundIndex: number) { + let activityMap = new Map(); + let playerDatas = await ActivityMonthlyFundModel.findNotReceivedReward(roundIndex); + let _ids: string[] = []; + for(let playerData of playerDatas) { + if(!activityMap.has(playerData.activityId)) { + let activity = await getActivityById(playerData.activityId); + activityMap.set(playerData.activityId, activity); + } + let activityData = activityMap.get(playerData.activityId); + if(!activityData) continue; + let data = new MonthlyFundData(activityData, 0, 0); + let page = data.findPage(playerData.pageIndex); + page.setPlayerRecord(playerData); + let rewards: RewardInter[] = []; + for(let { reward, hasReceived } of page.rewards) { + if(!hasReceived) rewards.push(...stringToRewardInter(reward)); + } + if(rewards.length > 0) { + await sendMailByContent(MAIL_TYPE.MONTHLY_FUND, playerData.roleId, { goods: rewards }); + } + _ids.push(playerData._id); + } + await ActivityMonthlyFundModel.updateHasReceivedAll(_ids); +} diff --git a/game-server/app/services/utilService.ts b/game-server/app/services/utilService.ts index 5bd26e267..6f7ed772d 100644 --- a/game-server/app/services/utilService.ts +++ b/game-server/app/services/utilService.ts @@ -1,6 +1,6 @@ -import { pinus } from "pinus"; -import { isDevelopEnv as pubIsDevelopEnv } from '../pubUtils/util'; - -export function isDevelopEnv() { - return pubIsDevelopEnv(pinus.app.get('env')); -} \ No newline at end of file +import { pinus } from "pinus"; +import { isDevelopEnv as pubIsDevelopEnv } from '@pubUtils/util'; + +export function isDevelopEnv() { + return pubIsDevelopEnv(pinus.app.get('env')); +} diff --git a/game-server/app/services/warRewardService.ts b/game-server/app/services/warRewardService.ts index f0c7e1de4..a10ea6b22 100644 --- a/game-server/app/services/warRewardService.ts +++ b/game-server/app/services/warRewardService.ts @@ -1,163 +1,163 @@ -/** - * 战场奖励发放 对象 - * 支持战场相关的奖励格式,目前包括fixedReward, randomReward, conditionReward - */ - -import { BattleDropModel } from '../db/BattleDrop'; -import { getRandEelmWithWeight, getRandSingleEelm, getReasonByWarType } from '../pubUtils/util'; -import { BATTLE_REWARD_TYPE, BLUEPRT_CONST } from '../consts'; -import { addItems } from './role/rewardService'; -import { gameData } from '../pubUtils/data'; -import { DicWar } from '../pubUtils/dictionary/DicWar'; -import { RewardInter } from '../pubUtils/interface'; -import { combineItems } from './role/util'; - -export class WarReward { - private roleId: string; - private roleName: string; - private sid: string; - private battleId: number; - private condition: Map; - private warInfo: DicWar; - private isSuccess: boolean; - private rewards: Array<{type?: number, id: number, count: number, times?: number}> = []; - private fixReward: Array<{id: number, count: number}> = []; - private conditionReward: Array<{id: number, count: number, condition: number}> = []; - private randomReward: Array<{id: number, count: number, frequency: number}> = []; - private ladderReward: Array<{id: number, count: number, weight: number, isSuccess: boolean}> = []; - private costAp: number; - - constructor(roleId: string, roleName: string, sid: string, battleId: number, isSuccess: boolean) { - this.roleId = roleId; - this.roleName = roleName; - this.sid = sid; - if(battleId) { - this.battleId = battleId; - this.warInfo = gameData.war.get(battleId); - let { fixReward, conditionReward, randomReward } = this.warInfo; - this.setFixReward(fixReward); - this.setConditionReward(conditionReward); - this.setRandomReward(randomReward); - } - this.condition = new Map(); - - this.isSuccess = isSuccess; - this.costAp = this.warInfo.cost; - } - - public setCondition(id: number, isOk: boolean) { - this.condition.set(id, isOk); - } - - public setFixReward(reward: RewardInter[]) { - for(let r of reward) { - // console.log('#####setFixReward', JSON.stringify(r)); - this.fixReward.push(r); - } - } - - public resetFixReward(reward: RewardInter[]) { - this.fixReward = reward; - } - - public setConditionReward(reward: {id: number, count: number, condition: number}[]) { - for(let r of reward) { - this.conditionReward.push(r); - } - } - - public setRandomReward(reward: {id: number, count: number, frequency: number}[]) { - for(let r of reward) { - this.randomReward.push(r); - } - } - - public setLadderReward(reward: {id: number, count: number, weight: number}[], isSuccess: boolean) { - for(let r of reward) { - this.ladderReward.push({...r, isSuccess}); - } - } - - private handleFixReward(num: number) { - if(!this.fixReward) return - for(let i = 0; i < num; i++) { - for(let obj of this.fixReward) { - // console.log('##### handleFixReward', JSON.stringify(obj)); - this.rewards.push({type: BATTLE_REWARD_TYPE.FIX_REWARD, times: i +1, ...obj, count: obj.count }); - } - } - } - private handleConditionReward(num: number) { - if(!this.conditionReward) return - for(let i = 0; i < num; i++) { - for(let obj of this.conditionReward) { - if(this.condition.get(obj.condition)) { - this.rewards.push({type: BATTLE_REWARD_TYPE.CONDITION_REWARD, times: i +1, ...obj, count: obj.count}); - } - } - } - } - - private async handleRandomReward(num: number) { - if(!this.randomReward) return - for(let obj of this.randomReward) { - let { id, frequency } = obj; - let dropHistory = await BattleDropModel.findByGid(this.roleId, this.battleId, id); - let { getNum = 0, allNum = 0, getSum = 0, allSum = 0 } = dropHistory; - for(let i = 0; i < num; i ++) { - let flag = false; // 是否可以获得 - if(allNum >= frequency) { - allNum = 0; getNum = 0; - } - allNum++; allSum++; - if(getNum == 0) { - let r = Math.random(); - if(r <= 1/frequency*allNum || (allNum >= frequency) ) { - flag = true; // 独立概率随机 - } - } - if(flag) { - getNum ++; getSum++; - this.rewards.push({type: BATTLE_REWARD_TYPE.RANDOM_REWARD, times: i +1, ...obj}); - } - } - await BattleDropModel.updateByGid(this.roleId, this.battleId, id, { - getNum, allNum, getSum, allSum - }); - } - } - - private async handleLadderReward(num: number, isSuccess: boolean) { - if(!this.ladderReward) return; - for(let i = 0; i < num; i++) { - let arr = this.ladderReward.filter(cur => cur.isSuccess == isSuccess); - let { dic: reward } = getRandEelmWithWeight(arr); - if(reward) { - this.rewards.push({type: BATTLE_REWARD_TYPE.RANDOM_REWARD, times: i +1, id: reward.id, count: reward.count }); - } - } - } - - public async saveReward(num: number, combine: boolean = false) { - this.rewards = new Array(); - // let warType = this.warInfo.warType; - - if(this.isSuccess) { // 成功了才给固定奖励 - // console.log(this.fixReward) - if(this.fixReward) this.handleFixReward(num); - if(this.conditionReward) this.handleConditionReward(num); - if(this.randomReward) await this.handleRandomReward(num); - - // if(this.costAp > 0) await this.handlerBlueprtReward(num); - } - if(this.ladderReward) this.handleLadderReward(num, this.isSuccess); - - let rewards = this.rewards; - if(combine) { - rewards = combineItems(rewards); - } - console.log('##### saveReward', JSON.stringify(rewards)) - await addItems(this.roleId, this.roleName, this.sid, rewards, getReasonByWarType(this.warInfo.warType)); - return rewards; - } -} \ No newline at end of file +/** + * 战场奖励发放 对象 + * 支持战场相关的奖励格式,目前包括fixedReward, randomReward, conditionReward + */ + +import { BattleDropModel } from '@db/BattleDrop'; +import { getRandEelmWithWeight, getRandSingleEelm, getReasonByWarType } from '@pubUtils/util'; +import { BATTLE_REWARD_TYPE, BLUEPRT_CONST } from '@consts'; +import { addItems } from './role/rewardService'; +import { gameData } from '@pubUtils/data'; +import { DicWar } from '@pubUtils/dictionary/DicWar'; +import { RewardInter } from '@pubUtils/interface'; +import { combineItems } from './role/util'; + +export class WarReward { + private roleId: string; + private roleName: string; + private sid: string; + private battleId: number; + private condition: Map; + private warInfo: DicWar; + private isSuccess: boolean; + private rewards: Array<{type?: number, id: number, count: number, times?: number}> = []; + private fixReward: Array<{id: number, count: number}> = []; + private conditionReward: Array<{id: number, count: number, condition: number}> = []; + private randomReward: Array<{id: number, count: number, frequency: number}> = []; + private ladderReward: Array<{id: number, count: number, weight: number, isSuccess: boolean}> = []; + private costAp: number; + + constructor(roleId: string, roleName: string, sid: string, battleId: number, isSuccess: boolean) { + this.roleId = roleId; + this.roleName = roleName; + this.sid = sid; + if(battleId) { + this.battleId = battleId; + this.warInfo = gameData.war.get(battleId); + let { fixReward, conditionReward, randomReward } = this.warInfo; + this.setFixReward(fixReward); + this.setConditionReward(conditionReward); + this.setRandomReward(randomReward); + } + this.condition = new Map(); + + this.isSuccess = isSuccess; + this.costAp = this.warInfo.cost; + } + + public setCondition(id: number, isOk: boolean) { + this.condition.set(id, isOk); + } + + public setFixReward(reward: RewardInter[]) { + for(let r of reward) { + // console.log('#####setFixReward', JSON.stringify(r)); + this.fixReward.push(r); + } + } + + public resetFixReward(reward: RewardInter[]) { + this.fixReward = reward; + } + + public setConditionReward(reward: {id: number, count: number, condition: number}[]) { + for(let r of reward) { + this.conditionReward.push(r); + } + } + + public setRandomReward(reward: {id: number, count: number, frequency: number}[]) { + for(let r of reward) { + this.randomReward.push(r); + } + } + + public setLadderReward(reward: {id: number, count: number, weight: number}[], isSuccess: boolean) { + for(let r of reward) { + this.ladderReward.push({...r, isSuccess}); + } + } + + private handleFixReward(num: number) { + if(!this.fixReward) return + for(let i = 0; i < num; i++) { + for(let obj of this.fixReward) { + // console.log('##### handleFixReward', JSON.stringify(obj)); + this.rewards.push({type: BATTLE_REWARD_TYPE.FIX_REWARD, times: i +1, ...obj, count: obj.count }); + } + } + } + private handleConditionReward(num: number) { + if(!this.conditionReward) return + for(let i = 0; i < num; i++) { + for(let obj of this.conditionReward) { + if(this.condition.get(obj.condition)) { + this.rewards.push({type: BATTLE_REWARD_TYPE.CONDITION_REWARD, times: i +1, ...obj, count: obj.count}); + } + } + } + } + + private async handleRandomReward(num: number) { + if(!this.randomReward) return + for(let obj of this.randomReward) { + let { id, frequency } = obj; + let dropHistory = await BattleDropModel.findByGid(this.roleId, this.battleId, id); + let { getNum = 0, allNum = 0, getSum = 0, allSum = 0 } = dropHistory; + for(let i = 0; i < num; i ++) { + let flag = false; // 是否可以获得 + if(allNum >= frequency) { + allNum = 0; getNum = 0; + } + allNum++; allSum++; + if(getNum == 0) { + let r = Math.random(); + if(r <= 1/frequency*allNum || (allNum >= frequency) ) { + flag = true; // 独立概率随机 + } + } + if(flag) { + getNum ++; getSum++; + this.rewards.push({type: BATTLE_REWARD_TYPE.RANDOM_REWARD, times: i +1, ...obj}); + } + } + await BattleDropModel.updateByGid(this.roleId, this.battleId, id, { + getNum, allNum, getSum, allSum + }); + } + } + + private async handleLadderReward(num: number, isSuccess: boolean) { + if(!this.ladderReward) return; + for(let i = 0; i < num; i++) { + let arr = this.ladderReward.filter(cur => cur.isSuccess == isSuccess); + let { dic: reward } = getRandEelmWithWeight(arr); + if(reward) { + this.rewards.push({type: BATTLE_REWARD_TYPE.RANDOM_REWARD, times: i +1, id: reward.id, count: reward.count }); + } + } + } + + public async saveReward(num: number, combine: boolean = false) { + this.rewards = new Array(); + // let warType = this.warInfo.warType; + + if(this.isSuccess) { // 成功了才给固定奖励 + // console.log(this.fixReward) + if(this.fixReward) this.handleFixReward(num); + if(this.conditionReward) this.handleConditionReward(num); + if(this.randomReward) await this.handleRandomReward(num); + + // if(this.costAp > 0) await this.handlerBlueprtReward(num); + } + if(this.ladderReward) this.handleLadderReward(num, this.isSuccess); + + let rewards = this.rewards; + if(combine) { + rewards = combineItems(rewards); + } + console.log('##### saveReward', JSON.stringify(rewards)) + await addItems(this.roleId, this.roleName, this.sid, rewards, getReasonByWarType(this.warInfo.warType)); + return rewards; + } +} diff --git a/game-server/app/util/logger.ts b/game-server/app/util/logger.ts index 6a249d064..d62d1a9e7 100644 --- a/game-server/app/util/logger.ts +++ b/game-server/app/util/logger.ts @@ -1,23 +1,23 @@ -import { getLogger, Logger } from 'pinus-logger'; - -let logger: Logger; -let infologger: Logger; -let errlogger: Logger; -let taLogger: Logger; -let itemLogger: Logger; - -export function loadLogger(sid: string) { - logger = getLogger(); - infologger = getLogger('info', sid); - errlogger = getLogger('err', sid); - taLogger = getLogger('ta'); - itemLogger = getLogger('item'); -} - -export { - logger, - infologger, - errlogger, - taLogger, - itemLogger -} \ No newline at end of file +import { getLogger, Logger } from 'pinus-logger'; + +let logger: Logger; +let infologger: Logger; +let errlogger: Logger; +let taLogger: Logger; +let itemLogger: Logger; + +export function loadLogger(sid: string) { + logger = getLogger(); + infologger = getLogger('info', sid); + errlogger = getLogger('err', sid); + taLogger = getLogger('ta'); + itemLogger = getLogger('item'); +} + +export { + logger, + infologger, + errlogger, + taLogger, + itemLogger +} diff --git a/game-server/app/util/routeUtil.ts b/game-server/app/util/routeUtil.ts index dde731f72..cfebe031a 100644 --- a/game-server/app/util/routeUtil.ts +++ b/game-server/app/util/routeUtil.ts @@ -1,207 +1,207 @@ - -import { dispatch } from '../pubUtils/dispatcher'; -import { Session, Application } from 'pinus'; -import { redisClient } from '../services/redisService'; -import { getGroupIdOfServer } from '../services/serverService'; -import { SERVER_GROUP_FUN_TYPE } from '../consts'; - -export async function chat(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let chatServers = app.getServersByType('chat'); - - if (!chatServers || chatServers.length === 0) { - cb(new Error('can not find chat servers.')); - return; - } - let id = session.get('chatServer')||(await dispatch(redisClient(), session.get('roleId'), chatServers, 'chat')).id; - - cb(null, id); -} - -export async function battle(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let battleServers = app.getServersByType('battle'); - - if (!battleServers || battleServers.length === 0) { - cb(new Error('can not find battle servers.')); - return; - } - - let rid = session.get('roleId'); - let id = session.get('battleServer')||(await dispatch(redisClient(), rid, battleServers, 'battle')).id; - cb(null, id); -} - -export async function comBattle(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let battleServers = app.getServersByType('comBattle'); - - if (!battleServers || battleServers.length === 0) { - cb(new Error('can not find comBattle servers.')); - return; - } - - let rid = session.get('roleId'); - let needDispatch = false; - - if (msg.args && msg.args.length > 0) { - for (let arg of msg.args) { - if (!arg.route) continue; - if (['comBattle.comBattleHandler.createTeam', 'comBattle.comBattleHandler.searchTeam'].indexOf(arg.route) !== -1) { - needDispatch = true; - rid = Math.random().toString(36).slice(-8); - session.set('teamCode', rid); - } else if (arg.route.indexOf('comBattle.comBattleHandler') !== -1) { - if (arg.body.teamCode) { - needDispatch = true; - rid = arg.body.teamCode; - } - } - } - } - - if(needDispatch) { - let id = (await dispatch(redisClient(), rid, battleServers, 'comBattle')).id; - cb(null, id); - } else { - let id = session.get('comBattleServer')||(await dispatch(redisClient(), rid, battleServers, 'comBattle')).id; - cb(null, id); - } -} - -export async function guild(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let guildServers = app.getServersByType('guild'); - - if (!guildServers || guildServers.length === 0) { - cb(new Error('can not find guild servers.')); - return; - } - - let rid = session.get('roleId'); - let needDispatch = false; - - if (msg.args && msg.args.length > 0) { - for (let arg of msg.args) { - if (!arg.route) continue; - - if (['guild.gateActivityHandler.getGateActivity', - 'guild.gateActivityHandler.checkBattle', // 军团活动蛮夷入侵路由,按军团路由 - 'guild.gateActivityHandler.action', - 'guild.gateActivityHandler.hitGate', - 'guild.gateActivityHandler.battleEnd', - 'guild.gateActivityHandler.debugGetPrivate', - 'guild.gateActivityHandler.debugStartActivity', - 'guild.gateActivityHandler.debugEndActivity' - ].indexOf(arg.route) !== -1) { - needDispatch = true; - rid = session.get('guildCode'); - } else if (['guild.cityActivityHandler.getCityStatus', - 'guild.cityActivityHandler.declareCity', - 'guild.cityActivityHandler.checkBattle', - 'guild.cityActivityHandler.hitGate', - 'guild.cityActivityHandler.battleEnd' - ].indexOf(arg.route) !== -1) { - if (arg.body.cityId) { - let serverId = session.get('serverId'); - needDispatch = true; - rid = `${serverId}_${arg.body.cityId}`; - } - } else if (['guild.raceActivityHandler.getRaceActivity', - 'guild.raceActivityHandler.leavePage', - 'guild.raceActivityHandler.join', - 'guild.raceActivityHandler.getRace', - 'guild.raceActivityHandler.useItem', - 'guild.raceActivityHandler.battleEnd', - ].indexOf(arg.route) !== -1) { - needDispatch = true; - rid = session.get('serverId').toString(); - } else if (['guild.gvgBattleHandler.startMove', - 'guild.gvgBattleHandler.stopMove', - 'guild.gvgBattleHandler.teamSettle', - 'guild.gvgBattleHandler.teamLeave', - 'guild.gvgBattleHandler.battleEnd', - 'guild.gvgBattleHandler.battleStart', - 'guild.gvgBattleHandler.getAreaTeams', - 'guild.gvgBattleHandler.useItem', - 'guild.gvgBattleHandler.reviveTeam', - 'guild.gvgBattleHandler.saveTeam', - 'guild.gvgBattleHandler.getCity', - 'guild.gvgBattleHandler.checkMyTeam', - 'guild.gvgBattleHandler.enterCity', - 'guild.gvgBattleHandler.leaveCity', - 'guild.gvgBattleHandler.getRankByCity', - 'guild.gvgBattleHandler.getAreaOfMyTeam', - 'guild.gvgBattleHandler.getOppTeam', - 'guild.gvgBattleHandler.debugAddRobots', - 'guild.gvgBattleHandler.debugMoveRobots', - 'guild.gvgBattleHandler.debugStopMoveRobot', - 'guild.gvgBattleHandler.debugAttacks', - ].indexOf(arg.route) !== -1) { - if (arg.body.cityId) { - let serverId = session.get('serverId'); - let groupId = await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG); - needDispatch = true; - rid = `${groupId}_${arg.body.cityId}`; - } - } else if ([ - 'guild.auctionHandler.offer' - ].indexOf(arg.route) != -1) { - if(arg.body.code) { - needDispatch = true; - rid = arg.body.code; - } - } - } - } - - if(needDispatch) { - let id = (await dispatch(redisClient(), rid, guildServers, 'guild')).id; - cb(null, id); - } else { - let id = session.get('guildServer')||(await dispatch(redisClient(), rid, guildServers, 'guild')).id; - cb(null, id); - } -} - -export async function activity(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let activityServers = app.getServersByType('activity'); - if (!activityServers || activityServers.length === 0) { - cb(new Error('can not find activity servers.')); - return; - } - let id = session.get('activityServer')||(await dispatch(redisClient(), session.get('roleId'), activityServers, 'activity')); - cb(null, id); -} - -export async function gm(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let gmServers = app.getServersByType('gm'); - - if (!gmServers || gmServers.length === 0) { - cb(new Error('can not find gm servers.')); - return; - } - - let res = await dispatch(redisClient(), session.get('roleId'), gmServers, 'gm'); - cb(null, res.id); -} - -export async function role(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let roleServers = app.getServersByType('role'); - - if (!roleServers || roleServers.length === 0) { - cb(new Error('can not find activity servers.')); - return; - } - - let id = session.get('roleServer')||(await dispatch(redisClient(), session.get('roleId'), roleServers)).id; - cb(null, id); -} - -export async function order(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { - let orderServers = app.getServersByType('order'); - - if (!orderServers || orderServers.length === 0) { - cb(new Error('can not find activity servers.')); - return; - } - - let id = session.get('orderServer')||(await dispatch(redisClient(), session.get('roleId'), orderServers, 'order')).id; - cb(null, id); -} \ No newline at end of file + +import { dispatch } from '@pubUtils/dispatcher'; +import { Session, Application } from 'pinus'; +import { redisClient } from '../services/redisService'; +import { getGroupIdOfServer } from '../services/serverService'; +import { SERVER_GROUP_FUN_TYPE } from '@consts'; + +export async function chat(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let chatServers = app.getServersByType('chat'); + + if (!chatServers || chatServers.length === 0) { + cb(new Error('can not find chat servers.')); + return; + } + let id = session.get('chatServer')||(await dispatch(redisClient(), session.get('roleId'), chatServers, 'chat')).id; + + cb(null, id); +} + +export async function battle(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let battleServers = app.getServersByType('battle'); + + if (!battleServers || battleServers.length === 0) { + cb(new Error('can not find battle servers.')); + return; + } + + let rid = session.get('roleId'); + let id = session.get('battleServer')||(await dispatch(redisClient(), rid, battleServers, 'battle')).id; + cb(null, id); +} + +export async function comBattle(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let battleServers = app.getServersByType('comBattle'); + + if (!battleServers || battleServers.length === 0) { + cb(new Error('can not find comBattle servers.')); + return; + } + + let rid = session.get('roleId'); + let needDispatch = false; + + if (msg.args && msg.args.length > 0) { + for (let arg of msg.args) { + if (!arg.route) continue; + if (['comBattle.comBattleHandler.createTeam', 'comBattle.comBattleHandler.searchTeam'].indexOf(arg.route) !== -1) { + needDispatch = true; + rid = Math.random().toString(36).slice(-8); + session.set('teamCode', rid); + } else if (arg.route.indexOf('comBattle.comBattleHandler') !== -1) { + if (arg.body.teamCode) { + needDispatch = true; + rid = arg.body.teamCode; + } + } + } + } + + if(needDispatch) { + let id = (await dispatch(redisClient(), rid, battleServers, 'comBattle')).id; + cb(null, id); + } else { + let id = session.get('comBattleServer')||(await dispatch(redisClient(), rid, battleServers, 'comBattle')).id; + cb(null, id); + } +} + +export async function guild(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let guildServers = app.getServersByType('guild'); + + if (!guildServers || guildServers.length === 0) { + cb(new Error('can not find guild servers.')); + return; + } + + let rid = session.get('roleId'); + let needDispatch = false; + + if (msg.args && msg.args.length > 0) { + for (let arg of msg.args) { + if (!arg.route) continue; + + if (['guild.gateActivityHandler.getGateActivity', + 'guild.gateActivityHandler.checkBattle', // 军团活动蛮夷入侵路由,按军团路由 + 'guild.gateActivityHandler.action', + 'guild.gateActivityHandler.hitGate', + 'guild.gateActivityHandler.battleEnd', + 'guild.gateActivityHandler.debugGetPrivate', + 'guild.gateActivityHandler.debugStartActivity', + 'guild.gateActivityHandler.debugEndActivity' + ].indexOf(arg.route) !== -1) { + needDispatch = true; + rid = session.get('guildCode'); + } else if (['guild.cityActivityHandler.getCityStatus', + 'guild.cityActivityHandler.declareCity', + 'guild.cityActivityHandler.checkBattle', + 'guild.cityActivityHandler.hitGate', + 'guild.cityActivityHandler.battleEnd' + ].indexOf(arg.route) !== -1) { + if (arg.body.cityId) { + let serverId = session.get('serverId'); + needDispatch = true; + rid = `${serverId}_${arg.body.cityId}`; + } + } else if (['guild.raceActivityHandler.getRaceActivity', + 'guild.raceActivityHandler.leavePage', + 'guild.raceActivityHandler.join', + 'guild.raceActivityHandler.getRace', + 'guild.raceActivityHandler.useItem', + 'guild.raceActivityHandler.battleEnd', + ].indexOf(arg.route) !== -1) { + needDispatch = true; + rid = session.get('serverId').toString(); + } else if (['guild.gvgBattleHandler.startMove', + 'guild.gvgBattleHandler.stopMove', + 'guild.gvgBattleHandler.teamSettle', + 'guild.gvgBattleHandler.teamLeave', + 'guild.gvgBattleHandler.battleEnd', + 'guild.gvgBattleHandler.battleStart', + 'guild.gvgBattleHandler.getAreaTeams', + 'guild.gvgBattleHandler.useItem', + 'guild.gvgBattleHandler.reviveTeam', + 'guild.gvgBattleHandler.saveTeam', + 'guild.gvgBattleHandler.getCity', + 'guild.gvgBattleHandler.checkMyTeam', + 'guild.gvgBattleHandler.enterCity', + 'guild.gvgBattleHandler.leaveCity', + 'guild.gvgBattleHandler.getRankByCity', + 'guild.gvgBattleHandler.getAreaOfMyTeam', + 'guild.gvgBattleHandler.getOppTeam', + 'guild.gvgBattleHandler.debugAddRobots', + 'guild.gvgBattleHandler.debugMoveRobots', + 'guild.gvgBattleHandler.debugStopMoveRobot', + 'guild.gvgBattleHandler.debugAttacks', + ].indexOf(arg.route) !== -1) { + if (arg.body.cityId) { + let serverId = session.get('serverId'); + let groupId = await getGroupIdOfServer(serverId, SERVER_GROUP_FUN_TYPE.GVG); + needDispatch = true; + rid = `${groupId}_${arg.body.cityId}`; + } + } else if ([ + 'guild.auctionHandler.offer' + ].indexOf(arg.route) != -1) { + if(arg.body.code) { + needDispatch = true; + rid = arg.body.code; + } + } + } + } + + if(needDispatch) { + let id = (await dispatch(redisClient(), rid, guildServers, 'guild')).id; + cb(null, id); + } else { + let id = session.get('guildServer')||(await dispatch(redisClient(), rid, guildServers, 'guild')).id; + cb(null, id); + } +} + +export async function activity(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let activityServers = app.getServersByType('activity'); + if (!activityServers || activityServers.length === 0) { + cb(new Error('can not find activity servers.')); + return; + } + let id = session.get('activityServer')||(await dispatch(redisClient(), session.get('roleId'), activityServers, 'activity')); + cb(null, id); +} + +export async function gm(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let gmServers = app.getServersByType('gm'); + + if (!gmServers || gmServers.length === 0) { + cb(new Error('can not find gm servers.')); + return; + } + + let res = await dispatch(redisClient(), session.get('roleId'), gmServers, 'gm'); + cb(null, res.id); +} + +export async function role(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let roleServers = app.getServersByType('role'); + + if (!roleServers || roleServers.length === 0) { + cb(new Error('can not find activity servers.')); + return; + } + + let id = session.get('roleServer')||(await dispatch(redisClient(), session.get('roleId'), roleServers)).id; + cb(null, id); +} + +export async function order(session: Session, msg: any, app: Application, cb: (err: Error, serverId?: string) => void) { + let orderServers = app.getServersByType('order'); + + if (!orderServers || orderServers.length === 0) { + cb(new Error('can not find activity servers.')); + return; + } + + let id = session.get('orderServer')||(await dispatch(redisClient(), session.get('roleId'), orderServers, 'order')).id; + cb(null, id); +} diff --git a/game-server/config/database.ts b/game-server/config/database.ts index 720ea9b94..981ff0b4a 100644 --- a/game-server/config/database.ts +++ b/game-server/config/database.ts @@ -1,9 +1,9 @@ module.exports = { 'development': { - 'mongo': 'mongodb://127.0.0.1/zyz?replicaSet=rs0', - 'gmmongo': 'mongodb://127.0.0.1/zyzgm', - 'redis': '127.0.0.1', - 'redispw': 'zyz_2020' + 'mongo': 'mongodb://192.168.1.99:27017/zyz?replicaSet=rs0', + 'gmmongo': 'mongodb://192.168.1.99:27017/zyzgm', + 'redis': '192.168.1.99', + 'redispw': 'Homzy@123' }, 'stable': { diff --git a/game-server/package-lock.json b/game-server/package-lock.json deleted file mode 100644 index 5df55dbeb..000000000 --- a/game-server/package-lock.json +++ /dev/null @@ -1,5513 +0,0 @@ -{ - "name": "pinus-sample-websocket-chat-game-server-ts-run", - "version": "1.4.9", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@alicloud/fc2": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@alicloud/fc2/-/fc2-2.2.2.tgz", - "integrity": "sha512-nBdeHowbQOcaAMWledEqK8TrPjntfYpg/gO+p3ezZWvs6nu2WGf9EQNRk4N4l1d8aVNbFUUQkzOrlO/pdJ5uVA==", - "requires": { - "babel-runtime": "^6.23.0", - "debug": "^2.6.4", - "httpx": "^2.1.1", - "kitx": "^1.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz", - "integrity": "sha1-Fo2ho26Q2miujUnA8bSMfGJJITo=", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.4.tgz?cache=0&sync_timestamp=1593522720715&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.10.4.tgz", - "integrity": "sha1-p4x6clHgH2FlEtMbEK3PUq2l4NI=", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.4.tgz?cache=0&sync_timestamp=1593522818552&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhighlight%2Fdownload%2F%40babel%2Fhighlight-7.10.4.tgz", - "integrity": "sha1-fRvf1ldTU4+r5sOFls23bZrGAUM=", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" - }, - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.4.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@socket.io/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==" - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.nlark.com/@tootallnate/once/download/@tootallnate/once-1.1.2.tgz", - "integrity": "sha1-zLkURTYBeaBOf+av94wA/8Hur4I=" - }, - "@typegoose/typegoose": { - "version": "7.3.5", - "resolved": "https://registry.npm.taobao.org/@typegoose/typegoose/download/@typegoose/typegoose-7.3.5.tgz", - "integrity": "sha1-94517zpL5R8DkYh55qjPDR/PecA=", - "requires": { - "lodash": "^4.17.19", - "loglevel": "^1.6.8", - "reflect-metadata": "^0.1.13", - "semver": "^7.3.2", - "tslib": "^2.0.0" - }, - "dependencies": { - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.2.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.2.tgz", - "integrity": "sha1-YElisFK4HtB4aq6EOJ/7pw/9OTg=" - }, - "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.0.1.tgz?cache=0&sync_timestamp=1596751904317&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.1.tgz", - "integrity": "sha1-QQ6w0RPltjVkkO7HSWA3JbAhtD4=" - } - } - }, - "@types/bluebird": { - "version": "3.5.32", - "resolved": "https://registry.npm.taobao.org/@types/bluebird/download/@types/bluebird-3.5.32.tgz", - "integrity": "sha1-OB57WeOfAQ0gu/fgROSPXK8atiA=" - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npm.taobao.org/@types/bson/download/@types/bson-4.0.2.tgz", - "integrity": "sha1-esy4WUL8ObvbdRXU3kN8BPaYEV8=", - "requires": { - "@types/node": "*" - } - }, - "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" - }, - "@types/chai": { - "version": "4.2.14", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.14.tgz", - "integrity": "sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ==" - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/@types/color-name/download/@types/color-name-1.1.1.tgz?cache=0&sync_timestamp=1588199606687&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fcolor-name%2Fdownload%2F%40types%2Fcolor-name-1.1.1.tgz", - "integrity": "sha1-HBJhu+qhCoBVu8XYq4S3sq/IRqA=" - }, - "@types/component-emitter": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", - "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/crc": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/crc/-/crc-3.4.0.tgz", - "integrity": "sha1-I2a+tDmc1zSzPkLHrICVduYX1Io=", - "requires": { - "@types/node": "*" - } - }, - "@types/lodash": { - "version": "4.14.182", - "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz", - "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" - }, - "@types/mocha": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.0.tgz", - "integrity": "sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ==" - }, - "@types/mongodb": { - "version": "3.5.27", - "resolved": "https://registry.npm.taobao.org/@types/mongodb/download/@types/mongodb-3.5.27.tgz?cache=0&sync_timestamp=1599138259359&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fmongodb%2Fdownload%2F%40types%2Fmongodb-3.5.27.tgz", - "integrity": "sha1-FYp6Q84l7zWSrIpi5iqzi+v2YfI=", - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/mongoose": { - "version": "5.7.36", - "resolved": "https://registry.npm.taobao.org/@types/mongoose/download/@types/mongoose-5.7.36.tgz", - "integrity": "sha1-La4oxjBBxq+6ioPqApafRjs/ECE=", - "requires": { - "@types/mongodb": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "8.10.54", - "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-8.10.54.tgz?cache=0&sync_timestamp=1595281257528&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-8.10.54.tgz", - "integrity": "sha1-HIjrJTrBIQ8aWHaVP7cPfMSShAI=" - }, - "@types/node-schedule": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-1.3.1.tgz", - "integrity": "sha512-xAY/ZATrThUkMElSDfOk+5uXprCrV6c6GQ5gTw3U04qPS6NofE1dhOUW+yrOF2UyrUiAax/Zc4WtagrbPAN3Tw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/redis": { - "version": "2.8.25", - "resolved": "https://registry.npm.taobao.org/@types/redis/download/@types/redis-2.8.25.tgz", - "integrity": "sha1-BGv/8kuC7/pZ10dExvz4mVvhdHk=", - "requires": { - "@types/node": "*" - } - }, - "@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", - "requires": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - } - }, - "@types/request-promise": { - "version": "4.1.47", - "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz", - "integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==", - "requires": { - "@types/bluebird": "*", - "@types/request": "*" - } - }, - "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==" - }, - "@types/underscore": { - "version": "1.10.24", - "resolved": "https://registry.npm.taobao.org/@types/underscore/download/@types/underscore-1.10.24.tgz", - "integrity": "sha1-3t4ATe7Ts/mcTbC9ue4hyuJb790=" - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz", - "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npm.taobao.org/address/download/address-1.1.2.tgz", - "integrity": "sha1-vxEWycdYxRt6kz0pa3LCIe2UKLY=" - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.nlark.com/agent-base/download/agent-base-6.0.2.tgz", - "integrity": "sha1-Sf/1hXfP7j83F2/qtMIuAPhtf3c=", - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "requires": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "alipay-mobile": { - "version": "4.0.2", - "resolved": "https://registry.nlark.com/alipay-mobile/download/alipay-mobile-4.0.2.tgz", - "integrity": "sha1-dGQCRAgLpSlJf76vhqwGKGUaFs4=", - "requires": { - "joi": "^14.3.1", - "moment": "^2.19.3", - "urllib": "^2.21.1" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", - "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", - "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npm.taobao.org/arg/download/arg-4.1.3.tgz", - "integrity": "sha1-Jp/HrVuOQstjyJbVZmAXJhwUQIk=" - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npm.taobao.org/arraybuffer.slice/download/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=" - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmmirror.com/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" - }, - "ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npm.taobao.org/ast-types/download/ast-types-0.13.4.tgz", - "integrity": "sha1-7g13s0MmOWXsw/ti2hbnIisrZ4I=", - "requires": { - "tslib": "^2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.2.0.tgz?cache=0&sync_timestamp=1617647281845&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.2.0.tgz", - "integrity": "sha1-+yxHWXfjXiQTEe3iaTzuHsZpj1w=" - } - } - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz", - "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmmirror.com/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npm.taobao.org/base64-arraybuffer/download/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", - "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/base64id/download/base64id-2.0.0.tgz", - "integrity": "sha1-J3Csa8R9MSr5eov5pjQ0LgzSXLY=" - }, - "bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", - "requires": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bearcat-buffer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bearcat-buffer/-/bearcat-buffer-0.1.1.tgz", - "integrity": "sha1-K7nJ/KYY0HRQHnN8fycY9ijOcSY=" - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/better-assert/download/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npm.taobao.org/blob/download/blob-0.0.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fblob%2Fdownload%2Fblob-0.0.5.tgz", - "integrity": "sha1-1oDu7yX4zZGtUz9bAe7UjmTK9oM=" - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz", - "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bson": { - "version": "1.1.5", - "resolved": "https://registry.npm.taobao.org/bson/download/bson-1.1.5.tgz?cache=0&sync_timestamp=1597069108497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbson%2Fdownload%2Fbson-1.1.5.tgz", - "integrity": "sha1-Kqrpj832dQwISLDLod3sPHMGCjQ=" - }, - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-5.6.0.tgz", - "integrity": "sha1-oxdJ3H2B2E2wir+Te2uMQDP2J4Y=", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz", - "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz", - "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=" - }, - "cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmmirror.com/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==" - } - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/callsite/download/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz", - "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1591687000046&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", - "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - } - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" - }, - "chinese-random-name": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chinese-random-name/-/chinese-random-name-1.0.0.tgz", - "integrity": "sha512-0ZJ0LhV4O9vqas4IgQB7IDqqSovpSoHlvZo3FWXShKBfs6BS7l4uRQVqin54D4KNrG81G7cZ7p6YIpn93fo2wQ==", - "requires": { - "flatten": "^1.0.2", - "random-to": "0.0.2" - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmmirror.com/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cliff": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz", - "integrity": "sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM=", - "requires": { - "colors": "~1.0.3", - "eyes": "~0.1.8", - "winston": "0.8.x" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz", - "integrity": "sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE=", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", - "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", - "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "copy-to": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" - }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npm.taobao.org/crc/download/crc-3.8.0.tgz", - "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", - "requires": { - "buffer": "^5.1.0" - } - }, - "cron-parser": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.18.0.tgz", - "integrity": "sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==", - "requires": { - "is-nan": "^1.3.0", - "moment-timezone": "^0.5.31" - } - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "csprng": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz", - "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=", - "requires": { - "sequin": "*" - } - }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npm.taobao.org/data-uri-to-buffer/download/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha1-WUuJc5OMW8LDMEZTV4U0GrxPNjY=" - }, - "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-3.0.0.tgz?cache=0&sync_timestamp=1572559173297&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdate-format%2Fdownload%2Fdate-format-3.0.0.tgz", - "integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "default-user-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", - "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", - "requires": { - "os-name": "~1.0.3" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "degenerator": { - "version": "2.2.0", - "resolved": "https://registry.nlark.com/degenerator/download/degenerator-2.2.0.tgz", - "integrity": "sha1-SemMEfoCk8Wybt+7UvFXKa/NslQ=", - "requires": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npm.taobao.org/denque/download/denque-1.4.1.tgz", - "integrity": "sha1-Z0T/dkHBSMP4ppwwflEjXB9KN88=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npm.taobao.org/diff/download/diff-4.0.2.tgz?cache=0&sync_timestamp=1578890988059&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff%2Fdownload%2Fdiff-4.0.2.tgz", - "integrity": "sha1-YPOuy4nV+uUgwRqhnvwruYKq3n0=" - }, - "digest-header": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz", - "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", - "requires": { - "utility": "0.1.11" - }, - "dependencies": { - "utility": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz", - "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", - "requires": { - "address": ">=0.0.1" - } - } - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-8.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-8.0.0.tgz", - "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=" - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz", - "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.4.2", - "resolved": "https://registry.npm.taobao.org/engine.io/download/engine.io-3.4.2.tgz?cache=0&sync_timestamp=1591281196713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fengine.io%2Fdownload%2Fengine.io-3.4.2.tgz", - "integrity": "sha1-j8hO4AOI4+IoZF4KfT367tW9Eiw=", - "requires": { - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "0.3.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" - } - }, - "engine.io-client": { - "version": "3.4.3", - "resolved": "https://registry.npm.taobao.org/engine.io-client/download/engine.io-client-3.4.3.tgz?cache=0&sync_timestamp=1591281305009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fengine.io-client%2Fdownload%2Fengine.io-client-3.4.3.tgz", - "integrity": "sha1-GS0JhlQD4wl+NXXr/rOGHE0Bpmw=", - "requires": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz", - "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=" - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npm.taobao.org/ws/download/ws-6.1.4.tgz?cache=0&sync_timestamp=1593925670988&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fws%2Fdownload%2Fws-6.1.4.tgz", - "integrity": "sha1-W1yIAK+rkl6UzLKdFTyNAsF3bvk=", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.2.0", - "resolved": "https://registry.npm.taobao.org/engine.io-parser/download/engine.io-parser-2.2.0.tgz", - "integrity": "sha1-MSxIlPV9UqArQgho2ntcHISvgO0=", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" - }, - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npm.taobao.org/escodegen/download/escodegen-1.14.3.tgz", - "integrity": "sha1-TnuB+6YVgdyXWC7XjKt/Do1j9QM=", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=" - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npm.taobao.org/estraverse/download/estraverse-4.3.0.tgz", - "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz", - "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=" - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" - }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "file-uri-to-path": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-2.0.0.tgz", - "integrity": "sha1-e0Fa66In1XWFHgpbDGQNdlZAP7o=" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz", - "integrity": "sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk=", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npm.taobao.org/flatted/download/flatted-2.0.2.tgz", - "integrity": "sha1-RXWyHivO50NKqb5mL0t7X5wrUTg=" - }, - "flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formstream": { - "version": "1.1.1", - "resolved": "https://registry.nlark.com/formstream/download/formstream-1.1.1.tgz", - "integrity": "sha1-FyWdJEDDXKlzbbn0X7O6P4Zpx1A=", - "requires": { - "destroy": "^1.0.4", - "mime": "^2.5.2", - "pause-stream": "~0.0.11" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz", - "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz", - "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=" - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" - }, - "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-uri": { - "version": "3.0.2", - "resolved": "https://registry.nlark.com/get-uri/download/get-uri-3.0.2.tgz", - "integrity": "sha1-8O8TVvqrxw4flAT6O2ayupv8clw=", - "requires": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmmirror.com/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz", - "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1588086905523&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz", - "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmmirror.com/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npm.taobao.org/has-binary2/download/has-binary2-1.0.3.tgz?cache=0&sync_timestamp=1587049505010&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-binary2%2Fdownload%2Fhas-binary2-1.0.3.tgz", - "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hoek": { - "version": "6.1.3", - "resolved": "https://registry.npm.taobao.org/hoek/download/hoek-6.1.3.tgz", - "integrity": "sha1-c7fTOVLgH+J6OLBFcpS3ndjaJCw=" - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz", - "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npm.taobao.org/http-proxy-agent/download/http-proxy-agent-4.0.1.tgz", - "integrity": "sha1-ioyO9/WTLM+VPClsqCkblap0qjo=", - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npm.taobao.org/https-proxy-agent/download/https-proxy-agent-5.0.0.tgz?cache=0&sync_timestamp=1614740547969&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttps-proxy-agent%2Fdownload%2Fhttps-proxy-agent-5.0.0.tgz", - "integrity": "sha1-4qkFQqu2inYuCghQ9sntrf2FBrI=", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "httpx": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/httpx/-/httpx-2.2.7.tgz", - "integrity": "sha512-Wjh2JOAah0pdczfqL8NC5378G7jMt0Zcpn8U+yyxAiejjlagzSTQgJHuVvka2VNPQlKfoGehYRc79WKq9E4gDw==", - "requires": { - "@types/node": "^14", - "debug": "^4.1.1" - }, - "dependencies": { - "@types/node": { - "version": "14.17.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.21.tgz", - "integrity": "sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==" - } - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.1.13.tgz", - "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=" - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", - "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "ip2region": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ip2region/-/ip2region-2.3.0.tgz", - "integrity": "sha512-zV5Xsadzrx9Ej6heoyhbXMsfGWWQ3C6bAIYStrHhw9kzLpGpVNlnAyRBxxPgxA1GNqr1Ti7oUxcWsMWNN3jZBg==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" - }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - }, - "dependencies": { - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - } - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isemail": { - "version": "3.2.0", - "resolved": "https://registry.npm.taobao.org/isemail/download/isemail-3.2.0.tgz", - "integrity": "sha1-WTEKAhkxqfsGu7UeFVzgs/I2gyw=", - "requires": { - "punycode": "2.x.x" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "joi": { - "version": "14.3.1", - "resolved": "https://registry.npm.taobao.org/joi/download/joi-14.3.1.tgz?cache=0&sync_timestamp=1612746391586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjoi%2Fdownload%2Fjoi-14.3.1.tgz", - "integrity": "sha1-FkomLsC4VUZuDDXuoqiFrotscDw=", - "requires": { - "hoek": "6.x.x", - "isemail": "3.x.x", - "topo": "3.x.x" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz", - "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.0.tgz?cache=0&sync_timestamp=1590172281856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-yaml%2Fdownload%2Fjs-yaml-3.14.0.tgz", - "integrity": "sha1-p6NBcPJqIbsWJCTYray0ETpp5II=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "kareem": { - "version": "2.3.1", - "resolved": "https://registry.npm.taobao.org/kareem/download/kareem-2.3.1.tgz", - "integrity": "sha1-3vEtnJQQF/q/sA+HOvlenJnhvoc=" - }, - "kitx": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/kitx/-/kitx-1.3.0.tgz", - "integrity": "sha512-fhBqFlXd0GkKTB+8ayLfpzPUw+LHxZlPAukPNBD1Om7JMeInT+/PxCAf1yLagvD+VKoyWhXtJR68xQkX/a0wOQ==" - }, - "koa-is-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", - "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "local": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/local/-/local-0.3.3.tgz", - "integrity": "sha1-vjsTPQgQz2bfY6nG5K2nxN0Kmvw=", - "requires": { - "async": "^2.0.0-rc.2" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz", - "integrity": "sha1-Gvujlq/WdqbUJQTQpno6frn2KqA=", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336097104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz", - "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=" - }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "requires": { - "chalk": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npm.taobao.org/log4js/download/log4js-6.3.0.tgz?cache=0&sync_timestamp=1590367779968&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flog4js%2Fdownload%2Flog4js-6.3.0.tgz", - "integrity": "sha1-EN+vu0NDUaPjAnegC5h5RG9xW8s=", - "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" - } - }, - "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.7.0.tgz?cache=0&sync_timestamp=1598447642950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.7.0.tgz", - "integrity": "sha1-coFmhVp0DVnTjbAc9G8ELKoEG7A=" - }, - "long-timeout": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz", - "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npm.taobao.org/make-error/download/make-error-1.3.6.tgz?cache=0&sync_timestamp=1582105759247&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-error%2Fdownload%2Fmake-error-1.3.6.tgz", - "integrity": "sha1-LrLjfqm2fEiR9oShOUeZr0hM96I=" - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmmirror.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmmirror.com/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - } - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npm.taobao.org/memory-pager/download/memory-pager-1.5.0.tgz", - "integrity": "sha1-2HUWVdItOEaCdByXLyw9bfo+ZrU=", - "optional": true - }, - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npm.taobao.org/mime/download/mime-2.5.2.tgz", - "integrity": "sha1-bj3GzCuVEGQ4MOXxnVy3U9pe6r4=" - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz", - "integrity": "sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I=" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz", - "integrity": "sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8=", - "requires": { - "mime-db": "1.44.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz?cache=0&sync_timestamp=1585431899596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimatch%2Fdownload%2Fminimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", - "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=" - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", - "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "mocha-parallel-tests": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/mocha-parallel-tests/-/mocha-parallel-tests-2.3.0.tgz", - "integrity": "sha512-GdU55VkOCXK2aBmjFzBE11RsSolA71WJppucU3BrTbMUpGIWnTidrje5Hvdr+hOolynEiv6fHWyoNT41mq4HkA==", - "dev": true, - "requires": { - "circular-json": "^0.5.9", - "debug": "^4.1.1", - "uuid": "^3.4.0", - "yargs": "^13.3.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.29.1.tgz?cache=0&sync_timestamp=1601983423917&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.29.1.tgz", - "integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M=" - }, - "moment-timezone": { - "version": "0.5.32", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.32.tgz", - "integrity": "sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "mongodb": { - "version": "3.6.1", - "resolved": "https://registry.npm.taobao.org/mongodb/download/mongodb-3.6.1.tgz", - "integrity": "sha1-LFzCqBRWuhg+jEMtgOeHMsxy2r0=", - "requires": { - "bl": "^2.2.0", - "bson": "^1.1.4", - "denque": "^1.4.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - }, - "dependencies": { - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npm.taobao.org/bl/download/bl-2.2.1.tgz?cache=0&sync_timestamp=1599194088618&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbl%2Fdownload%2Fbl-2.2.1.tgz", - "integrity": "sha1-jBGntzBlXF1WiYzchxIk9A/ZAdU=", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - } - } - }, - "mongoose": { - "version": "5.10.4", - "resolved": "https://registry.npm.taobao.org/mongoose/download/mongoose-5.10.4.tgz", - "integrity": "sha1-CVGSYZmCQ95H7XLtKNyMOtv2qRA=", - "requires": { - "bson": "^1.1.4", - "kareem": "2.3.1", - "mongodb": "3.6.1", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.7.0", - "mquery": "3.2.2", - "ms": "2.1.2", - "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", - "sift": "7.0.1", - "sliced": "1.0.1" - } - }, - "mongoose-lean-getters": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/mongoose-lean-getters/-/mongoose-lean-getters-0.1.2.tgz", - "integrity": "sha512-OIgQP4POwsWE3oItEIohbvb0BvqW2SV248WU6Hh7mlEX1isPTCrfayZUgVoBkd9L/q42FTza+NZ4qOXtJSzEOQ==", - "requires": { - "mpath": "0.5.x" - }, - "dependencies": { - "mpath": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.2.tgz", - "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==" - } - } - }, - "mongoose-lean-virtuals": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.7.6.tgz", - "integrity": "sha512-Yb3u9+1vTbCgG87BFTbKl2O3kzcKRnZF9A4bRbbE2NMvWJqGzj0iVdDxPXaZQ8lBhlgFMPwh6oEYIAAPIvld+g==", - "requires": { - "array.prototype.flat": "1.2.3", - "mpath": "0.5.x" - }, - "dependencies": { - "mpath": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.2.tgz", - "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==" - } - } - }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/mongoose-legacy-pluralize/download/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha1-O6n5H6UHtRhtOZ+0CFS/8Y+1Y+Q=" - }, - "mongoose-transactions": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", - "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==" - }, - "mpath": { - "version": "0.7.0", - "resolved": "https://registry.npm.taobao.org/mpath/download/mpath-0.7.0.tgz", - "integrity": "sha1-IOgQLidrcXCdbgfp+NTQ9kGvv7g=" - }, - "mqtt-connection": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mqtt-connection/-/mqtt-connection-4.1.0.tgz", - "integrity": "sha512-GxfIEosx2Rxh7Yw8951L2s3WDqNLLqhyA8f6O9IyEMdrATX750TkdPMcqdDyTJTdwGCMjCRNGPvsI6PxFlX3AA==", - "requires": { - "duplexify": "^3.5.1", - "inherits": "^2.0.3", - "mqtt-packet": "^6.0.0", - "safe-buffer": "^5.1.1", - "through2": "^2.0.1" - } - }, - "mqtt-packet": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", - "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", - "requires": { - "bl": "^4.0.2", - "debug": "^4.1.1", - "process-nextick-args": "^2.0.1" - } - }, - "mquery": { - "version": "3.2.2", - "resolved": "https://registry.npm.taobao.org/mquery/download/mquery-3.2.2.tgz", - "integrity": "sha1-4Tg6OVGFLOI+N/YZqbNQ8fs2ZOc=", - "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "dependencies": { - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz", - "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1575472461218&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1575472461218&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", - "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz", - "integrity": "sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI=", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmmirror.com/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" - }, - "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", - "dev": true - }, - "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz", - "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=" - }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npm.taobao.org/netmask/download/netmask-2.0.2.tgz", - "integrity": "sha1-iwGgdkQGXVNjg4NYI7xSAE66xec=" - }, - "node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" - }, - "node-bignumber": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/node-bignumber/-/node-bignumber-1.2.2.tgz", - "integrity": "sha512-VoTZHmdFQpZH1+q1dz2qcHNCwTWsJg2T3PYwlAyDNFOfVhSYUKQBLFcCpCud+wJBGgCttGavZILaIggDIKqEQQ==" - }, - "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmmirror.com/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "requires": { - "abbrev": "^1.0.0" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "7.4.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "node-schedule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.2.tgz", - "integrity": "sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==", - "requires": { - "cron-parser": "^2.7.3", - "long-timeout": "0.1.1", - "sorted-array-functions": "^1.0.0" - } - }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmmirror.com/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npm.taobao.org/object-component/download/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, - "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npm.taobao.org/optionator/download/optionator-0.8.3.tgz", - "integrity": "sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU=", - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-name": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", - "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", - "requires": { - "osx-release": "^1.0.0", - "win-release": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "osx-release": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", - "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", - "requires": { - "minimist": "^1.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1594560064408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", - "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz", - "integrity": "sha1-o0KLtwiLOmApL2aRkni3wpetTwc=", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", - "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" - }, - "pac-proxy-agent": { - "version": "4.1.0", - "resolved": "https://registry.npm.taobao.org/pac-proxy-agent/download/pac-proxy-agent-4.1.0.tgz", - "integrity": "sha1-Zog+6rrckV/F6VRXMkyw8Kx43vs=", - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^4.1.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - } - }, - "pac-resolver": { - "version": "4.2.0", - "resolved": "https://registry.npm.taobao.org/pac-resolver/download/pac-resolver-4.2.0.tgz", - "integrity": "sha1-uCvLmZLUgWaSC8g8dUKrtFS9m90=", - "requires": { - "degenerator": "^2.2.0", - "ip": "^1.1.5", - "netmask": "^2.0.1" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npm.taobao.org/parseqs/download/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npm.taobao.org/parseuri/download/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz", - "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz", - "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", - "dev": true - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "pinus": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus/-/pinus-1.6.3.tgz", - "integrity": "sha512-tOqSspjwV71LtpAYE7N4ohna8pVJT+mhmL0Rgpd0vqH2J85hWVE4B/ntCbH/+5DEUcKQg8raRid+N1MOTASNpA==", - "requires": { - "async": "^3.0.0", - "cliff": "^0.1.10", - "commander": "3.0.2", - "crc": "^3.5.0", - "eyes": "^0.1.8", - "mkdirp": "^1.0.4", - "mqtt-connection": "^4.1.0", - "node-bignumber": "^1.2.1", - "pinus-admin": "^1.6.3", - "pinus-loader": "^1.6.3", - "pinus-logger": "^1.6.3", - "pinus-protobuf": "^1.6.3", - "pinus-protocol": "^1.6.3", - "pinus-rpc": "^1.6.3", - "pinus-scheduler": "^1.6.3", - "seq-queue": "^0.0.5", - "socket.io": "^4.1.3", - "ws": "^7.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" - } - } - }, - "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "pinus-scheduler": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-scheduler/-/pinus-scheduler-1.6.3.tgz", - "integrity": "sha512-W8AbWsQPOeOKPQo4U1J1TI3aVNbIk4H5Q0fDLoqSDbqVAEr+nfMXiflLGN9uPs/k1ohbLRDfgqRFjMXzy7c3zw==", - "requires": { - "pinus-logger": "^1.6.3" - } - }, - "socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - } - } - } - }, - "pinus-admin": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-admin/-/pinus-admin-1.6.3.tgz", - "integrity": "sha512-Af8I7wZ62QEUpHCNuIHFrXEnHKOoZfhwVSqAVHOFsEfC2oPbypkH9M1Ps3l4SUMBB/kW2yMhsZr8Wsnwd42hAw==", - "requires": { - "mqtt-connection": "^4.1.0", - "pinus-logger": "^1.6.3", - "pinus-monitor": "^1.6.3", - "pinus-scheduler": "^1.6.3", - "read-last-lines": "^1.3.0" - }, - "dependencies": { - "pinus-scheduler": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-scheduler/-/pinus-scheduler-1.6.3.tgz", - "integrity": "sha512-W8AbWsQPOeOKPQo4U1J1TI3aVNbIk4H5Q0fDLoqSDbqVAEr+nfMXiflLGN9uPs/k1ohbLRDfgqRFjMXzy7c3zw==", - "requires": { - "pinus-logger": "^1.6.3" - } - } - } - }, - "pinus-loader": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-loader/-/pinus-loader-1.6.3.tgz", - "integrity": "sha512-h3v7I6S5VKpw6Y5M9rr3ZwHT1l2GlwW04J+1VmeC8r+cx7R8i5H1gIBvHV43zmp9et5RXE6hoPySYLJdwjdQTQ==", - "requires": { - "reflect-metadata": "0.1.13" - } - }, - "pinus-logger": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-logger/-/pinus-logger-1.6.3.tgz", - "integrity": "sha512-tcQ7K2iK2qupOzbVE8qxBHyRRVvYJlnRglZRyitAZR7NC+rJOGIESweH+azvn4c33diQEC+4JnzGyUKPBPJMiw==", - "requires": { - "log4js": "^6.0.0" - } - }, - "pinus-monitor": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-monitor/-/pinus-monitor-1.6.3.tgz", - "integrity": "sha512-YnJR2Eyyf/pvUyF8PS18hYvQAXv/WXJ8O2gZgC39dNZ2yI2/7QbOy9J9DBR84gAqjsKw5u0tcDewwN43C34lfg==" - }, - "pinus-protobuf": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-protobuf/-/pinus-protobuf-1.6.3.tgz", - "integrity": "sha512-T2/d76K+iDRHHEnXvUsF0qTnZhgQQIvAfTZyTcyzmpFYhGqhGHyf+XaNiaP6977kWDPS6Ow8CZ5BQdLf7qI8fQ==" - }, - "pinus-protocol": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-protocol/-/pinus-protocol-1.6.3.tgz", - "integrity": "sha512-8lD+TlzhjK7GGL/RROpFo2UwEtcQB1expaPzLrY0pTYEwWIw9WC0Me6U5+uNKZYB2HyWhuMQrYqHJTMWm8reog==" - }, - "pinus-robot": { - "version": "1.4.9", - "resolved": "https://registry.npm.taobao.org/pinus-robot/download/pinus-robot-1.4.9.tgz", - "integrity": "sha1-ZJLDT5CRSCYJLJKsIf60G0kX6Kg=", - "requires": { - "cliff": "^0.1.10", - "socket.io": "^2.3.0", - "socket.io-client": "^2.3.0", - "typescript": "3.7.3", - "underscore": "1.9.1" - }, - "dependencies": { - "typescript": { - "version": "3.7.3", - "resolved": "https://registry.npm.taobao.org/typescript/download/typescript-3.7.3.tgz?cache=0&sync_timestamp=1596790269694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftypescript%2Fdownload%2Ftypescript-3.7.3.tgz", - "integrity": "sha1-s2hAZooWRYpwJbnqv60Rtmq4XGk=" - } - } - }, - "pinus-robot-plugin": { - "version": "1.4.9", - "resolved": "https://registry.npm.taobao.org/pinus-robot-plugin/download/pinus-robot-plugin-1.4.9.tgz", - "integrity": "sha1-mvNp0vLKN6nfBcQTX+zLvT4C3qQ=", - "requires": { - "pinus": "^1.4.9", - "yargs": "^15.0.0" - } - }, - "pinus-rpc": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pinus-rpc/-/pinus-rpc-1.6.3.tgz", - "integrity": "sha512-AiNwqXONDOXN30adMQGtIDUUYrcucCzo+8oVXkqP31eJNWA6wvgMhiOd4OeGk5Rov2/1GTpuXi+qF7X2o6rq9A==", - "requires": { - "async": "^3.0.0", - "bearcat-buffer": "^0.1.x", - "bluebird": "^3.5.1", - "crc": "^3.8.0", - "mqtt-connection": "^4.1.0", - "pinus-loader": "^1.6.3", - "pinus-logger": "^1.6.3", - "socket.io": "^4.1.3", - "source-map-support": "^0.5.0", - "stream-pkg": "0.0.5", - "uuid": "^8.3.2", - "ws": "^7.0.0" - }, - "dependencies": { - "@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" - } - } - }, - "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" - } - }, - "socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", - "socket.io-parser": "~4.0.4" - } - }, - "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" - }, - "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - } - } - } - }, - "pinus-scheduler": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/pinus-scheduler/-/pinus-scheduler-1.4.10.tgz", - "integrity": "sha512-iqc9TV+rKMkQabCa+jI1Y/jP75lGUGU8QNwjtg3R6KdTV+pVx+NBfcYgMh/+zkJayzshK8XgqJII/GAT9qbDFA==", - "requires": { - "pinus-logger": "^1.4.10" - }, - "dependencies": { - "pinus-logger": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/pinus-logger/-/pinus-logger-1.4.10.tgz", - "integrity": "sha512-qKQw4YwvWttUJX6/18lneJupZfmgc092d+marA66BfSgPOyXvn/jB+IYQMuNzsGqN2KgF+T083QPmZioIXdTLA==", - "requires": { - "log4js": "^6.0.0" - } - } - } - }, - "pkginfo": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", - "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", - "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npm.taobao.org/proxy-agent/download/proxy-agent-4.0.1.tgz?cache=0&sync_timestamp=1610406773864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fproxy-agent%2Fdownload%2Fproxy-agent-4.0.1.tgz", - "integrity": "sha1-MmwyUHdscETNGWVcy/rfLgZaBFw=", - "requires": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^4.1.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.nlark.com/proxy-from-env/download/proxy-from-env-1.1.0.tgz", - "integrity": "sha1-4QLxbKNVQkhldV0sno6k8k1Yw+I=" - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", - "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.10.1.tgz", - "integrity": "sha1-STFIL6jWR6Wqt5nFJx0hM7mB+2o=", - "requires": { - "side-channel": "^1.0.4" - } - }, - "random-to": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/random-to/-/random-to-0.0.2.tgz", - "integrity": "sha1-RoO58lfPuWSqPXsyPgCKIMboWnY=" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.nlark.com/raw-body/download/raw-body-2.4.1.tgz", - "integrity": "sha1-MKyC+Yu1rowVLmcUnayNVRU7Fow=", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "read-last-lines": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/read-last-lines/-/read-last-lines-1.8.0.tgz", - "integrity": "sha512-oPL0cnZkhsO2xF7DBrdzVhXSNajPP5TzzCim/2IAjeGb17ArLLTRriI/ceV6Rook3L27mvbrOvLlf9xYYnaftQ==", - "requires": { - "mz": "^2.7.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", - "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - } - } - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "redis": { - "version": "3.0.2", - "resolved": "https://registry.npm.taobao.org/redis/download/redis-3.0.2.tgz?cache=0&sync_timestamp=1581290711215&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fredis%2Fdownload%2Fredis-3.0.2.tgz", - "integrity": "sha1-vUcGe4pKPmouVW5X9xzILHNgFQo=", - "requires": { - "denque": "^1.4.1", - "redis-commands": "^1.5.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - } - }, - "redis-commands": { - "version": "1.6.0", - "resolved": "https://registry.npm.taobao.org/redis-commands/download/redis-commands-1.6.0.tgz?cache=0&sync_timestamp=1595989738051&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fredis-commands%2Fdownload%2Fredis-commands-1.6.0.tgz", - "integrity": "sha1-NtTKQq6e0pgVzbMK2fl5guuhziM=" - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "redlock": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redlock/-/redlock-4.2.0.tgz", - "integrity": "sha512-j+oQlG+dOwcetUt2WJWttu4CZVeRzUrcVcISFmEmfyuwCVSJ93rDT7YSgg7H7rnxwoRyk/jU46kycVka5tW7jA==", - "requires": { - "bluebird": "^3.7.2" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npm.taobao.org/reflect-metadata/download/reflect-metadata-0.1.13.tgz", - "integrity": "sha1-Z648pXyXKiqhZCsQ/jY/4y1J3Ag=" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/regexp-clone/download/regexp-clone-1.0.0.tgz", - "integrity": "sha1-Ii25Z2IydwViYLmSYmNUoEzpv2M=" - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmmirror.com/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "request-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", - "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "requires": { - "lodash": "^4.17.19" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz", - "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=" - }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/require_optional/download/require_optional-1.0.1.tgz", - "integrity": "sha1-TPNaQkf2TKPfjC7yCMxJSxyo/C4=", - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.17.0.tgz", - "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" - }, - "rfdc": { - "version": "1.1.4", - "resolved": "https://registry.npm.taobao.org/rfdc/download/rfdc-1.1.4.tgz", - "integrity": "sha1-unLME2egzNnPgahws7WL060H+MI=" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz", - "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npm.taobao.org/saslprep/download/saslprep-1.0.3.tgz", - "integrity": "sha1-TAL5RrVs9UKX40e6EJPnrKxM8iY=", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", - "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" - }, - "seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" - }, - "sequin": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz", - "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE=" - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz", - "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npm.taobao.org/side-channel/download/side-channel-1.0.4.tgz", - "integrity": "sha1-785cj9wQTudRslxY1CkAEfpeos8=", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sift": { - "version": "7.0.1", - "resolved": "https://registry.npm.taobao.org/sift/download/sift-7.0.1.tgz", - "integrity": "sha1-R9YsULFZ0xbxNy+LU/nBDNIaSwg=" - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" - }, - "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npm.taobao.org/smart-buffer/download/smart-buffer-4.1.0.tgz", - "integrity": "sha1-kWBcJdkWUvRmHqacz0XxszHKIbo=" - }, - "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/socket.io/download/socket.io-2.3.0.tgz", - "integrity": "sha1-zXYu1qT67KWbwfPiQ8CWkxHrc/s=", - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.4.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", - "socket.io-parser": "~3.4.0" - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npm.taobao.org/socket.io-adapter/download/socket.io-adapter-1.1.2.tgz?cache=0&sync_timestamp=1574684498510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsocket.io-adapter%2Fdownload%2Fsocket.io-adapter-1.1.2.tgz", - "integrity": "sha1-qz8Nb2a4/H/KOVmrWZH4IiF4m+k=" - }, - "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/socket.io-client/download/socket.io-client-2.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsocket.io-client%2Fdownload%2Fsocket.io-client-2.3.0.tgz", - "integrity": "sha1-FNW6LgC5vNFFrkQ6uWs/hsvMG7Q=", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1575472461218&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npm.taobao.org/socket.io-parser/download/socket.io-parser-3.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsocket.io-parser%2Fdownload%2Fsocket.io-parser-3.3.0.tgz", - "integrity": "sha1-K1KpalCf3zFEC6QP7WCUx9TxJi8=", - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "2.0.0" - } - } - } - } - } - }, - "socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npm.taobao.org/socket.io-parser/download/socket.io-parser-3.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsocket.io-parser%2Fdownload%2Fsocket.io-parser-3.4.1.tgz", - "integrity": "sha1-sGr4ODApdYN+qy3JgAN9okBU1ko=", - "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "socks": { - "version": "2.6.1", - "resolved": "https://registry.npm.taobao.org/socks/download/socks-2.6.1.tgz?cache=0&sync_timestamp=1618719243252&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsocks%2Fdownload%2Fsocks-2.6.1.tgz", - "integrity": "sha1-mJ5lNKB88zfesbHJSqpEKWUg0w4=", - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.nlark.com/socks-proxy-agent/download/socks-proxy-agent-5.0.0.tgz", - "integrity": "sha1-fA82Tnsc9KekN+cSU77XLpAEvmA=", - "requires": { - "agent-base": "6", - "debug": "4", - "socks": "^2.3.3" - } - }, - "sorted-array-functions": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1587719493563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz", - "integrity": "sha1-qYti+G3K9PZzmWSMCFKRq56P7WE=", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmmirror.com/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "requires": { - "minipass": "^3.1.1" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, - "stream-pkg": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stream-pkg/-/stream-pkg-0.0.5.tgz", - "integrity": "sha1-kx/TMuLomR8GBEKUNBYL1qSC82U=" - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npm.taobao.org/streamroller/download/streamroller-2.2.4.tgz", - "integrity": "sha1-wZjO1C25QIamGTYIGHzoCl8rDlM=", - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-2.1.0.tgz?cache=0&sync_timestamp=1572559173297&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdate-format%2Fdownload%2Fdate-format-2.1.0.tgz", - "integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8=" - } - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz", - "integrity": "sha1-lSGCxGzHssMT0VluYjmSvRY7crU=", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - } - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", - "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "tenpay": { - "version": "2.1.18", - "resolved": "https://registry.npm.taobao.org/tenpay/download/tenpay-2.1.18.tgz", - "integrity": "sha1-yxfEZmCYOCemFCCJIs9PcKiaxyw=", - "requires": { - "urllib": "^2.33.0", - "xml2js": "^0.4.19" - } - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npm.taobao.org/thenify/download/thenify-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthenify%2Fdownload%2Fthenify-3.3.1.tgz", - "integrity": "sha1-iTLmhqQGYDigFt2eLKRq3Zg4qV8=", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "thinkingdata-node": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/thinkingdata-node/-/thinkingdata-node-1.2.2.tgz", - "integrity": "sha512-U5Nz2/OsFj3oFGboo/OmQcc1bcbibNJm2KVMPy7JpIVdYAH8U/VKzXCHfuVvbGSalLAdvMiBklL49r5uQnVqvw==", - "requires": { - "log4js": "^5.3.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==" - }, - "log4js": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-5.3.0.tgz", - "integrity": "sha512-PZHXaXJKMKEscvQxSnTjM4UosQalSDlNpMw63eCKW+/DiAFKIZPW1jGyIPXZDjiEYFusMfiI7zzvnxeGozUcAw==", - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.2" - } - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz", - "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=" - }, - "topo": { - "version": "3.0.3", - "resolved": "https://registry.npm.taobao.org/topo/download/topo-3.0.3.tgz", - "integrity": "sha1-1aZ/suaTB+vusIQC7Coqb1962Vw=", - "requires": { - "hoek": "6.x.x" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npm.taobao.org/ts-node/download/ts-node-8.10.2.tgz?cache=0&sync_timestamp=1590685779800&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fts-node%2Fdownload%2Fts-node-8.10.2.tgz", - "integrity": "sha1-7uA3ZGM7EjTd03+NuewQt17H+40=", - "requires": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-1.13.0.tgz", - "integrity": "sha1-yIHhPMcBWJTtkUhi0nZDb6mkcEM=", - "dev": true - }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npm.taobao.org/tslint/download/tslint-5.20.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslint%2Fdownload%2Ftslint-5.20.1.tgz", - "integrity": "sha1-5AHortoBUrxE3QfmFANPP4DGe30=", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1595168120323&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz", - "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", - "dev": true - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npm.taobao.org/tsutils/download/tsutils-2.29.0.tgz", - "integrity": "sha1-MrSIUBRnrL7dS4VJhnOggSrKC5k=", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmmirror.com/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - }, - "typegoose": { - "version": "5.9.1", - "resolved": "https://registry.npmmirror.com/typegoose/-/typegoose-5.9.1.tgz", - "integrity": "sha512-D+vMhNyZeKBZHrmJFZwOodl3T9W2NOXY+hbnW/f1n60oEL8+L15eryFc9C6fAKrlnkgpui+kdQnNXsLwx2MgCw==", - "requires": { - "reflect-metadata": "^0.1.13" - } - }, - "typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npm.taobao.org/underscore/download/underscore-1.9.1.tgz?cache=0&sync_timestamp=1585605854253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funderscore%2Fdownload%2Funderscore-1.9.1.tgz", - "integrity": "sha1-BtzjSg5op7q8KbNluOdLiSUgOWE=" - }, - "unescape": { - "version": "1.0.1", - "resolved": "https://registry.nlark.com/unescape/download/unescape-1.0.1.tgz", - "integrity": "sha1-lW5DD2HK2KTVfYLFGPXmzF0N2pY=", - "requires": { - "extend-shallow": "^2.0.1" - } - }, - "unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz", - "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urllib": { - "version": "2.37.1", - "resolved": "https://registry.npm.taobao.org/urllib/download/urllib-2.37.1.tgz?cache=0&sync_timestamp=1618453009809&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furllib%2Fdownload%2Furllib-2.37.1.tgz", - "integrity": "sha1-EBa4iqsysnBIpNUtNiA3ccY+Ow8=", - "requires": { - "any-promise": "^1.3.0", - "content-type": "^1.0.2", - "debug": "^2.6.9", - "default-user-agent": "^1.0.0", - "digest-header": "^0.0.1", - "ee-first": "~1.1.1", - "formstream": "^1.1.0", - "humanize-ms": "^1.2.0", - "iconv-lite": "^0.4.15", - "ip": "^1.1.5", - "proxy-agent": "^4.0.1", - "pump": "^3.0.0", - "qs": "^6.4.0", - "statuses": "^1.3.1", - "utility": "^1.16.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433856030&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utility": { - "version": "1.17.0", - "resolved": "https://registry.npm.taobao.org/utility/download/utility-1.17.0.tgz?cache=0&sync_timestamp=1608037982120&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futility%2Fdownload%2Futility-1.17.0.tgz", - "integrity": "sha1-YIGfcSpuDOd09S+x1pGZKl9Z02I=", - "requires": { - "copy-to": "^2.0.1", - "escape-html": "^1.0.3", - "mkdirp": "^0.5.1", - "mz": "^2.7.0", - "unescape": "^1.0.1" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmmirror.com/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "win-release": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "requires": { - "semver": "^5.0.1" - } - }, - "winston": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", - "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", - "requires": { - "async": "0.2.x", - "colors": "0.6.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "pkginfo": "0.3.x", - "stack-trace": "0.0.x" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" - }, - "colors": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", - "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz", - "integrity": "sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=" - }, - "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", - "dev": true - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz", - "integrity": "sha1-6Tk7oHEC5skaOyIUePAlfNKFblM=", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npm.taobao.org/ws/download/ws-7.3.1.tgz?cache=0&sync_timestamp=1593925670988&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fws%2Fdownload%2Fws-7.3.1.tgz", - "integrity": "sha1-0FR79n985PEqct/jEmLGjX3FUcg=" - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npm.taobao.org/xml2js/download/xml2js-0.4.23.tgz", - "integrity": "sha1-oMaVFnUkIesqx1juTUzPWIQ+rGY=", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-11.0.1.tgz", - "integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM=" - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npm.taobao.org/xmlhttprequest-ssl/download/xmlhttprequest-ssl-1.5.5.tgz?cache=0&sync_timestamp=1564594177335&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxmlhttprequest-ssl%2Fdownload%2Fxmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, - "xprofiler": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/xprofiler/-/xprofiler-2.5.1.tgz", - "integrity": "sha512-xPvrJqd22klQStM3Q9TVk33i5ZBMgHRkPbmNskjZz/6oOeKD66tEn56WoRlwpA81VL1WoYiIbEhxzOL/AOhHgA==", - "requires": { - "@xprofiler/node-pre-gyp": "^1.0.9", - "moment": "^2.29.4", - "nan": "^2.17.0", - "uuid": "^9.0.0", - "yargs": "^17.6.2" - }, - "dependencies": { - "@xprofiler/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/@xprofiler/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-dJSwF3UXDWRUIrqI+FTWyzwo+dxqDrKMIPD9hTHNvqotlu7Bsk8qqsGGMtNUgNV7QK0QwBozROJiW7iFkO9EHQ==", - "requires": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.5", - "node-gyp": "^9.3.1", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "7.4.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - } - } - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz", - "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-15.4.1.tgz", - "integrity": "sha1-DYehbeAa7p2L7Cv7909nhRcw9Pg=", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-18.1.3.tgz?cache=0&sync_timestamp=1595125671180&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-18.1.3.tgz", - "integrity": "sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A=", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npm.taobao.org/yn/download/yn-3.1.1.tgz", - "integrity": "sha1-HodAGgnXZ8HV6rJqbkwYUYLS61A=" - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/game-server/package.json b/game-server/package.json index 5aecf891c..9b9299c10 100644 --- a/game-server/package.json +++ b/game-server/package.json @@ -38,8 +38,9 @@ "ip2region": "^2.3.0", "koa-is-json": "^1.0.0", "local": "^0.3.3", + "log4js": "5.3.0", "moment": "^2.29.1", - "mongoose": "^5.10.4", + "mongoose": "^5.10.18", "mongoose-lean-getters": "^0.1.2", "mongoose-lean-virtuals": "^0.7.6", "mongoose-transactions": "^1.1.4", @@ -57,13 +58,13 @@ "tenpay": "^2.1.18", "thinkingdata-node": "^1.2.2", "ts-node": "^8.2.0", + "tsconfig-paths": "^4.2.0", "typegoose": "^5.9.1", "xprofiler": "^2.5.1" }, "devDependencies": { "@types/node-schedule": "^1.3.1", "mocha": "^8.4.0", - "mocha-parallel-tests": "^2.3.0", "tslint": "^5.9.1", "typescript": "^4.4.4" } diff --git a/game-server/tsconfig.json b/game-server/tsconfig.json index 80a274dd7..486bf6c29 100644 --- a/game-server/tsconfig.json +++ b/game-server/tsconfig.json @@ -8,6 +8,7 @@ "module": "commonjs", //指定生成哪个模块系统代码 "target": "es2017", "resolveJsonModule": true, + "skipLibCheck": true, "lib": [ "es2015", "es2016", @@ -18,12 +19,21 @@ "noImplicitThis": true, "inlineSourceMap": true, //用于debug - "rootDirs": ["."], //仅用来控制输出的目录结构--outDir。 + "rootDirs": [".", "../shared"], //仅用来控制输出的目录结构--outDir。 "outDir":"./dist", //重定向输出目录。 "experimentalDecorators":true, "emitDecoratorMetadata": true, "moduleResolution": "node", - "watch":false //在监视模式下运行编译器。会监视输出文件,在它们改变时重新编译。 + "baseUrl": ".", + "paths": { + "@consts": ["../shared/consts"], + "@consts/*": ["../shared/consts/*"], + "@db": ["../shared/db"], + "@db/*": ["../shared/db/*"], + "@domain/*": ["../shared/domain/*"], + "@pubUtils/*": ["../shared/pubUtils/*", "app/services/*", "app/util/*"], + "@resource/*": ["../shared/resource/*"] + } }, "include":[ "./app/**/*.json", diff --git a/game-server/tsrun.js b/game-server/tsrun.js index 3491e7499..56da21f67 100644 --- a/game-server/tsrun.js +++ b/game-server/tsrun.js @@ -1,34 +1,6 @@ +process.env.NODE_OPTIONS = '--openssl-legacy-provider'; + +require('tsconfig-paths/register'); require('ts-node/register'); -// -// 如果堆栈信息不准确.取消注释下面的代码应该可以解决. -// 参考 ts-node 下错误堆栈问题排查小记: https://zhuanlan.zhihu.com/p/43181384 -// -/* -const sourceMapSupport = require('source-map-support'); -const cacheMap = {}; -const extensions = ['.ts', '.tsx']; - -sourceMapSupport.install({ - environment: 'node', - retrieveFile: function (path) { - // 根据路径找缓存的编译后的代码 - return cacheMap[path]; - } -}); - -extensions.forEach(ext => { - const originalExtension = require.extensions[ext]; - require.extensions[ext] = (module, filePath) => { - const originalCompile = module._compile; - module._compile = function(code, filePath) { - // 缓存编译后的代码 - cacheMap[filePath] = code; - return originalCompile.call(this, code, filePath); - }; - return originalExtension(module, filePath); - }; -}) - - */ require('./app'); diff --git a/gm-server/.github/workflows/nodejs.yml b/gm-server/.github/workflows/nodejs.yml index 81041c4bc..31e86f96a 100644 --- a/gm-server/.github/workflows/nodejs.yml +++ b/gm-server/.github/workflows/nodejs.yml @@ -5,9 +5,13 @@ name: Node.js CI on: push: - branches: [ master ] + branches: + - main + - master pull_request: - branches: [ master ] + branches: + - main + - master schedule: - cron: '0 2 * * *' @@ -31,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Dependencies - run: npm i -g npminstall && npminstall + run: npm i -g npminstall@5 && npminstall - name: Continuous Integration run: npm run ci diff --git a/gm-server/.travis.yml b/gm-server/.travis.yml index 9749f42d5..fc5fd2a56 100644 --- a/gm-server/.travis.yml +++ b/gm-server/.travis.yml @@ -3,7 +3,7 @@ language: node_js node_js: - '8' before_install: - - npm i npminstall -g + - npm i npminstall@5 -g install: - npminstall script: diff --git a/gm-server/appveyor.yml b/gm-server/appveyor.yml index c274b7d35..5fd5337de 100644 --- a/gm-server/appveyor.yml +++ b/gm-server/appveyor.yml @@ -4,7 +4,7 @@ environment: install: - ps: Install-Product node $env:nodejs_version - - npm i npminstall && node_modules\.bin\npminstall + - npm i npminstall@5 && node_modules\.bin\npminstall test_script: - node --version diff --git a/gm-server/package-lock.json b/gm-server/package-lock.json deleted file mode 100644 index cd2db131b..000000000 --- a/gm-server/package-lock.json +++ /dev/null @@ -1,11786 +0,0 @@ -{ - "name": "gm-server", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", - "dev": true, - "requires": { - "@babel/types": "^7.11.5", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } - } - }, - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", - "dev": true - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - } - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@eggjs/router": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eggjs/router/-/router-2.0.0.tgz", - "integrity": "sha512-ViFlE/09kgaSMgH+nGozweJYr0bVBUvG72GmTv+i7OPIxK9uj1Z1GpSTT3zB6mBfnvakvErPR5jUBsl2wBrcHA==", - "requires": { - "co": "^4.6.0", - "debug": "^3.1.0", - "http-errors": "^1.3.1", - "inflection": "^1.12.0", - "is-type-of": "^1.2.1", - "koa-compose": "^3.0.0", - "koa-convert": "^1.2.0", - "methods": "^1.0.1", - "path-to-regexp": "^1.1.1", - "urijs": "^1.19.0", - "utility": "^1.15.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - }, - "dependencies": { - "@types/yargs": { - "version": "13.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.10.tgz", - "integrity": "sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - } - } - }, - "@koa/cors": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-3.1.0.tgz", - "integrity": "sha512-7ulRC1da/rBa6kj6P4g2aJfnET3z8Uf3SWu60cjbtxTA5g8lxRdX/Bd2P92EagGwwAhANeNw8T8if99rJliR6Q==", - "requires": { - "vary": "^1.1.2" - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" - }, - "@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" - }, - "@types/cookiejar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz", - "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==", - "dev": true - }, - "@types/cookies": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", - "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", - "requires": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/dargs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha512-2cXlO8pz13kVYMp6Zgr8Z5DACbaGfoBp7svqZqPGcO+qG3LQLWdB5BzPPASj+UI447XxGmFHi6KjLgUB0fzucQ==" - }, - "@types/depd": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/@types/depd/-/depd-1.1.32.tgz", - "integrity": "sha512-kB2cpXs3A0TGWl4a4h74yIwvclYZUTW6Irpee/3Dc1s4Cr5rGPHtpGPpBBpEV1MaKH5z/oul+57oDkEkeRXRnw==", - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/empower": { - "version": "1.2.30", - "resolved": "https://registry.npmjs.org/@types/empower/-/empower-1.2.30.tgz", - "integrity": "sha1-x8/BSzph5Ux0xnTB+8kbot8NE5I=", - "dev": true - }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true - }, - "@types/express": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", - "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz", - "integrity": "sha512-EaEdY+Dty1jEU7U6J4CUWwxL+hyEGMkO5jan5gplfegUgCUsIUWqXxqw47uGjimeT4Qgkz/XUfwoau08+fgvKA==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/http-assert": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", - "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" - }, - "@types/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==" - }, - "@types/http-proxy": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz", - "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==", - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" - }, - "@types/koa": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.4.tgz", - "integrity": "sha512-Etqs0kdqbuAsNr5k6mlZQelpZKVwMu9WPRHVVTLnceZlhr0pYmblRNJbCgoCMzKWWePldydU0AYEOX4Q9fnGUQ==", - "requires": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "requires": { - "@types/koa": "*" - } - }, - "@types/koa-router": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/koa-router/-/koa-router-7.4.1.tgz", - "integrity": "sha512-Hg78TXz78QYfEgdq3nTeRmQFEwJKZljsXb/DhtexmyrpRDRnl59oMglh9uPj3/WgKor0woANrYTnxA8gaWGK2A==", - "requires": { - "@types/koa": "*" - } - }, - "@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "2.2.48", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", - "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", - "dev": true - }, - "@types/node": { - "version": "7.10.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.12.tgz", - "integrity": "sha512-SieeKQUj5NbRKZtRH/6T3H2XQCraXqSEc+gABTXNtL4uwPtXmoZEaHJ3WJylfwF3vJzj5ha6Aq8h9dbKFBINiQ==" - }, - "@types/power-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/power-assert/-/power-assert-1.5.3.tgz", - "integrity": "sha512-PzV9RX7RRUBYLxp52ipXo9dSvBnqVR09mcvGt3hXuzoJt0EUpPPv0X3btjCQqrhQ1xLbyt0dfPiGfRfrZB4G0A==", - "dev": true, - "requires": { - "@types/empower": "*", - "@types/power-assert-formatter": "*" - } - }, - "@types/power-assert-formatter": { - "version": "1.4.29", - "resolved": "https://registry.npmjs.org/@types/power-assert-formatter/-/power-assert-formatter-1.4.29.tgz", - "integrity": "sha512-K3kBfCD4xnx+W5xLVbkyiKUKHvkZBL3R2fS3/wSoFJORcXdzN3ir13zTok1wNnH+hbv8Wc+YTWJDyqEdNsEXzg==", - "dev": true - }, - "@types/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==" - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" - }, - "@types/serve-static": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", - "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "@types/superagent": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.10.tgz", - "integrity": "sha512-xAgkb2CMWUMCyVc/3+7iQfOEBE75NvuZeezvmixbUw3nmENf2tCnQkW5yQLTYqvXUQ+R6EXxdqKKbal2zM5V/g==", - "dev": true, - "requires": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "@types/supertest": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.10.tgz", - "integrity": "sha512-Xt8TbEyZTnD5Xulw95GLMOkmjGICrOQyJ2jqgkSjAUR3mm7pAIzSR0NFBaMcwlzVvlpCjNwbATcWWwjNiZiFrQ==", - "dev": true, - "requires": { - "@types/superagent": "*" - } - }, - "@types/yargs": { - "version": "12.0.18", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.18.tgz", - "integrity": "sha512-S5zJIrr2/n0DJpbwfpUc7wt9zQF0Y4GYKecxjPZ/25xPfsCIl+u+wD/HjyNZ6QPwmDPcPJmt9uMXtriRW/FiAw==" - }, - "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz", - "integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "3.10.1", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", - "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", - "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", - "dev": true, - "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.10.1", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-visitor-keys": "^1.1.0" - } - }, - "@typescript-eslint/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", - "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", - "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/visitor-keys": "3.10.1", - "debug": "^4.1.1", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", - "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true - }, - "acorn-es7-plugin": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", - "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.3.tgz", - "integrity": "sha512-wn8fw19xKZwdGPO47jivonaHRTd+nGOMP1z11sgGeQzDy2xd5FG0R67dIMcKHDE2cJ5y+YXV30XVGUBPRSY7Hg==", - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "agentx": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/agentx/-/agentx-1.10.7.tgz", - "integrity": "sha512-RW74AfrErchL0/lqFUgeBYyACFQtFVSAuTTJtRVFn1EQ1zsEhKJKnEoLTNckfm/g+mvWlD+IhaPyfuvPKXbWNw==", - "requires": { - "debug": "^3.1.0", - "nounou": "^1.2.1", - "split2": "^2.2.0", - "through2": "^2.0.3", - "ws": "^1.1.5" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", - "dev": true - }, - "array-find": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz", - "integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=", - "dev": true - }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "array.prototype.flatmap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", - "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "ast-types": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", - "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", - "requires": { - "tslib": "^2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" - } - } - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "autod": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/autod/-/autod-3.1.0.tgz", - "integrity": "sha512-sx9phRpnxeAD4tbsqXyidDLuOWuXRIbRUEj8i9GXO9Izucrq4E+LRFPGXayEVkF4SfUJRumLTNblxiz7KfzxgQ==", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-preset-env": "^1.6.1", - "babel-preset-react": "^6.24.1", - "babel-preset-stage-0": "^6.24.1", - "co": "^4.6.0", - "colors": "^1.1.2", - "commander": "^2.11.0", - "crequire": "^1.8.1", - "debug": "^3.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.1.2", - "minimatch": "^3.0.4", - "printable": "^0.0.3", - "semver": "^6.0.0", - "urllib": "^2.25.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "autod-egg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/autod-egg/-/autod-egg-1.1.0.tgz", - "integrity": "sha512-dZ5ZRiHcHaehQnpEBWmxHTvQfIHKUdr10Qlrs/ZdBfb6NG2lUfNlVUGnqNVkp9wFsJJTGdN7ADmW9gkN8bSLrg==", - "dev": true - }, - "await-event": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/await-event/-/await-event-2.1.0.tgz", - "integrity": "sha1-eOn5JoS65AIvn6C18xShFVD5qnY=" - }, - "await-first": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/await-first/-/await-first-1.0.0.tgz", - "integrity": "sha512-SK20HicVu6lXvNM0nS1flurrs4/1NdhvccvEn52Gf+vpERZnnkKBnJvAQDsYkzJnsHs1bRNNKEiobEet7a/0TA==", - "requires": { - "ee-first": "^1.1.1" - } - }, - "await-stream-ready": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/await-stream-ready/-/await-stream-ready-1.0.1.tgz", - "integrity": "sha1-+jCMY/4UrHqQlmrXCCKqk2n4prs=" - }, - "axe-core": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", - "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-eslint": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz", - "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/traverse": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "^1.0.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", - "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.44" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", - "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44", - "jsesc": "^2.5.1", - "lodash": "^4.2.0", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", - "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.44", - "@babel/template": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", - "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", - "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", - "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", - "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "lodash": "^4.2.0" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", - "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/generator": "7.0.0-beta.44", - "@babel/helper-function-name": "7.0.0-beta.44", - "@babel/helper-split-export-declaration": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.2.0" - } - }, - "@babel/types": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", - "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^2.0.0" - } - }, - "babylon": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", - "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "^6.18.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } - }, - "babel-preset-stage-0": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "^6.22.0", - "babel-plugin-transform-function-bind": "^6.22.0", - "babel-preset-stage-1": "^6.24.1" - } - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "^6.24.1", - "babel-plugin-transform-export-extensions": "^6.22.0", - "babel-preset-stage-2": "^6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - }, - "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" - }, - "bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", - "requires": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" - } - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "black-hole-stream": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/black-hole-stream/-/black-hole-stream-0.0.1.tgz", - "integrity": "sha1-M7ega58edFPWBBuCl0SB0hUq6kI=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - } - }, - "byte": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/byte/-/byte-2.0.0.tgz", - "integrity": "sha512-rNiK8YxOMvquToaBubKxA10sjRIZ/taDqtc/1jLQA4X7aNDlA1XGx4Ciml3YxL8DskFz1XX3WFskSp0peKYSKg==", - "requires": { - "debug": "^3.1.0", - "long": "^4.0.0", - "utility": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "bytes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "requires": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - } - }, - "cache-require-paths": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/cache-require-paths/-/cache-require-paths-0.3.0.tgz", - "integrity": "sha1-EqYHWj5JiNpMIvIY4pSFZj5MSmM=", - "dev": true - }, - "call-matcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.1.0.tgz", - "integrity": "sha512-IoQLeNwwf9KTNbtSA7aEBb1yfDbdnzwjCetjkC8io5oGeOmK2CBNdg0xr+tadRYKO0p7uQyZzvon0kXlZbvGrw==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "deep-equal": "^1.0.0", - "espurify": "^1.6.0", - "estraverse": "^4.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "call-signature": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", - "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "caniuse-lite": { - "version": "1.0.30001131", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz", - "integrity": "sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==", - "dev": true - }, - "cfork": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/cfork/-/cfork-1.8.0.tgz", - "integrity": "sha512-DrCPQ4GWbaz4cJWRKh7YycAa0o2V1pFJyUNpCGWSzMGKlLY1+yRnnbBQzz/2BIafcu4UUDFoNIme8pF6b15fGg==", - "requires": { - "utility": "^1.12.0" - } - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "requires": { - "traverse": ">=0.3.0 <0.4" - }, - "dependencies": { - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" - } - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chan": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/chan/-/chan-0.6.1.tgz", - "integrity": "sha1-7ArRMuW8YsJ+8QzL/E2NzYygBkA=" - }, - "change-case": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz", - "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==", - "requires": { - "camel-case": "^3.0.0", - "constant-case": "^2.0.0", - "dot-case": "^2.1.0", - "header-case": "^1.0.0", - "is-lower-case": "^1.1.0", - "is-upper-case": "^1.1.0", - "lower-case": "^1.1.1", - "lower-case-first": "^1.0.0", - "no-case": "^2.3.2", - "param-case": "^2.1.0", - "pascal-case": "^2.0.0", - "path-case": "^2.1.0", - "sentence-case": "^2.1.0", - "snake-case": "^2.1.0", - "swap-case": "^1.1.0", - "title-case": "^2.1.0", - "upper-case": "^1.1.1", - "upper-case-first": "^1.1.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "child_process": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", - "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "circular-json-for-egg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/circular-json-for-egg/-/circular-json-for-egg-1.0.0.tgz", - "integrity": "sha512-BzMR1dg0+YqcFoMETHq0gFeQNNKliXI1Oe+C0nx/4npLaohsR7/Oj3UFht65MLwF7zs6x13gOr+f4+JeYni6vw==" - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "cluster-client": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cluster-client/-/cluster-client-3.0.1.tgz", - "integrity": "sha512-j5xReT5tECbiUME8TCNDU5ise34vSqbhWMs7Ni06VDKlKvRVAlUbrgYCFQc27Bw7MF8H+QEJ/8GJtk/HGx4u6w==", - "requires": { - "byte": "^2.0.0", - "co": "^4.6.0", - "debug": "^4.1.1", - "egg-logger": "^2.3.2", - "is-type-of": "^1.2.1", - "json-stringify-safe": "^5.0.1", - "long": "^4.0.0", - "mz-modules": "^2.1.0", - "sdk-base": "^3.5.1", - "serialize-json": "^1.0.3", - "tcp-base": "^3.1.0", - "utility": "^1.15.0" - } - }, - "cluster-reload": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cluster-reload/-/cluster-reload-1.0.2.tgz", - "integrity": "sha1-NGv1hJ0Y5FkLzBsw7kcNTKvxXBA=" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "co-body": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", - "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", - "requires": { - "inflation": "^2.0.0", - "qs": "^6.5.2", - "raw-body": "^2.3.3", - "type-is": "^1.6.16" - } - }, - "co-busboy": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/co-busboy/-/co-busboy-1.4.1.tgz", - "integrity": "sha512-ec1GTa1psuvngN+821rEYeEahresYHzUB74f6kRzaoD4ZcmMuhJkgVns9YW9Zt2cgcQVtGOFraRzJscO8zbDyw==", - "requires": { - "black-hole-stream": "~0.0.1", - "busboy": "^0.2.8", - "chan": "^0.6.1" - } - }, - "co-mocha": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/co-mocha/-/co-mocha-1.2.2.tgz", - "integrity": "sha512-ocdJRn3sxonOqpdjSU2VwTwWzjTSoatzsTqCWiC3eGvJFNs8ZNMlZwfgYolQCdfddMz4muiZl99KIV9gKoNvxg==", - "dev": true, - "requires": { - "co": "^4.0.0", - "is-generator": "^1.0.1" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "coffee": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/coffee/-/coffee-5.4.0.tgz", - "integrity": "sha512-YI0t6g78gf2YroH+hjees7LfiQfo7XnTwYAShp0PHp6fUgxV6wkbolIX+z1+mbNws48TfWVp59OpLeb/bWqvNw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.5", - "debug": "^4.1.0", - "is-type-of": "^1.2.1" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commandx": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/commandx/-/commandx-1.5.4.tgz", - "integrity": "sha512-DTb4nXLwTTSa500Ga3zn2bdVNsGV9L2bcsnZPs6Sx/M5OC57EoEgHR7J6J3VZtBnMJ6qJBOd7oGr0CpCe0pA7w==", - "requires": { - "formstream": "^1.1.0", - "tunnel-agent": "^0.6.0", - "urllib": "^2.22.0" - } - }, - "comment-parser": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.5.5.tgz", - "integrity": "sha512-oB3TinFT+PV3p8UwDQt71+HkG03+zwPwikDlKU6ZDmql6QX2zFlQ+G0GGSDqyJhdZi4PSlzFBm+YJ+ebOX3Vgw==", - "dev": true - }, - "common-bin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/common-bin/-/common-bin-2.9.0.tgz", - "integrity": "sha512-VYKiPMPx+hrd53QVJmwm7mpdbIHM4ZPaHXjHE34s4vfGDgAAKHr2v4PRzqM2crEA3vZO9pLSs4eJIXrYCFmKXg==", - "requires": { - "@types/dargs": "^5.1.0", - "@types/node": "^10.12.18", - "@types/yargs": "^12.0.4", - "chalk": "^2.4.1", - "change-case": "^3.0.2", - "co": "^4.6.0", - "dargs": "^6.0.0", - "debug": "^4.1.0", - "is-type-of": "^1.2.1", - "semver": "^5.5.1", - "yargs": "^12.0.2", - "yargs-parser": "^11.0.0" - }, - "dependencies": { - "@types/node": { - "version": "10.17.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.34.tgz", - "integrity": "sha512-DlT8xondSSUixRxkdXQ3+dIZmCWkM6PX8kqIx1Zqp+FA/GmHJwqPixMeF89OirKVCFBh7U1m1I1Oj4gSrUW5oQ==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compressing": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/compressing/-/compressing-1.5.1.tgz", - "integrity": "sha512-1AGBR4Vh0/rpPKSXHoV9cerLo0CUlAhZ/xsJqU3a9+2cbSaFjWT3fk2MIGkCnbpk//DGWrcWw03rhKFQrA9RQw==", - "requires": { - "flushwritable": "^1.0.0", - "get-ready": "^1.0.0", - "iconv-lite": "^0.5.0", - "mkdirp": "^0.5.1", - "pump": "^3.0.0", - "streamifier": "^0.1.1", - "tar-stream": "^1.5.2", - "yauzl": "^2.7.0", - "yazl": "^2.4.2" - }, - "dependencies": { - "get-ready": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz", - "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I=" - }, - "iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "constant-case": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", - "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", - "requires": { - "snake-case": "^2.1.0", - "upper-case": "^1.1.1" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "requires": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-to": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, - "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "requires": { - "buffer": "^5.1.0" - } - }, - "crequire": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/crequire/-/crequire-1.8.1.tgz", - "integrity": "sha1-rIHyBHhrXyARlOsWmM9EGxCktX0=", - "dev": true - }, - "cron-parser": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.16.3.tgz", - "integrity": "sha512-XNJBD1QLFeAMUkZtZQuncAAOgJFWNhBdIbwgD22hZxrcWOImBFMKgPC66GzaXpyoJs7UvYLLgPH/8BRk/7gbZg==", - "requires": { - "is-nan": "^1.3.0", - "moment-timezone": "^0.5.31" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "csprng": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz", - "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=", - "requires": { - "sequin": "*" - } - }, - "csrf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", - "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.6", - "uid-safe": "2.1.5" - } - }, - "cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "damerau-levenshtein": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", - "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", - "dev": true - }, - "dargs": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.1.0.tgz", - "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==" - }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" - }, - "debounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", - "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "default-user-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", - "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", - "requires": { - "os-name": "~1.0.3" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, - "detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "requires": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "requires": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", - "dev": true - }, - "digest-header": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz", - "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", - "requires": { - "utility": "0.1.11" - }, - "dependencies": { - "utility": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz", - "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", - "requires": { - "address": ">=0.0.1" - } - } - } - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", - "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=", - "requires": { - "no-case": "^2.2.0" - } - }, - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "egg": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/egg/-/egg-2.28.0.tgz", - "integrity": "sha512-vFzVx7iX+eegE+EXEaPY0N3tsLYuN6tXGOAw4MsFjjSZvswEIo9tKnYo6C5DE9EFxEPArkYuVwx07x4IolypjQ==", - "requires": { - "@types/accepts": "^1.3.5", - "@types/koa": "^2.0.48", - "@types/koa-router": "^7.0.40", - "accepts": "^1.3.5", - "agentkeepalive": "^4.0.2", - "cache-content-type": "^1.0.1", - "circular-json-for-egg": "^1.0.0", - "cluster-client": "^3.0.1", - "debug": "^4.1.1", - "delegates": "^1.0.0", - "egg-cluster": "^1.23.0", - "egg-cookies": "^2.3.0", - "egg-core": "^4.18.0", - "egg-development": "^2.4.2", - "egg-i18n": "^2.0.0", - "egg-jsonp": "^2.0.0", - "egg-logger": "^2.3.2", - "egg-logrotator": "^3.0.5", - "egg-multipart": "^2.4.0", - "egg-onerror": "^2.1.0", - "egg-schedule": "^3.6.0", - "egg-security": "^2.4.3", - "egg-session": "^3.1.0", - "egg-static": "^2.2.0", - "egg-view": "^2.1.2", - "egg-watcher": "^3.1.0", - "extend2": "^1.0.0", - "graceful": "^1.0.2", - "humanize-ms": "^1.2.1", - "is-type-of": "^1.2.1", - "koa-bodyparser": "^4.2.1", - "koa-is-json": "^1.0.0", - "koa-override": "^3.0.0", - "ms": "^2.1.1", - "mz": "^2.7.0", - "on-finished": "^2.3.0", - "semver": "^7.3.2", - "sendmessage": "^1.1.0", - "urllib": "^2.33.0", - "utility": "^1.15.0", - "ylru": "^1.2.1" - } - }, - "egg-alinode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/egg-alinode/-/egg-alinode-2.0.1.tgz", - "integrity": "sha512-ZzZdFITE8qlZ+W4yFzKYCCieKPV8CqNRIfDCxtq+0OEQZiYVv4FBUTTsr2AII5Dx5e1NbmS22HG5jEx97NEZQw==", - "requires": { - "agentx": "^1.8.4", - "commandx": "^1.3.3", - "mkdirp": "^0.5.1", - "moment": "^2.17.1", - "mz": "^2.6.0", - "node-homedir": "^1.1.0" - } - }, - "egg-bin": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/egg-bin/-/egg-bin-4.15.0.tgz", - "integrity": "sha512-g+u7B1bRZpi1EMYNGN6YZlCWQsntoq05yDRLSxWNL5bC2bj7PLaPiUEnM1kS4qLJz5DJuwMGXzXJKsSvczeGYg==", - "dev": true, - "requires": { - "autod": "^3.1.0", - "chalk": "^2.4.2", - "co-mocha": "^1.2.2", - "common-bin": "^2.9.0", - "debug": "^4.1.1", - "detect-port": "^1.3.0", - "egg-ts-helper": "^1.25.2", - "egg-utils": "^2.4.1", - "espower-typescript": "9.0.1", - "globby": "^9.2.0", - "inspector-proxy": "^1.2.1", - "intelli-espower-loader": "^1.0.1", - "jest-changed-files": "^24.7.0", - "mocha": "^6.0.2", - "mz-modules": "^2.1.0", - "nyc": "^13.3.0", - "power-assert": "^1.6.1", - "semver": "^6.0.0", - "test-exclude": "^5.1.0", - "ts-node": "^7", - "ypkgfiles": "^1.6.0" - }, - "dependencies": { - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "egg-ts-helper": { - "version": "1.25.8", - "resolved": "https://registry.npmjs.org/egg-ts-helper/-/egg-ts-helper-1.25.8.tgz", - "integrity": "sha512-aRD1f4mP3ALqsqTcbET5vU1W5RCWNoGnP36QnIwW3qNb6qNRZo+czY0HjKpvOblzGKdcr+DIP0xEmp672lkJtQ==", - "dev": true, - "requires": { - "cache-require-paths": "^0.3.0", - "chalk": "^2.4.2", - "chokidar": "^2.0.1", - "commander": "^2.15.1", - "debug": "^3.1.0", - "dot-prop": "^4.2.0", - "enquirer": "^2.3.0", - "globby": "^8.0.1", - "mkdirp": "^0.5.1", - "ts-node": "^7.0.0", - "tslib": "^1.9.3", - "typescript": "^3.0.0", - "yn": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - }, - "dependencies": { - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "egg-ci": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/egg-ci/-/egg-ci-1.18.0.tgz", - "integrity": "sha512-WqUG5vuSGsqNlBLD2uYB8rqXlC8J59ct+fuhbJFDZvSpvPQrNGqGOpcchMt/sAnOXLumtLHvlnltxvA9VhOsEA==", - "dev": true, - "requires": { - "nunjucks": "^3.1.3" - } - }, - "egg-cluster": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/egg-cluster/-/egg-cluster-1.26.0.tgz", - "integrity": "sha512-+HJ2vT28HI+Dlt11/aJN2WpudvuJ/snwdsq5PAoyC61jl8SP4bhZQvAfojsEY1RVFctLq0ky4My0cujDk0SUlQ==", - "requires": { - "await-event": "^2.1.0", - "cfork": "^1.7.1", - "cluster-reload": "^1.0.2", - "co": "^4.6.0", - "debug": "^4.1.1", - "depd": "^2.0.0", - "detect-port": "^1.3.0", - "egg-logger": "^2.3.2", - "egg-utils": "^2.4.1", - "get-ready": "^2.0.1", - "graceful-process": "^1.2.0", - "is-type-of": "^1.2.1", - "mz-modules": "^2.1.0", - "ps-tree": "^1.2.0", - "semver": "^5.6.0", - "sendmessage": "^1.1.0", - "utility": "^1.15.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "egg-cookies": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/egg-cookies/-/egg-cookies-2.4.2.tgz", - "integrity": "sha512-NxGwoH+d62SHDfD8fOMdG2tmBwCKhHUnhUZRbMLKW7KbJx3JDxYZmGl9RkAtVJiEVwMWbEwj2WzJEgGwaQQfKQ==", - "requires": { - "debug": "^3.1.0", - "scmp": "^2.0.0", - "should-send-same-site-none": "^2.0.2", - "utility": "^1.14.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "egg-core": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/egg-core/-/egg-core-4.19.1.tgz", - "integrity": "sha512-oqIhXmJnm/m718fEHgD/7fKcDez9L3irXKNggANZP0KY1Xm9Op96ZiCtjvQ8Ao5D26yp7YEhcj8VqUOHOIcfWA==", - "requires": { - "@eggjs/router": "^2.0.0", - "@types/depd": "^1.1.32", - "@types/koa": "^2.0.48", - "co": "^4.6.0", - "debug": "^4.1.1", - "depd": "^2.0.0", - "egg-logger": "^2.4.1", - "egg-path-matching": "^1.0.1", - "extend2": "^1.0.0", - "get-ready": "^2.0.1", - "globby": "^8.0.2", - "is-type-of": "^1.2.1", - "koa": "^2.7.0", - "koa-convert": "^1.2.0", - "node-homedir": "^1.1.1", - "ready-callback": "^2.1.0", - "utility": "^1.16.1" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, - "egg-cors": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/egg-cors/-/egg-cors-2.2.3.tgz", - "integrity": "sha512-MLG4pQekZpycLXR45ZAIgFpFYshosBxu1CMdhXAzqPzxUn0xI21gVzqLqcxUrzzulaErCwG6qMXaS1eFyj9u2w==", - "requires": { - "@koa/cors": "^3.0.0" - } - }, - "egg-development": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/egg-development/-/egg-development-2.7.0.tgz", - "integrity": "sha512-vPkC+Wngm/a48bj0rXpvTOmSjslBnygCsjBG7qahJ1PuCs0f10KrOGOGY9JzOW6KpfjKSPb+Y21mpzkxBJ9q2Q==", - "requires": { - "debounce": "^1.1.0", - "multimatch": "^2.1.0", - "mz": "^2.7.0", - "mz-modules": "^2.1.0", - "utility": "^1.13.1" - } - }, - "egg-http-proxy-middleware": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/egg-http-proxy-middleware/-/egg-http-proxy-middleware-1.0.3.tgz", - "integrity": "sha512-mS5MGg8sBNMaWGieJ8DJ/+f51dQTl303v7wvxSM+w4yE5AsQx8Lh9pIY2PpBk/OvvPBHpwEuMNU23tSH7qQcQQ==", - "requires": { - "http-proxy-middleware": "^1.0.4", - "is-glob": "^4.0.1", - "koa-connect": "^2.1.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "egg-i18n": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/egg-i18n/-/egg-i18n-2.1.1.tgz", - "integrity": "sha512-rpKP2nrUzeTOkjQObvlrLbb/BZAMtP7zeoGggwJLN9+zKbFKVkeF6Q0BrpuucDSekD+2oHQz7fC3w/5eQY1g8w==", - "requires": { - "debug": "^3.1.0", - "koa-locales": "^1.11.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "egg-jsonp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/egg-jsonp/-/egg-jsonp-2.0.0.tgz", - "integrity": "sha512-dno7BXAvSFO0WTb3GJD0aci9MFlaQhdgvEznwARam75GGJdLpg1K0XQq88/dEvYWHxEHa+iGIOXcNx5NOyyUHw==", - "requires": { - "is-type-of": "^1.2.0", - "jsonp-body": "^1.0.0" - } - }, - "egg-logger": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/egg-logger/-/egg-logger-2.4.2.tgz", - "integrity": "sha512-HsZjAqafizTVujCkaBulT9b6Nrc5S97BvH30iXeFJz9eL2pHQpzsMCw5s1k5e1RxrvhidtNUX+avJmmfRpXnTQ==", - "requires": { - "chalk": "^2.4.1", - "circular-json-for-egg": "^1.0.0", - "debug": "^2.6.9", - "depd": "^2.0.0", - "iconv-lite": "^0.4.24", - "mkdirp": "^0.5.1", - "utility": "^1.15.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "egg-logrotator": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/egg-logrotator/-/egg-logrotator-3.1.0.tgz", - "integrity": "sha512-3kUmUO9UxFiiN4lSvRqzu44UjfTHYD3wqBKsQU7e5PtjSwdQTkbjSp4YvGcbaTlQp0Yp3i/aEc/rBcYH/e/gjw==", - "requires": { - "debug": "^4.1.1", - "moment": "^2.24.0", - "mz": "^2.7.0" - } - }, - "egg-mock": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/egg-mock/-/egg-mock-3.25.1.tgz", - "integrity": "sha512-2euNxl9sQhdk7SWix2/yw/EWVqYLB1n4V1L9fOmqr0LViBZLeb/wrzXSAd6JJG0qj8ki5FHwxTzSTWxOtGUOfg==", - "dev": true, - "requires": { - "@types/power-assert": "^1.5.0", - "@types/supertest": "^2.0.7", - "await-event": "^2.1.0", - "co": "^4.6.0", - "coffee": "^5.2.1", - "debug": "^4.1.1", - "detect-port": "^1.3.0", - "egg-logger": "^2.4.1", - "egg-utils": "^2.4.1", - "extend2": "^1.0.0", - "get-ready": "^2.0.1", - "globby": "^9.2.0", - "is-type-of": "^1.2.1", - "ko-sleep": "^1.0.3", - "merge-descriptors": "^1.0.1", - "methods": "^1.1.2", - "mm": "^2.5.0", - "mz-modules": "^2.1.0", - "power-assert": "^1.6.1", - "supertest": "^4.0.2", - "urllib": "^2.33.3" - }, - "dependencies": { - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - } - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "egg-multipart": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/egg-multipart/-/egg-multipart-2.10.3.tgz", - "integrity": "sha512-+Ce2RE7YzdUv6G2+u8ke+ZMkyqSfIC3g2lKhSA1zKVetcRJ8GNfxPCoSuEFJMoUePdsJofasnp0EvWYstTpVbw==", - "requires": { - "co-busboy": "^1.4.0", - "egg-path-matching": "^1.0.1", - "humanize-bytes": "^1.0.1", - "moment": "^2.22.2", - "mz": "^2.7.0", - "mz-modules": "^2.1.0", - "stream-wormhole": "^1.1.0", - "uuid": "^3.3.2" - } - }, - "egg-onerror": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/egg-onerror/-/egg-onerror-2.1.0.tgz", - "integrity": "sha512-ujsqFfcXjWZPiYbZAz4bfaCribV6V3DkltYUvwiTV7Qi4g16w6+L9eMHk/eHq8+3Frlis8WT6CcJL0zKUDmLUQ==", - "requires": { - "cookie": "^0.3.1", - "koa-onerror": "^4.0.0", - "mustache": "^2.3.0", - "stack-trace": "^0.0.10" - } - }, - "egg-path-matching": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/egg-path-matching/-/egg-path-matching-1.0.1.tgz", - "integrity": "sha512-XhwWldfhbjKvdDE9kUA6ywxgcxcLFHNaNKP1VZAE9oYTcKGB+piEn99R18zZWvBbk7eXXKHcxT1PQYpqu9GR7A==", - "requires": { - "path-to-regexp": "^1.7.0" - } - }, - "egg-schedule": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/egg-schedule/-/egg-schedule-3.6.5.tgz", - "integrity": "sha512-ARGF7XCEtZcWFk86aFqanFhoT/SClT+Y8/OImh2t4ERh81mESYG8XORjS8w4VMyRsIX64qi1fif+o94O8meK6g==", - "requires": { - "cron-parser": "^2.16.3", - "humanize-ms": "^1.2.1", - "is-type-of": "^1.2.1", - "safe-timers": "^1.1.0", - "utility": "^1.16.3" - } - }, - "egg-scripts": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/egg-scripts/-/egg-scripts-2.13.0.tgz", - "integrity": "sha512-oxFjb2V9G5EVIFWPK3EkQoAHV+eMDbBGi1FnOH32MkGP+IRe/Y/Nnj4jbuxzJzpwsLLYvtNEk3FRpokEOC3V3A==", - "requires": { - "await-event": "^2.1.0", - "common-bin": "^2.8.0", - "debug": "^4.1.0", - "egg-utils": "^2.4.1", - "moment": "^2.23.0", - "mz": "^2.7.0", - "mz-modules": "^2.1.0", - "node-homedir": "^1.1.1", - "runscript": "^1.3.0", - "source-map-support": "^0.5.9", - "zlogger": "^1.1.0" - } - }, - "egg-security": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/egg-security/-/egg-security-2.8.0.tgz", - "integrity": "sha512-Qv+wwHy8C0x2IQzTUBzef+/G3fe5lkrOAKdAilDMbG5UADg+y9wGdJL7Nl3V23xB3lb3yQzJ//7mxngEWeQYJw==", - "requires": { - "csrf": "^3.0.6", - "debug": "^4.1.1", - "delegates": "^1.0.0", - "egg-path-matching": "^1.0.0", - "escape-html": "^1.0.3", - "extend": "^3.0.1", - "ip": "^1.1.5", - "koa-compose": "^4.0.0", - "matcher": "^1.1.1", - "methods": "^1.1.2", - "nanoid": "^2.0.1", - "platform": "^1.3.4", - "statuses": "^1.5.0", - "type-is": "^1.6.15", - "xss": "^1.0.3" - }, - "dependencies": { - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" - } - } - }, - "egg-session": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/egg-session/-/egg-session-3.2.0.tgz", - "integrity": "sha512-YzwqYJoDZLzsMuev+yYPgpeQh2BSNImJtsoJ3W5IcvB0RU1Cmy3I805KMUY+Hsv3jc17AqyCFPUQIBLIO1WEYg==", - "requires": { - "koa-session": "^6.0.0" - } - }, - "egg-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/egg-static/-/egg-static-2.2.0.tgz", - "integrity": "sha512-9Qzllp78ILUfnsnNIQD74xBzsmp5dF/iLMv/qKGPXRK8YefjzCn0UzKDhjSuw7BOH3or3VmEgI4U5zThPnuNUQ==", - "requires": { - "is-type-of": "^1.2.1", - "koa-compose": "^4.1.0", - "koa-range": "^0.3.0", - "koa-static-cache": "^5.1.2", - "mkdirp": "^0.5.1", - "ylru": "^1.2.1" - }, - "dependencies": { - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" - } - } - }, - "egg-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/egg-utils/-/egg-utils-2.4.1.tgz", - "integrity": "sha512-M7KIuzZdlN7AsL2mFvx0jpyEGcKTeQ5j+YT3eAhJOpBvBH9f4by2nKnb30huTRZIeJpjXWPdEzjGck/uj2N0jw==", - "requires": { - "mkdirp": "^0.5.1", - "utility": "^1.13.1" - } - }, - "egg-view": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/egg-view/-/egg-view-2.1.2.tgz", - "integrity": "sha512-C/EpRwjcstv/qaOJtpphNKeCgjd7AbHayqirY65eICG+0EaH4EiFUoh4b1WhIBiYNJHoV/DkkAW78Uiyr+XkEA==", - "requires": { - "mz": "^2.7.0" - } - }, - "egg-watcher": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/egg-watcher/-/egg-watcher-3.1.1.tgz", - "integrity": "sha512-fLo8f2GD9kSrAKeDoXaCckl9MaMMwTEkqU9gVDYWYGPYLsmX79ugA+Wo/2RGQkytsxSCk3bn8YqhPdMzsozgWA==", - "requires": { - "camelcase": "^5.0.0", - "sdk-base": "^3.5.0", - "wt": "^1.2.0" - } - }, - "electron-to-chromium": { - "version": "1.3.570", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz", - "integrity": "sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "empower": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/empower/-/empower-1.3.1.tgz", - "integrity": "sha512-uB6/ViBaawOO/uujFADTK3SqdYlxYNn+N4usK9MRKZ4Hbn/1QSy8k2PezxCA2/+JGbF8vd/eOfghZ90oOSDZCA==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "empower-core": "^1.2.0" - } - }, - "empower-assert": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/empower-assert/-/empower-assert-1.1.0.tgz", - "integrity": "sha512-Ylck0Q6p8y/LpNzYeBccaxAPm2ZyuqBgErgZpO9KT0HuQWF0sJckBKCLmgS1/DEXEiyBi9XtYh3clZm5cAdARw==", - "dev": true, - "requires": { - "estraverse": "^4.2.0" - } - }, - "empower-core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz", - "integrity": "sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ==", - "dev": true, - "requires": { - "call-signature": "0.0.2", - "core-js": "^2.0.0" - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - }, - "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - } - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escallmatch": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/escallmatch/-/escallmatch-1.5.0.tgz", - "integrity": "sha1-UAmdhugJGwkt+N37w/mm+wWgJNA=", - "dev": true, - "requires": { - "call-matcher": "^1.0.0", - "esprima": "^2.0.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - } - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - } - } - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "eslint-config-egg": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/eslint-config-egg/-/eslint-config-egg-8.1.2.tgz", - "integrity": "sha512-7mVlTBsQZNEheNNnTwHqbhho6js6EbgIHGKHy2qfWdd/Yr5mXMOD7buRjvEH/sy83x0b6+LsqhHa1JBeXbKj4A==", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "^3.0.0", - "@typescript-eslint/parser": "^3.0.0", - "babel-eslint": "^8.2.6", - "eslint-plugin-eggache": "^1.0.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jsdoc": "^4.1.1", - "eslint-plugin-jsx-a11y": "^6.1.1", - "eslint-plugin-react": "^7.11.1" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-eggache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-eggache/-/eslint-plugin-eggache-1.0.0.tgz", - "integrity": "sha512-LPTrTvITFDZggiXAIdMPL4bJo0wvXUgJqC3f6UIskJxzHZze2aBTvjWQJ7TgEbkfpk++KWhcOl+lels+qAPKDg==", - "dev": true - }, - "eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - } - } - }, - "eslint-plugin-jsdoc": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-4.8.4.tgz", - "integrity": "sha512-VDP+BI2hWpKNNdsJDSPofSQ9q7jGLgWbDMI0LzOeEcfsTjSS7jQtHDUuVLQ5E+OV2MPyQPk/3lnVcHfStXk5yA==", - "dev": true, - "requires": { - "comment-parser": "^0.5.4", - "jsdoctypeparser": "3.1.0", - "lodash": "^4.17.11" - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz", - "integrity": "sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "aria-query": "^4.2.2", - "array-includes": "^3.1.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^3.5.4", - "axobject-query": "^2.1.2", - "damerau-levenshtein": "^1.0.6", - "emoji-regex": "^9.0.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "language-tags": "^1.0.5" - }, - "dependencies": { - "emoji-regex": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.0.0.tgz", - "integrity": "sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==", - "dev": true - } - } - }, - "eslint-plugin-react": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz", - "integrity": "sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.17.0", - "string.prototype.matchall": "^4.0.2" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espower": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/espower/-/espower-2.1.2.tgz", - "integrity": "sha512-2qa3aEFtcgPB782jTKDPu82hOdw8+zJsWdOn12Tey8XlexHTqsYUIdLC2B7cUECENXly0vZblH1CEZcqttPNjw==", - "dev": true, - "requires": { - "array-find": "^1.0.0", - "escallmatch": "^1.5.0", - "escodegen": "^1.7.0", - "escope": "^3.3.0", - "espower-location-detector": "^1.0.0", - "espurify": "^1.3.0", - "estraverse": "^4.1.0", - "source-map": "^0.5.0", - "type-name": "^2.0.0" - } - }, - "espower-loader": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/espower-loader/-/espower-loader-1.2.2.tgz", - "integrity": "sha1-7bRsPFmga6yOpzppXIblxaC8gto=", - "dev": true, - "requires": { - "convert-source-map": "^1.1.0", - "espower-source": "^2.0.0", - "minimatch": "^3.0.0", - "source-map-support": "^0.4.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - } - } - }, - "espower-location-detector": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/espower-location-detector/-/espower-location-detector-1.0.0.tgz", - "integrity": "sha1-oXt+zFnTDheeK+9z+0E3cEyzMbU=", - "dev": true, - "requires": { - "is-url": "^1.2.1", - "path-is-absolute": "^1.0.0", - "source-map": "^0.5.0", - "xtend": "^4.0.0" - } - }, - "espower-source": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/espower-source/-/espower-source-2.3.0.tgz", - "integrity": "sha512-Wc4kC4zUAEV7Qt31JRPoBUc5jjowHRylml2L2VaDQ1XEbnqQofGWx+gPR03TZAPokAMl5dqyL36h3ITyMXy3iA==", - "dev": true, - "requires": { - "acorn": "^5.0.0", - "acorn-es7-plugin": "^1.0.10", - "convert-source-map": "^1.1.1", - "empower-assert": "^1.0.0", - "escodegen": "^1.10.0", - "espower": "^2.1.1", - "estraverse": "^4.0.0", - "merge-estraverse-visitors": "^1.0.0", - "multi-stage-sourcemap": "^0.2.1", - "path-is-absolute": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "espower-typescript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/espower-typescript/-/espower-typescript-9.0.1.tgz", - "integrity": "sha512-WmEm8Hs0SX06izEdi4Qlu3GPOgshejXXA22OA5i+9oN0yC9pWLxlomyPkNkksAQl+ZV5dOGyTdC4gBAEfwqBww==", - "dev": true, - "requires": { - "espower-source": "^2.3.0", - "minimatch": "^3.0.3", - "source-map-support": "^0.5.9", - "ts-node": "^7.0.1" - } - }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", - "dev": true - } - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, - "espurify": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.8.1.tgz", - "integrity": "sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg==", - "dev": true, - "requires": { - "core-js": "^2.0.0" - } - }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "extend2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/extend2/-/extend2-1.0.0.tgz", - "integrity": "sha1-BCWpibTawqSGoyJX9RQBA3Vqejw=" - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "flushwritable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz", - "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg=" - }, - "follow-redirects": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", - "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "dev": true - }, - "formstream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formstream/-/formstream-1.1.1.tgz", - "integrity": "sha512-yHRxt3qLFnhsKAfhReM4w17jP+U1OlhUjnKPPtonwKbIJO7oBP0MvoxkRUwb8AU9n0MIkYy5X5dK6pQnbj+R2Q==", - "requires": { - "destroy": "^1.0.4", - "mime": "^2.5.2", - "pause-stream": "~0.0.11" - }, - "dependencies": { - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" - } - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" - } - }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "get-ready": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-2.0.1.tgz", - "integrity": "sha1-pIxBh1PjnPTQHzpCDPG3V93MZI8=", - "requires": { - "is-type-of": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "graceful": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/graceful/-/graceful-1.0.2.tgz", - "integrity": "sha512-oRX5662cb/o89rj6R591DS7CGYB9A3vZKDI5ycmO0o6Ub56yM31LySCzIx8N1GHMcMq9J7JqaMLK5U7EIUWB6Q==", - "requires": { - "humanize-ms": "^1.2.1", - "ps-tree": "^1.1.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "graceful-process": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/graceful-process/-/graceful-process-1.2.0.tgz", - "integrity": "sha512-sH5WMY74gxObrKf+5SaqyI1sYv4AF1W5odeW+rA+kHuvKEiqaRgVIUKV2O/CT1NQr6zIhgbtEGOgJORjEHEcdw==", - "requires": { - "is-type-of": "^1.2.0", - "once": "^1.4.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "header-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", - "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.3" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "http-assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", - "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", - "requires": { - "deep-equal": "~1.0.1", - "http-errors": "~1.7.2" - }, - "dependencies": { - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } - } - }, - "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "http-proxy-middleware": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", - "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", - "requires": { - "@types/http-proxy": "^1.17.5", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "humanize-bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/humanize-bytes/-/humanize-bytes-1.0.1.tgz", - "integrity": "sha1-IfV8oxjSEaAG3JeYpGWE+vLZfpw=", - "requires": { - "bytes": "~2.2.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", - "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "inspector-proxy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/inspector-proxy/-/inspector-proxy-1.2.1.tgz", - "integrity": "sha512-/4X2XWYM2huvpQzSMuM3SLykvhpsS7LOnV5wKPNaOdXUBi6Vg1Aor5M4BBLnQ1Q7OdrgbbiQ3Ld8N3OFeW7voQ==", - "dev": true, - "requires": { - "cfork": "^1.6.1", - "debug": "^3.0.1", - "tcp-proxy.js": "^1.0.5", - "urllib": "^2.24.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "intelli-espower-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/intelli-espower-loader/-/intelli-espower-loader-1.0.1.tgz", - "integrity": "sha1-LHsDFGvB1GvyENCgOXxckatMorA=", - "dev": true, - "requires": { - "espower-loader": "^1.0.0" - } - }, - "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-callable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", - "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", - "dev": true - }, - "is-class-hotfix": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", - "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-generator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", - "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", - "dev": true - }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-lower-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", - "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", - "requires": { - "lower-case": "^1.1.0" - } - }, - "is-nan": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", - "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", - "requires": { - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-type-of": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz", - "integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==", - "requires": { - "core-util-is": "^1.0.2", - "is-class-hotfix": "~0.0.6", - "isstream": "~0.1.2" - } - }, - "is-upper-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", - "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", - "requires": { - "upper-case": "^1.1.0" - } - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsdoctypeparser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-3.1.0.tgz", - "integrity": "sha512-JNbkKpDFqbYjg+IU3FNo7qjX7Opy7CwjHywT32zgAcz/d4lX6Umn5jOHVETUdnNNgGrMk0nEx1gvP0F4M0hzlQ==", - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonp-body": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jsonp-body/-/jsonp-body-1.0.0.tgz", - "integrity": "sha1-5hD7b86nnPDMnye6p7Vjd9SwuzY=" - }, - "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "requires": { - "tsscmp": "1.0.6" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "ko-sleep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ko-sleep/-/ko-sleep-1.0.3.tgz", - "integrity": "sha1-KKKgoUhei39BX/SI3uF9JHiKsII=", - "requires": { - "ms": "^2.0.0" - } - }, - "koa": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", - "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", - "requires": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "~3.1.0", - "delegates": "^1.0.0", - "depd": "^1.1.2", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^1.2.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "koa-bodyparser": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", - "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", - "requires": { - "co-body": "^6.0.0", - "copy-to": "^2.0.1" - } - }, - "koa-compose": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", - "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", - "requires": { - "any-promise": "^1.1.0" - } - }, - "koa-connect": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/koa-connect/-/koa-connect-2.1.0.tgz", - "integrity": "sha512-O9pcFafHk0oQsBevlbTBlB9co+2RUQJ4zCzu3qJPmGlGoeEZkne+7gWDkecqDPSbCtED6LmhlQladxs6NjOnMQ==" - }, - "koa-convert": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", - "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", - "requires": { - "co": "^4.6.0", - "koa-compose": "^3.0.0" - } - }, - "koa-is-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", - "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=" - }, - "koa-locales": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/koa-locales/-/koa-locales-1.12.0.tgz", - "integrity": "sha512-lalx0OuvdZ39JppTVqHnYKIgJJbByon9xpt5KSKFOL6/VQS+XBMklMX83+fgkCXzsNacynWaN75ihWP2EGsWIQ==", - "requires": { - "debug": "^2.6.0", - "humanize-ms": "^1.2.0", - "ini": "^1.3.4", - "object-assign": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "koa-onerror": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-onerror/-/koa-onerror-4.1.0.tgz", - "integrity": "sha512-UDvOkkXiyVtlhRIvo9wbqKG/pTiiVE5x2uIFpG5e6OmBawxBSURG/PeFa6e6UZjjxinXde3BmPWVSIVePMG6TA==", - "requires": { - "escape-html": "^1.0.3", - "stream-wormhole": "^1.1.0" - } - }, - "koa-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/koa-override/-/koa-override-3.0.0.tgz", - "integrity": "sha512-w2rWCfapbQUZ8TrRBarj6iwryCTooEcdw9lr1hYC1q4FnaCZcAOhpjB1VpqtbODALVMgY3JGlzLSeYRXc5Ky0Q==", - "requires": { - "methods": "^1.1.2" - } - }, - "koa-range": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", - "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", - "requires": { - "stream-slice": "^0.1.2" - } - }, - "koa-session": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/koa-session/-/koa-session-6.0.0.tgz", - "integrity": "sha512-mEj2ximzLqoypk0Q+/JLu0j7fuMk/fL+yiBM0RKmxBqdImKxq3hfnpHLwpMhwya05z/W8i7vawpFl+lsYTZbAg==", - "requires": { - "crc": "^3.4.4", - "debug": "^3.1.0", - "is-type-of": "^1.0.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "koa-static-cache": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/koa-static-cache/-/koa-static-cache-5.1.4.tgz", - "integrity": "sha512-abVWOHY6z6qSTvNtapWMAnvHS9SUiUCaQQQubClSAT9ybQPsZ6ioKcRarnownS4fMD0sXQgQ5ey8CYEuwoa1Yg==", - "requires": { - "compressible": "^2.0.6", - "debug": "^3.1.0", - "fs-readdir-recursive": "^1.0.0", - "mime-types": "^2.1.8", - "mz": "^2.7.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "language-subtag-registry": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", - "integrity": "sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "requires": { - "invert-kv": "^2.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" - }, - "lower-case-first": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", - "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", - "requires": { - "lower-case": "^1.1.2" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "matcher": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", - "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", - "requires": { - "escape-string-regexp": "^1.0.4" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-estraverse-visitors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/merge-estraverse-visitors/-/merge-estraverse-visitors-1.0.0.tgz", - "integrity": "sha1-65aDOLXe1c7tgs7AMH3sui2OqZQ=", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "requires": { - "minipass": "^2.9.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mm": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mm/-/mm-2.5.0.tgz", - "integrity": "sha512-ilm+lGEBNm7Cw45um9ax0tbApiNwQV3PY6Yk1ol+wtA8c98hHuJqTgmdKB6rYQJTUC2QrhBfoWwN+/766ZlrYA==", - "dev": true, - "requires": { - "is-type-of": "^1.0.0", - "ko-sleep": "^1.0.2", - "muk-prop": "^1.0.0", - "thenify": "^3.2.1" - } - }, - "moment": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", - "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" - }, - "moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "muk-prop": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/muk-prop/-/muk-prop-1.2.1.tgz", - "integrity": "sha512-NdkOVav3GoIkBZqMUneU435HW0a90zitpuO1erPRhOQdPtl65dXD3G9/1k46G6/0ZMau4CJFFUHkMKVsyNZT+w==", - "dev": true - }, - "multi-stage-sourcemap": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", - "integrity": "sha1-sJ/IWG6qF/gdV1xK0C4Pej9rEQU=", - "dev": true, - "requires": { - "source-map": "^0.1.34" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" - } - }, - "mustache": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", - "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "mz-modules": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mz-modules/-/mz-modules-2.1.0.tgz", - "integrity": "sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==", - "requires": { - "glob": "^7.1.2", - "ko-sleep": "^1.0.3", - "mkdirp": "^0.5.1", - "pump": "^3.0.0", - "rimraf": "^2.6.1" - } - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "ndir": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/ndir/-/ndir-0.1.5.tgz", - "integrity": "sha1-EgiR12l7u+ghTP7/CWAgYNNFRVg=" - }, - "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-addon-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz", - "integrity": "sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==" - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "node-homedir": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-homedir/-/node-homedir-1.1.1.tgz", - "integrity": "sha512-Xsmf94D/DdeDISAECUaxXVxhh+kHdbOQE4CnP4igo3HXL3BSmmUpD5M7orH434EZZwBTFF2xe5SgsQr/wOBuNw==" - }, - "node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "nounou": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/nounou/-/nounou-1.2.1.tgz", - "integrity": "sha1-qQR++kQF4m7H52iHW9JYD8Sl8I8=" - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "nunjucks": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", - "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", - "dev": true, - "requires": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "chokidar": "^3.3.0", - "commander": "^5.1.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "optional": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "optional": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "nyc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz", - "integrity": "sha512-P+FwIuro2aFG6B0Esd9ZDWUd51uZrAEoGutqZxzrVmYl3qSfkLgcQpBPBjtDFsUQLFY1dvTQJPOyeqr8S9GF8w==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "arrify": "^1.0.1", - "caching-transform": "^3.0.1", - "convert-source-map": "^1.6.0", - "find-cache-dir": "^2.0.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.3", - "istanbul-lib-hook": "^2.0.3", - "istanbul-lib-instrument": "^3.1.0", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.2", - "istanbul-reports": "^2.1.1", - "make-dir": "^1.3.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.1.0", - "uuid": "^3.3.2", - "yargs": "^12.0.5", - "yargs-parser": "^11.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "append-transform": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "default-require-extensions": "^2.0.0" - } - }, - "archy": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "arrify": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "async": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "caching-transform": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "hasha": "^3.0.0", - "make-dir": "^1.3.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.3.0" - } - }, - "camelcase": { - "version": "5.0.0", - "bundled": true, - "dev": true - }, - "cliui": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "commander": { - "version": "2.17.1", - "bundled": true, - "dev": true, - "optional": true - }, - "commondir": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cross-spawn": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "default-require-extensions": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "strip-bom": "^3.0.0" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "bundled": true, - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es6-error": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "execa": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "bundled": true, - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "find-cache-dir": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "foreground-child": { - "version": "1.5.6", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.15", - "bundled": true, - "dev": true - }, - "handlebars": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "async": "^2.5.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "hasha": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "is-stream": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "bundled": true, - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "invert-kv": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "istanbul-lib-hook": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "append-transform": "^1.0.0" - } - }, - "istanbul-lib-report": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "supports-color": "^6.0.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "bundled": true, - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "rimraf": "^2.6.2", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "istanbul-reports": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "handlebars": "^4.1.0" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "lcid": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "bundled": true, - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "bundled": true, - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "bundled": true, - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "bundled": true, - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^2.0.0" - } - }, - "merge-source-map": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "mimic-fn": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.10", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "bundled": true, - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optimist": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "p-is-promise": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "p-limit": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "package-hash": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "bundled": true, - "dev": true - }, - "path-type": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "read-pkg": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "release-zalgo": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "resolve": { - "version": "1.10.0", - "bundled": true, - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "spawn-wrap": { - "version": "1.4.2", - "bundled": true, - "dev": true, - "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "spdx-correct": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.3", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "test-exclude": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "arrify": "^1.0.1", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^1.0.1" - } - }, - "uglify-js": { - "version": "3.4.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "uuid": { - "version": "3.3.2", - "bundled": true, - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "bundled": true, - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "write-file-atomic": { - "version": "2.4.2", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "y18n": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "yargs": { - "version": "12.0.5", - "bundled": true, - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "bundled": true, - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - } - }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "os-name": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", - "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", - "requires": { - "osx-release": "^1.0.0", - "win-release": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "osx-release": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", - "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", - "requires": { - "minimist": "^1.1.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "pac-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", - "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", - "requires": { - "agent-base": "^4.2.0", - "debug": "^4.1.1", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "requires": { - "no-case": "^2.2.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "pascal-case": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", - "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=", - "requires": { - "camel-case": "^3.0.0", - "upper-case-first": "^1.1.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", - "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=", - "requires": { - "no-case": "^2.2.0" - } - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "^3.0.0" - } - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "~2.3" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "optional": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } - } - }, - "platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "power-assert": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.6.1.tgz", - "integrity": "sha512-VWkkZV6Y+W8qLX/PtJu2Ur2jDPIs0a5vbP0TpKeybNcIXmT4vcKoVkyTp5lnQvTpY/DxacAZ4RZisHRHLJcAZQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "empower": "^1.3.1", - "power-assert-formatter": "^1.4.1", - "universal-deep-strict-equal": "^1.2.1", - "xtend": "^4.0.0" - } - }, - "power-assert-context-formatter": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz", - "integrity": "sha512-HLNEW8Bin+BFCpk/zbyKwkEu9W8/zThIStxGo7weYcFkKgMuGCHUJhvJeBGXDZf0Qm2xis4pbnnciGZiX0EpSg==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "power-assert-context-traversal": "^1.2.0" - } - }, - "power-assert-context-reducer-ast": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz", - "integrity": "sha512-EgOxmZ/Lb7tw4EwSKX7ZnfC0P/qRZFEG28dx/690qvhmOJ6hgThYFm5TUWANDLK5NiNKlPBi5WekVGd2+5wPrw==", - "dev": true, - "requires": { - "acorn": "^5.0.0", - "acorn-es7-plugin": "^1.0.12", - "core-js": "^2.0.0", - "espurify": "^1.6.0", - "estraverse": "^4.2.0" - } - }, - "power-assert-context-traversal": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz", - "integrity": "sha512-NFoHU6g2umNajiP2l4qb0BRWD773Aw9uWdWYH9EQsVwIZnog5bd2YYLFCVvaxWpwNzWeEfZIon2xtyc63026pQ==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "estraverse": "^4.1.0" - } - }, - "power-assert-formatter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", - "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "power-assert-context-formatter": "^1.0.7", - "power-assert-context-reducer-ast": "^1.0.7", - "power-assert-renderer-assertion": "^1.0.7", - "power-assert-renderer-comparison": "^1.0.7", - "power-assert-renderer-diagram": "^1.0.7", - "power-assert-renderer-file": "^1.0.7" - } - }, - "power-assert-renderer-assertion": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz", - "integrity": "sha512-3F7Q1ZLmV2ZCQv7aV7NJLNK9G7QsostrhOU7U0RhEQS/0vhEqrRg2jEJl1jtUL4ZyL2dXUlaaqrmPv5r9kRvIg==", - "dev": true, - "requires": { - "power-assert-renderer-base": "^1.1.1", - "power-assert-util-string-width": "^1.2.0" - } - }, - "power-assert-renderer-base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", - "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=", - "dev": true - }, - "power-assert-renderer-comparison": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz", - "integrity": "sha512-7c3RKPDBKK4E3JqdPtYRE9cM8AyX4LC4yfTvvTYyx8zSqmT5kJnXwzR0yWQLOavACllZfwrAGQzFiXPc5sWa+g==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "diff-match-patch": "^1.0.0", - "power-assert-renderer-base": "^1.1.1", - "stringifier": "^1.3.0", - "type-name": "^2.0.1" - } - }, - "power-assert-renderer-diagram": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz", - "integrity": "sha512-JZ6PC+DJPQqfU6dwSmpcoD7gNnb/5U77bU5KgNwPPa+i1Pxiz6UuDeM3EUBlhZ1HvH9tMjI60anqVyi5l2oNdg==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "power-assert-renderer-base": "^1.1.1", - "power-assert-util-string-width": "^1.2.0", - "stringifier": "^1.3.0" - } - }, - "power-assert-renderer-file": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz", - "integrity": "sha512-/oaVrRbeOtGoyyd7e4IdLP/jIIUFJdqJtsYzP9/88R39CMnfF/S/rUc8ZQalENfUfQ/wQHu+XZYRMaCEZmEesg==", - "dev": true, - "requires": { - "power-assert-renderer-base": "^1.1.1" - } - }, - "power-assert-util-string-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz", - "integrity": "sha512-lX90G0igAW0iyORTILZ/QjZWsa1MZ6VVY3L0K86e2eKun3S4LKPH4xZIl8fdeMYLfOjkaszbNSzf1uugLeAm2A==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "printable": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/printable/-/printable-0.0.3.tgz", - "integrity": "sha1-9lPLObIUt4BJrhQD4vsF10ptUOA=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, - "proxy-agent": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", - "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", - "requires": { - "agent-base": "^4.2.0", - "debug": "4", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^3.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "requires": { - "event-stream": "=3.3.4" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ready-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ready-callback/-/ready-callback-2.1.0.tgz", - "integrity": "sha512-pyoQjeks8RvkzHbdDgSS1Faw+3xByvnWxccsIiBLOtFX+sp6pkpdSuIZJzfIgpzpOSOdVFVxrFEL+VcNL3+bBQ==", - "requires": { - "debug": "^2.6.0", - "get-ready": "^2.0.0", - "once": "^1.4.0", - "uuid": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-files": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/resolve-files/-/resolve-files-1.0.2.tgz", - "integrity": "sha1-WnIRi5L6c5T/LYYF0fw3Ppw+kO8=", - "dev": true, - "requires": { - "crequire": "^1.8.0", - "debug": "^2.6.3" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "runscript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/runscript/-/runscript-1.5.0.tgz", - "integrity": "sha512-o9MaYVXr9ZNwOj+KO4jWWkC8qvTvsu6RfZLgF2h1UZjD2cenwEjoMMnCcILXZ0nu/RrSShc0OYgm1xl8iXEjJA==", - "requires": { - "debug": "^2.6.8", - "is-type-of": "^1.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, - "safe-timers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-timers/-/safe-timers-1.1.0.tgz", - "integrity": "sha1-xYroMl2407BnMi8KTvOgytZ6rYM=" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "scmp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", - "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" - }, - "sdk-base": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-3.6.0.tgz", - "integrity": "sha512-jxHUIrRLlAoRFRwiXKhOGjd6BeFWO/jz7tv+E7lbMSef6F9jzFN2Sv3hLW58oDDKscKaBGG6vQdkbXn7isE7fw==", - "requires": { - "await-event": "^2.1.0", - "await-first": "^1.0.0", - "co": "^4.6.0", - "is-type-of": "^1.2.1" - } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" - }, - "sendmessage": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sendmessage/-/sendmessage-1.1.0.tgz", - "integrity": "sha1-EKJFzuLVDHWfHgmiNHe5FJbQnjU=" - }, - "sentence-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", - "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=", - "requires": { - "no-case": "^2.2.0", - "upper-case-first": "^1.1.2" - } - }, - "sequin": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz", - "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE=" - }, - "serialize-json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/serialize-json/-/serialize-json-1.0.3.tgz", - "integrity": "sha512-TJvXOXSUEH4Lh2FNy1mYzNkUyBG7Ti5fRKGAbcpaDX3mLq23aT/5unC+cIFc5JTDi4/BHTaYLhynrboCCYrFaQ==", - "requires": { - "debug": "^3.2.6", - "is-type-of": "^1.2.1", - "utility": "^1.15.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "should-send-same-site-none": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/should-send-same-site-none/-/should-send-same-site-none-2.0.5.tgz", - "integrity": "sha512-7dig49H7sKnv1v/GPoFQChGgJdEX9s2oy9TQBSD5RbUx7M9CCRjHMaFP06v+DZQNM0K+o8dBhvBAd4eEKirqbQ==" - }, - "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", - "dev": true, - "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" - }, - "snake-case": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", - "requires": { - "no-case": "^2.2.0" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "requires": { - "through2": "^2.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "requires": { - "duplexer": "~0.1.1" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "stream-slice": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", - "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=" - }, - "stream-wormhole": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", - "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==" - }, - "streamifier": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", - "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=" - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.matchall": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", - "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2" - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "stringifier": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.4.0.tgz", - "integrity": "sha512-cNsMOqqrcbLcHTXEVmkw9y0fwDwkdgtZwlfyolzpQDoAE1xdNGhQhxBUfiDvvZIKl1hnUEgMv66nHwtMz3OjPw==", - "dev": true, - "requires": { - "core-js": "^2.0.0", - "traverse": "^0.6.6", - "type-name": "^2.0.1" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "swap-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", - "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", - "requires": { - "lower-case": "^1.1.1", - "upper-case": "^1.1.1" - } - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "tcp-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tcp-base/-/tcp-base-3.1.0.tgz", - "integrity": "sha512-5iTlUaVmeZBzyq9cSVjB4mzKtvBP2wpkbVZoMdRhFwq35DYUBAfeTgAD31NYJSba3HVxetjuqKlAkUUHlWoShw==", - "requires": { - "is-type-of": "^1.0.0", - "sdk-base": "^3.1.1" - } - }, - "tcp-proxy.js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tcp-proxy.js/-/tcp-proxy.js-1.3.0.tgz", - "integrity": "sha512-bR33J6mcAhjueCH7emiXNxvIg/fitNma6zXs195uyteQizD+omAUZFTxRVNpW2EUSV3I+IbHoKJiHViq/ugR4A==", - "dev": true, - "requires": { - "debug": "^3.0.1", - "through2": "^2.0.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "temp": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.1.tgz", - "integrity": "sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA==", - "requires": { - "rimraf": "~2.6.2" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - }, - "dependencies": { - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "throat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" - }, - "title-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", - "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.0.3" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "dependencies": { - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - } - } - }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "type-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", - "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=", - "dev": true - }, - "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", - "dev": true - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" - }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" - }, - "unescape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", - "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", - "requires": { - "extend-shallow": "^2.0.1" - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "universal-deep-strict-equal": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", - "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", - "dev": true, - "requires": { - "array-filter": "^1.0.0", - "indexof": "0.0.1", - "object-keys": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - } - } - }, - "unzip-stream": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.0.tgz", - "integrity": "sha512-NG1h/MdGIX3HzyqMjyj1laBCmlPYhcO4xEy7gEqqzGiSLw7XqDQCnY4nYSn5XSaH8mQ6TFkaujrO8d/PIZN85A==", - "requires": { - "binary": "^0.3.0", - "mkdirp": "^0.5.1" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" - }, - "upper-case-first": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", - "requires": { - "upper-case": "^1.1.1" - } - }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urijs": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz", - "integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==" - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "urllib": { - "version": "2.36.1", - "resolved": "https://registry.npmjs.org/urllib/-/urllib-2.36.1.tgz", - "integrity": "sha512-g0Gh7bH5AwfPUzFetxPtJwumGHE6D7KQn0K68MwcJXPgO2K0AliwEIxLAwGMF+TpY75DYAsvz1h9ekagYoq33w==", - "requires": { - "any-promise": "^1.3.0", - "content-type": "^1.0.2", - "debug": "^2.6.9", - "default-user-agent": "^1.0.0", - "digest-header": "^0.0.1", - "ee-first": "~1.1.1", - "formstream": "^1.1.0", - "humanize-ms": "^1.2.0", - "iconv-lite": "^0.4.15", - "ip": "^1.1.5", - "proxy-agent": "^3.1.0", - "pump": "^3.0.0", - "qs": "^6.4.0", - "statuses": "^1.3.1", - "utility": "^1.16.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utility": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/utility/-/utility-1.16.3.tgz", - "integrity": "sha512-kYghm8fknkPkUd9ncODj/b2Zojc23gnRC29QmpmL3BBsSX6W++RNRTQ1tB7l0UA7d4SisIjUyvRfVET3lBwurw==", - "requires": { - "copy-to": "^2.0.1", - "escape-html": "^1.0.3", - "mkdirp": "^0.5.1", - "mz": "^2.7.0", - "unescape": "^1.0.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "win-release": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "requires": { - "semver": "^5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" - } - }, - "wt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/wt/-/wt-1.2.0.tgz", - "integrity": "sha512-nJttxFyxnIvWBWYcy7Px4XkXbRoEe77by66d0FDof266Mv00vVBNcUGa00rL1+0DdsXG75LG1rwBnBfUa2bNLA==", - "requires": { - "debug": "^2.2.0", - "ndir": "^0.1.5", - "sdk-base": "^2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "get-ready": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz", - "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "sdk-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz", - "integrity": "sha1-ukAonovfJy7RHdnql+r5jgNtJMY=", - "requires": { - "get-ready": "~1.0.0" - } - } - } - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" - }, - "xss": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz", - "integrity": "sha512-3MgPdaXV8rfQ/pNn16Eio6VXYPTkqwa0vc7GkiymmY/DqR1SE/7VPAAVZz1GJsJFrllMYO3RHfEaiUGjab6TNw==", - "requires": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "ypkgfiles": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ypkgfiles/-/ypkgfiles-1.6.0.tgz", - "integrity": "sha512-q8vgLzZy5CO1LUBFPWOkYpqCkAEaWdXTAAIfLREB72vxnXd+vUZvU3Qxb694TyPc56zA3t8fZIcBNj8fWtSR2A==", - "dev": true, - "requires": { - "debug": "^2.6.1", - "glob": "^7.1.1", - "is-type-of": "^1.0.0", - "resolve-files": "^1.0.0", - "yargs": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - } - } - }, - "zlogger": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zlogger/-/zlogger-1.1.0.tgz", - "integrity": "sha1-vA1KGlDYi04CdjYGDHojaCdUdE4=", - "requires": { - "pumpify": "^1.3.5", - "split2": "^2.1.0", - "through2": "^2.0.1" - } - } - } -} diff --git a/gm-server/package.json b/gm-server/package.json index e392975cc..800762138 100644 --- a/gm-server/package.json +++ b/gm-server/package.json @@ -40,12 +40,14 @@ "exceljs": "^4.3.0", "form-data": "^4.0.0", "formstream": "^1.1.1", + "koa": "^2.13.4", "moment": "^2.29.0", "node-xlsx": "^0.23.0", "pump": "^3.0.0", "reflect-metadata": "^0.1.13", "stream-wormhole": "^1.1.0", "temp": "^0.9.1", + "tsconfig-paths": "^3.9.0", "underscore": "^1.12.0", "unzip-stream": "^0.3.0" }, diff --git a/gm-server/tsconfig.json b/gm-server/tsconfig.json index 831035c0f..20254640a 100644 --- a/gm-server/tsconfig.json +++ b/gm-server/tsconfig.json @@ -24,10 +24,10 @@ "importHelpers": true, "baseUrl": ".", "paths": { - "@domain/*": ["app/domain/*"], - "@db/*": ["app/db/*"], - "@consts": ["app/consts"], - "@pubUtils/*": ["app/pubUtils/*"] + "@domain/*": ["../shared/domain/*"], + "@db/*": ["../shared/db/*"], + "@consts": ["../shared/consts"], + "@pubUtils/*": ["../shared/pubUtils/*"] }, }, "exclude": [ diff --git a/gm-server/typings/app/service/index.d.ts b/gm-server/typings/app/service/index.d.ts index 93acc9337..1c96a53bf 100644 --- a/gm-server/typings/app/service/index.d.ts +++ b/gm-server/typings/app/service/index.d.ts @@ -12,8 +12,8 @@ import ExportGmUser from '../../../app/service/GmUser'; import ExportLog from '../../../app/service/Log'; import ExportMail from '../../../app/service/Mail'; import ExportTest from '../../../app/service/Test'; -import ExportUtils from '../../../app/service/Utils'; import ExportUsers from '../../../app/service/users'; +import ExportUtils from '../../../app/service/Utils'; declare module 'egg' { interface IService { @@ -23,7 +23,7 @@ declare module 'egg' { log: AutoInstanceType; mail: AutoInstanceType; test: AutoInstanceType; - utils: AutoInstanceType; users: AutoInstanceType; + utils: AutoInstanceType; } } diff --git a/package-lock.json b/package-lock.json index f5b94d554..7de106003 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,773 +1,1864 @@ { "name": "zyz_server", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, - "dependencies": { - "@typegoose/typegoose": { - "version": "7.3.5", - "resolved": "https://registry.npm.taobao.org/@typegoose/typegoose/download/@typegoose/typegoose-7.3.5.tgz", - "integrity": "sha1-94517zpL5R8DkYh55qjPDR/PecA=", - "requires": { - "lodash": "^4.17.19", - "loglevel": "^1.6.8", + "packages": { + "": { + "name": "zyz_server", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@typegoose/typegoose": "^7.3.5", + "@types/mongoose": "^5.7.36", + "@types/request-promise": "^4.1.47", + "bcrypt": "^5.0.0", + "chinese-random-name": "^1.0.0", + "crc": "^3.8.0", + "csprng": "^0.1.2", + "koa-is-json": "^1.0.0", + "lodash": "^4.17.20", + "moment": "^2.27.0", + "mongoose": "5.10.18", + "mongoose-lean-getters": "^0.1.2", + "mongoose-lean-virtuals": "^0.7.6", + "mongoose-transactions": "^1.1.4", + "redis": "^3.1.2", + "request": "^2.88.2", + "request-promise": "^4.2.6", + "underscore": "^1.12.0" + }, + "devDependencies": { + "@types/redis": "^2.8.31" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", + "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@typegoose/typegoose": { + "version": "7.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typegoose/typegoose/-/typegoose-7.6.3.tgz", + "integrity": "sha512-u12nUEmpMa0e+K8UuzAZvSnWZ7JZGo0yMs7HR4mG47gJJhVe/PIAzfXVPV+CJQBZrMSPyaEZ6HRKjmDxnjEgFg==", + "dependencies": { + "lodash": "^4.17.20", + "loglevel": "^1.7.0", "reflect-metadata": "^0.1.13", "semver": "^7.3.2", - "tslib": "^2.0.0" + "tslib": "^2.0.1" }, + "engines": { + "node": ">=10.15.0" + }, + "peerDependencies": { + "@types/mongoose": "~5.10.2", + "mongoose": "5.10.0 - 5.10.18" + } + }, + "node_modules/@types/bluebird": { + "version": "3.5.42", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/bluebird/-/bluebird-3.5.42.tgz", + "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==" + }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" + }, + "node_modules/@types/mongodb": { + "version": "4.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/mongodb/-/mongodb-4.0.7.tgz", + "integrity": "sha512-lPUYPpzA43baXqnd36cZ9xxorprybxXDzteVKCPAdp14ppHtFJHnXYvNpmBvtMUTb5fKXVv6sVbzo1LHkWhJlw==", + "deprecated": "mongodb provides its own types. @types/mongodb is no longer needed.", "dependencies": { - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.2.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.2.tgz", - "integrity": "sha1-YElisFK4HtB4aq6EOJ/7pw/9OTg=" - } + "mongodb": "*" } }, - "@types/bluebird": { - "version": "3.5.33", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.33.tgz", - "integrity": "sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==" - }, - "@types/bson": { - "version": "4.0.2", - "resolved": "https://registry.npm.taobao.org/@types/bson/download/@types/bson-4.0.2.tgz", - "integrity": "sha1-esy4WUL8ObvbdRXU3kN8BPaYEV8=", - "requires": { - "@types/node": "*" - } - }, - "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" - }, - "@types/mongodb": { - "version": "3.5.27", - "resolved": "https://registry.npm.taobao.org/@types/mongodb/download/@types/mongodb-3.5.27.tgz?cache=0&sync_timestamp=1599138259359&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fmongodb%2Fdownload%2F%40types%2Fmongodb-3.5.27.tgz", - "integrity": "sha1-FYp6Q84l7zWSrIpi5iqzi+v2YfI=", - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/mongoose": { - "version": "5.7.36", - "resolved": "https://registry.npm.taobao.org/@types/mongoose/download/@types/mongoose-5.7.36.tgz", - "integrity": "sha1-La4oxjBBxq+6ioPqApafRjs/ECE=", - "requires": { + "node_modules/@types/mongoose": { + "version": "5.10.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/mongoose/-/mongoose-5.10.5.tgz", + "integrity": "sha512-37QMIA954T3n+HSksSNLlxZsqF8fMJu5S4dyPBod6gRxGtsXlQ9jUtL8BE8Seimv99u79eLXI3bggoCnSQ/fxQ==", + "dependencies": { "@types/mongodb": "*", "@types/node": "*" } }, - "@types/node": { - "version": "14.10.0", - "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.10.0.tgz?cache=0&sync_timestamp=1599757029267&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.10.0.tgz", - "integrity": "sha1-FYFd/4LI3DCCf2sShvhlkClFCVo=" + "node_modules/@types/node": { + "version": "25.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "dependencies": { + "undici-types": "~7.18.0" + } }, - "@types/redis": { + "node_modules/@types/redis": { "version": "2.8.32", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.32.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/redis/-/redis-2.8.32.tgz", "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*" } }, - "@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", - "requires": { + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", + "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", - "form-data": "^2.5.0" + "form-data": "^2.5.5" } }, - "@types/request-promise": { - "version": "4.1.47", - "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz", - "integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==", - "requires": { + "node_modules/@types/request-promise": { + "version": "4.1.51", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request-promise/-/request-promise-4.1.51.tgz", + "integrity": "sha512-qVcP9Fuzh9oaAh8oPxiSoWMFGnWKkJDknnij66vi09Yiy62bsSDqtd+fG5kIM9wLLgZsRP3Y6acqj9O/v2ZtRw==", + "dependencies": { "@types/bluebird": "*", "@types/request": "*" } }, - "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==" + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" }, - "abbrev": { + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "13.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==" }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" } }, - "array.prototype.flat": { + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "requires": { + "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { "safer-buffer": "~2.1.0" } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", - "requires": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" } }, - "bcrypt-pbkdf": { + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" + }, + "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { "tweetnacl": "^0.14.3" } }, - "bl": { + "node_modules/bl": { "version": "2.2.1", - "resolved": "https://registry.npm.taobao.org/bl/download/bl-2.2.1.tgz?cache=0&sync_timestamp=1599194088618&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbl%2Fdownload%2Fbl-2.2.1.tgz", - "integrity": "sha1-jBGntzBlXF1WiYzchxIk9A/ZAdU=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dependencies": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" } }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz", - "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=" + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bluebird": { + "version": "3.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "bson": { - "version": "1.1.5", - "resolved": "https://registry.npm.taobao.org/bson/download/bson-1.1.5.tgz?cache=0&sync_timestamp=1597069108497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbson%2Fdownload%2Fbson-1.1.5.tgz", - "integrity": "sha1-Kqrpj832dQwISLDLod3sPHMGCjQ=" + "node_modules/bson": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/bson/-/bson-7.2.0.tgz", + "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==", + "engines": { + "node": ">=20.19.0" + } }, - "buffer": { + "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } }, - "chinese-random-name": { + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chinese-random-name": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chinese-random-name/-/chinese-random-name-1.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/chinese-random-name/-/chinese-random-name-1.0.0.tgz", "integrity": "sha512-0ZJ0LhV4O9vqas4IgQB7IDqqSovpSoHlvZo3FWXShKBfs6BS7l4uRQVqin54D4KNrG81G7cZ7p6YIpn93fo2wQ==", - "requires": { + "dependencies": { "flatten": "^1.0.2", "random-to": "0.0.2" } }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" } }, - "concat-map": { + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "console-control-strings": { + "node_modules/console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "resolved": "https://mirrors.cloud.tencent.com/npm/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, - "crc": { + "node_modules/crc": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "requires": { + "dependencies": { "buffer": "^5.1.0" } }, - "csprng": { + "node_modules/csprng": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz", - "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=", - "requires": { - "sequin": "*" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "2.0.0" - }, + "resolved": "https://mirrors.cloud.tencent.com/npm/csprng/-/csprng-0.1.2.tgz", + "integrity": "sha512-D3WAbvvgUVIqSxUfdvLeGjuotsB32bvfVPd+AaaTWMtyUeC9zgCnw5xs94no89yFLVsafvY9dMZEhTwsY/ZecA==", "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "sequin": "*" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "delayed-stream": { + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "resolved": "https://mirrors.cloud.tencent.com/npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } }, - "delegates": { + "node_modules/delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "resolved": "https://mirrors.cloud.tencent.com/npm/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, - "denque": { - "version": "1.4.1", - "resolved": "https://registry.npm.taobao.org/denque/download/denque-1.4.1.tgz", - "integrity": "sha1-Z0T/dkHBSMP4ppwwflEjXB9KN88=" + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "engines": { + "node": ">=8" + } }, - "ecc-jsbn": { + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" } }, - "extend": { + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "extsprintf": { + "node_modules/extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] }, - "fast-deep-equal": { + "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "flatten": { + "node_modules/flatten": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash." }, - "forever-agent": { + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forever-agent": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "resolved": "https://mirrors.cloud.tencent.com/npm/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "requires": { + "node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" } }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "fs.realpath": { + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" } }, - "get-intrinsic": { + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", - "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "resolved": "https://mirrors.cloud.tencent.com/npm/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "getpass": { + "node_modules/getpass": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { "assert-plus": "^1.0.0" } }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "har-validator": { + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { + "deprecated": "this library is no longer supported", + "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "http-signature": { + "node_modules/has-proto": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "ieee754": { + "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "resolved": "https://mirrors.cloud.tencent.com/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", - "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" + "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "is-date-object": { + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-regex": { + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-finalizationregistry": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" + "resolved": "https://mirrors.cloud.tencent.com/npm/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "requires": { - "has-symbols": "^1.0.1" + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "isstream": { + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isstream": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "resolved": "https://mirrors.cloud.tencent.com/npm/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, - "jsbn": { + "node_modules/jsbn": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "resolved": "https://mirrors.cloud.tencent.com/npm/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "json-stringify-safe": { + "node_modules/json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "resolved": "https://mirrors.cloud.tencent.com/npm/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" } }, - "kareem": { + "node_modules/kareem": { "version": "2.3.1", - "resolved": "https://registry.npm.taobao.org/kareem/download/kareem-2.3.1.tgz", - "integrity": "sha1-3vEtnJQQF/q/sA+HOvlenJnhvoc=" + "resolved": "https://mirrors.cloud.tencent.com/npm/kareem/-/kareem-2.3.1.tgz", + "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" }, - "koa-is-json": { + "node_modules/koa-is-json": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-is-json/-/koa-is-json-1.0.0.tgz", "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336097104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz", - "integrity": "sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=" + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://mirrors.cloud.tencent.com/npm/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" }, - "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.7.0.tgz?cache=0&sync_timestamp=1598447642950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.7.0.tgz", - "integrity": "sha1-coFmhVp0DVnTjbAc9G8ELKoEG7A=" + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } }, - "memory-pager": { + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memory-pager": { "version": "1.5.0", - "resolved": "https://registry.npm.taobao.org/memory-pager/download/memory-pager-1.5.0.tgz", - "integrity": "sha1-2HUWVdItOEaCdByXLyw9bfo+ZrU=", - "optional": true + "resolved": "https://mirrors.cloud.tencent.com/npm/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, - "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" - }, - "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", - "requires": { - "mime-db": "1.46.0" + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" } }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "requires": { - "minipass": "^2.9.0" + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "moment": { - "version": "2.27.0", - "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.27.0.tgz?cache=0&sync_timestamp=1592516084857&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.27.0.tgz", - "integrity": "sha1-i/9OPiaiNiIN/j423nVrbrqgEF0=" - }, - "mongodb": { - "version": "3.6.1", - "resolved": "https://registry.npm.taobao.org/mongodb/download/mongodb-3.6.1.tgz", - "integrity": "sha1-LFzCqBRWuhg+jEMtgOeHMsxy2r0=", - "requires": { - "bl": "^2.2.0", - "bson": "^1.1.4", - "denque": "^1.4.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, - "mongoose": { - "version": "5.10.4", - "resolved": "https://registry.npm.taobao.org/mongoose/download/mongoose-5.10.4.tgz", - "integrity": "sha1-CVGSYZmCQ95H7XLtKNyMOtv2qRA=", - "requires": { + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "7.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb/-/mongodb-7.1.0.tgz", + "integrity": "sha512-kMfnKunbolQYwCIyrkxNJFB4Ypy91pYqua5NargS/f8ODNSJxT03ZU3n1JqL4mCzbSih8tvmMEMLpKTT7x5gCg==", + "dependencies": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^7.1.1", + "mongodb-connection-string-url": "^7.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.806.0", + "@mongodb-js/zstd": "^7.0.0", + "gcp-metadata": "^7.0.1", + "kerberos": "^7.0.0", + "mongodb-client-encryption": ">=7.0.0 <7.1.0", + "snappy": "^7.3.2", + "socks": "^2.8.6" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "7.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz", + "integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==", + "dependencies": { + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" + }, + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/mongoose": { + "version": "5.10.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose/-/mongoose-5.10.18.tgz", + "integrity": "sha512-vaLUzBpUxqacoCqP/xXWMg/uVwCDrlc8LvYjDXCf8hdApvX/CXa0HLa7v2ieFaVd5Fgv3W2QXODLoC4Z/abbNw==", + "dependencies": { "bson": "^1.1.4", "kareem": "2.3.1", - "mongodb": "3.6.1", + "mongodb": "3.6.3", "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.7.0", "mquery": "3.2.2", @@ -776,11 +1867,2604 @@ "safe-buffer": "5.2.1", "sift": "7.0.1", "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose-lean-getters": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-lean-getters/-/mongoose-lean-getters-0.1.2.tgz", + "integrity": "sha512-OIgQP4POwsWE3oItEIohbvb0BvqW2SV248WU6Hh7mlEX1isPTCrfayZUgVoBkd9L/q42FTza+NZ4qOXtJSzEOQ==", + "dependencies": { + "mpath": "0.5.x" + }, + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "mongoose": "5.x" + } + }, + "node_modules/mongoose-lean-getters/node_modules/mpath": { + "version": "0.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.5.2.tgz", + "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mongoose-lean-virtuals": { + "version": "0.7.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.7.6.tgz", + "integrity": "sha512-Yb3u9+1vTbCgG87BFTbKl2O3kzcKRnZF9A4bRbbE2NMvWJqGzj0iVdDxPXaZQ8lBhlgFMPwh6oEYIAAPIvld+g==", + "dependencies": { + "array.prototype.flat": "1.2.3", + "mpath": "0.5.x" + }, + "peerDependencies": { + "mongoose": ">=5.9.9" + } + }, + "node_modules/mongoose-lean-virtuals/node_modules/mpath": { + "version": "0.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.5.2.tgz", + "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "peerDependencies": { + "mongoose": "*" + } + }, + "node_modules/mongoose-transactions": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", + "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==", + "peerDependencies": { + "mongoose": ">=4.11.1" + } + }, + "node_modules/mongoose/node_modules/bson": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "3.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "dependencies": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4" + }, + "optionalDependencies": { + "saslprep": "^1.0.0" + }, + "peerDependenciesMeta": { + "aws4": { + "optional": true + }, + "bson-ext": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "mongodb-extjson": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mpath": { + "version": "0.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.7.0.tgz", + "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mquery/-/mquery-3.2.2.tgz", + "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", + "dependencies": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/mquery/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/random-to": { + "version": "0.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/random-to/-/random-to-0.0.2.tgz", + "integrity": "sha512-ZuN1RFci2EBqx0fj2oClPUDEZ5FS20nxz0zXikR1ip1NUyu99i+2X9nL4872b7tESBatVaLXtMHHcxc7S4c9VA==" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp-clone": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise": { + "version": "4.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dependencies": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/require_optional": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "dependencies": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "node_modules/require_optional/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sequin": { + "version": "0.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sequin/-/sequin-0.1.1.tgz", + "integrity": "sha512-hJWMZRwP75ocoBM+1/YaCsvS0j5MTPeBHJkS2/wruehl9xwtX30HlDF1Gt6UZ8HHHY8SJa2/IL+jo+JJCd59rA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "7.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sift/-/sift-7.0.1.tgz", + "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sliced": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==" + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, + "@mongodb-js/saslprep": { + "version": "1.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", + "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "@typegoose/typegoose": { + "version": "7.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typegoose/typegoose/-/typegoose-7.6.3.tgz", + "integrity": "sha512-u12nUEmpMa0e+K8UuzAZvSnWZ7JZGo0yMs7HR4mG47gJJhVe/PIAzfXVPV+CJQBZrMSPyaEZ6HRKjmDxnjEgFg==", + "requires": { + "lodash": "^4.17.20", + "loglevel": "^1.7.0", + "reflect-metadata": "^0.1.13", + "semver": "^7.3.2", + "tslib": "^2.0.1" + } + }, + "@types/bluebird": { + "version": "3.5.42", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/bluebird/-/bluebird-3.5.42.tgz", + "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==" + }, + "@types/caseless": { + "version": "0.12.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" + }, + "@types/mongodb": { + "version": "4.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/mongodb/-/mongodb-4.0.7.tgz", + "integrity": "sha512-lPUYPpzA43baXqnd36cZ9xxorprybxXDzteVKCPAdp14ppHtFJHnXYvNpmBvtMUTb5fKXVv6sVbzo1LHkWhJlw==", + "requires": { + "mongodb": "*" + } + }, + "@types/mongoose": { + "version": "5.10.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/mongoose/-/mongoose-5.10.5.tgz", + "integrity": "sha512-37QMIA954T3n+HSksSNLlxZsqF8fMJu5S4dyPBod6gRxGtsXlQ9jUtL8BE8Seimv99u79eLXI3bggoCnSQ/fxQ==", + "requires": { + "@types/mongodb": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "25.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "requires": { + "undici-types": "~7.18.0" + } + }, + "@types/redis": { + "version": "2.8.32", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/redis/-/redis-2.8.32.tgz", + "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/request": { + "version": "2.48.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", + "requires": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.5" + } + }, + "@types/request-promise": { + "version": "4.1.51", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request-promise/-/request-promise-4.1.51.tgz", + "integrity": "sha512-qVcP9Fuzh9oaAh8oPxiSoWMFGnWKkJDknnij66vi09Yiy62bsSDqtd+fG5kIM9wLLgZsRP3Y6acqj9O/v2ZtRw==", + "requires": { + "@types/bluebird": "*", + "@types/request": "*" + } + }, + "@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + }, + "@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "@types/whatwg-url": { + "version": "13.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", + "requires": { + "@types/webidl-conversions": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.14.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "aproba": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "requires": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + } + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" + }, + "async-function": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + }, + "aws4": { + "version": "1.13.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bl": { + "version": "2.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "brace-expansion": { + "version": "1.1.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "bson": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/bson/-/bson-7.2.0.tgz", + "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==" + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "call-bind": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "requires": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "chinese-random-name": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chinese-random-name/-/chinese-random-name-1.0.0.tgz", + "integrity": "sha512-0ZJ0LhV4O9vqas4IgQB7IDqqSovpSoHlvZo3FWXShKBfs6BS7l4uRQVqin54D4KNrG81G7cZ7p6YIpn93fo2wQ==", + "requires": { + "flatten": "^1.0.2", + "random-to": "0.0.2" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "csprng": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/csprng/-/csprng-0.1.2.tgz", + "integrity": "sha512-D3WAbvvgUVIqSxUfdvLeGjuotsB32bvfVPd+AaaTWMtyUeC9zgCnw5xs94no89yFLVsafvY9dMZEhTwsY/ZecA==", + "requires": { + "sequin": "*" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-view-buffer": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "denque": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, + "detect-libc": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "es-abstract": { + "version": "1.24.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "requires": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, + "es-to-primitive": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "requires": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" + }, + "for-each": { + "version": "0.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "requires": { + "is-callable": "^1.2.7" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" + }, + "form-data": { + "version": "2.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "generator-function": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==" + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "get-symbol-description": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globalthis": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "requires": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-bigints": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==" + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "requires": { + "dunder-proto": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "internal-slot": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "requires": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + } + }, + "is-array-buffer": { + "version": "3.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + } + }, + "is-async-function": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "requires": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + } + }, + "is-bigint": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "requires": { + "has-bigints": "^1.0.2" + } + }, + "is-boolean-object": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "requires": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-data-view": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "requires": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + } + }, + "is-date-object": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "requires": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + } + }, + "is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "requires": { + "call-bound": "^1.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-function": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "requires": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + } + }, + "is-map": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==" + }, + "is-negative-zero": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==" + }, + "is-number-object": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "requires": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + } + }, + "is-regex": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "requires": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, + "is-set": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==" + }, + "is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "requires": { + "call-bound": "^1.0.3" + } + }, + "is-string": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "requires": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + } + }, + "is-symbol": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "requires": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + } + }, + "is-typed-array": { + "version": "1.1.15", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "requires": { + "which-typed-array": "^1.1.16" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==" + }, + "is-weakref": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "requires": { + "call-bound": "^1.0.3" + } + }, + "is-weakset": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "requires": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "kareem": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/kareem/-/kareem-2.3.1.tgz", + "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" + }, + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" + }, + "lodash": { + "version": "4.17.23", + "resolved": "https://mirrors.cloud.tencent.com/npm/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + }, + "loglevel": { + "version": "1.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "moment": { + "version": "2.30.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "mongodb": { + "version": "7.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb/-/mongodb-7.1.0.tgz", + "integrity": "sha512-kMfnKunbolQYwCIyrkxNJFB4Ypy91pYqua5NargS/f8ODNSJxT03ZU3n1JqL4mCzbSih8tvmMEMLpKTT7x5gCg==", + "requires": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^7.1.1", + "mongodb-connection-string-url": "^7.0.0" + } + }, + "mongodb-connection-string-url": { + "version": "7.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz", + "integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==", + "requires": { + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" + } + }, + "mongoose": { + "version": "5.10.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose/-/mongoose-5.10.18.tgz", + "integrity": "sha512-vaLUzBpUxqacoCqP/xXWMg/uVwCDrlc8LvYjDXCf8hdApvX/CXa0HLa7v2ieFaVd5Fgv3W2QXODLoC4Z/abbNw==", + "requires": { + "bson": "^1.1.4", + "kareem": "2.3.1", + "mongodb": "3.6.3", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.7.0", + "mquery": "3.2.2", + "ms": "2.1.2", + "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", + "sift": "7.0.1", + "sliced": "1.0.1" + }, + "dependencies": { + "bson": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + }, + "mongodb": { + "version": "3.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, "mongoose-lean-getters": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/mongoose-lean-getters/-/mongoose-lean-getters-0.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-lean-getters/-/mongoose-lean-getters-0.1.2.tgz", "integrity": "sha512-OIgQP4POwsWE3oItEIohbvb0BvqW2SV248WU6Hh7mlEX1isPTCrfayZUgVoBkd9L/q42FTza+NZ4qOXtJSzEOQ==", "requires": { "mpath": "0.5.x" @@ -788,14 +4472,14 @@ "dependencies": { "mpath": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.5.2.tgz", "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==" } } }, "mongoose-lean-virtuals": { "version": "0.7.6", - "resolved": "https://registry.npmjs.org/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.7.6.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-lean-virtuals/-/mongoose-lean-virtuals-0.7.6.tgz", "integrity": "sha512-Yb3u9+1vTbCgG87BFTbKl2O3kzcKRnZF9A4bRbbE2NMvWJqGzj0iVdDxPXaZQ8lBhlgFMPwh6oEYIAAPIvld+g==", "requires": { "array.prototype.flat": "1.2.3", @@ -804,30 +4488,32 @@ "dependencies": { "mpath": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.5.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.5.2.tgz", "integrity": "sha512-NOeCoW6AYc3hLi30npe7uzbD9b4FQZKH40YKABUCCvaKKL5agj6YzvHoNx8jQpDMNPgIa5bvSZQbQpWBAVD0Kw==" } } }, "mongoose-legacy-pluralize": { "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/mongoose-legacy-pluralize/download/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha1-O6n5H6UHtRhtOZ+0CFS/8Y+1Y+Q=" + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "requires": {} }, "mongoose-transactions": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", - "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", + "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==", + "requires": {} }, "mpath": { "version": "0.7.0", - "resolved": "https://registry.npm.taobao.org/mpath/download/mpath-0.7.0.tgz", - "integrity": "sha1-IOgQLidrcXCdbgfp+NTQ9kGvv7g=" + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.7.0.tgz", + "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==" }, "mquery": { "version": "3.2.2", - "resolved": "https://registry.npm.taobao.org/mquery/download/mquery-3.2.2.tgz", - "integrity": "sha1-4Tg6OVGFLOI+N/YZqbNQ8fs2ZOc=", + "resolved": "https://mirrors.cloud.tencent.com/npm/mquery/-/mquery-3.2.2.tgz", + "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", "requires": { "bluebird": "3.5.1", "debug": "3.1.0", @@ -836,282 +4522,258 @@ "sliced": "1.0.1" }, "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1575472461218&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", - "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "whatwg-url": "^5.0.0" }, "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "tr46": { + "version": "0.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { - "ms": "^2.1.1" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } } } }, - "node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" - }, - "node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + "abbrev": "1" } }, "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "oauth-sign": { "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, "object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "own-keys": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" } }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "performance-now": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "resolved": "https://mirrors.cloud.tencent.com/npm/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==" }, "process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", - "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" + "resolved": "https://mirrors.cloud.tencent.com/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "version": "1.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "requires": { + "punycode": "^2.3.1" + } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==" }, "random-to": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/random-to/-/random-to-0.0.2.tgz", - "integrity": "sha1-RoO58lfPuWSqPXsyPgCKIMboWnY=" - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } + "resolved": "https://mirrors.cloud.tencent.com/npm/random-to/-/random-to-0.0.2.tgz", + "integrity": "sha512-ZuN1RFci2EBqx0fj2oClPUDEZ5FS20nxz0zXikR1ip1NUyu99i+2X9nL4872b7tESBatVaLXtMHHcxc7S4c9VA==" }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", - "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - } + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "redis": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis/-/redis-3.1.2.tgz", "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", "requires": { "denque": "^1.5.0", "redis-commands": "^1.7.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0" - }, - "dependencies": { - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - } } }, "redis-commands": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-commands/-/redis-commands-1.7.0.tgz", "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" }, "redis-errors": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" }, "redis-parser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", "requires": { "redis-errors": "^1.0.0" } }, "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npm.taobao.org/reflect-metadata/download/reflect-metadata-0.1.13.tgz", - "integrity": "sha1-Z648pXyXKiqhZCsQ/jY/4y1J3Ag=" + "version": "0.1.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "requires": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + } }, "regexp-clone": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/regexp-clone/download/regexp-clone-1.0.0.tgz", - "integrity": "sha1-Ii25Z2IydwViYLmSYmNUoEzpv2M=" + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "requires": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + } }, "request": { "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", @@ -1138,7 +4800,7 @@ "dependencies": { "form-data": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", @@ -1150,7 +4812,7 @@ }, "request-promise": { "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise/-/request-promise-4.2.6.tgz", "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", "requires": { "bluebird": "^3.5.0", @@ -1161,7 +4823,7 @@ }, "request-promise-core": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise-core/-/request-promise-core-1.1.4.tgz", "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "requires": { "lodash": "^4.17.19" @@ -1169,93 +4831,203 @@ }, "require_optional": { "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/require_optional/download/require_optional-1.0.1.tgz", - "integrity": "sha1-TPNaQkf2TKPfjC7yCMxJSxyo/C4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "requires": { "resolve-from": "^2.0.0", "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } } }, "resolve-from": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } }, + "safe-array-concat": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + } + }, "safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz", - "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-push-apply": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "requires": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + } + }, + "safe-regex-test": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + } }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "saslprep": { "version": "1.0.3", - "resolved": "https://registry.npm.taobao.org/saslprep/download/saslprep-1.0.3.tgz", - "integrity": "sha1-TAL5RrVs9UKX40e6EJPnrKxM8iY=", + "resolved": "https://mirrors.cloud.tencent.com/npm/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", "optional": true, "requires": { "sparse-bitfield": "^3.0.3" } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", - "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==" }, "sequin": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz", - "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE=" + "resolved": "https://mirrors.cloud.tencent.com/npm/sequin/-/sequin-0.1.1.tgz", + "integrity": "sha512-hJWMZRwP75ocoBM+1/YaCsvS0j5MTPeBHJkS2/wruehl9xwtX30HlDF1Gt6UZ8HHHY8SJa2/IL+jo+JJCd59rA==" }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "resolved": "https://mirrors.cloud.tencent.com/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "set-proto": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "requires": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + } + }, + "side-channel": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + } }, "sift": { "version": "7.0.1", - "resolved": "https://registry.npm.taobao.org/sift/download/sift-7.0.1.tgz", - "integrity": "sha1-R9YsULFZ0xbxNy+LU/nBDNIaSwg=" + "resolved": "https://mirrors.cloud.tencent.com/npm/sift/-/sift-7.0.1.tgz", + "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "sliced": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + "resolved": "https://mirrors.cloud.tencent.com/npm/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" }, "sparse-bitfield": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, + "resolved": "https://mirrors.cloud.tencent.com/npm/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "requires": { "memory-pager": "^1.0.2" } }, "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -1270,114 +5042,200 @@ }, "stealthy-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + "resolved": "https://mirrors.cloud.tencent.com/npm/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==" }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" } }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" - } + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + } + }, + "string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "6.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" } }, "tough-cookie": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" } }, + "tr46": { + "version": "5.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "requires": { + "punycode": "^2.3.1" + } + }, "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.0.1.tgz?cache=0&sync_timestamp=1596751904317&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.1.tgz", - "integrity": "sha1-QQ6w0RPltjVkkO7HSWA3JbAhtD4=" + "version": "2.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "resolved": "https://mirrors.cloud.tencent.com/npm/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "requires": { "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "resolved": "https://mirrors.cloud.tencent.com/npm/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + } + }, + "typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "requires": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + } + }, + "typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + } + }, + "typed-array-length": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + } + }, + "unbox-primitive": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "requires": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + } }, "underscore": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.0.tgz", - "integrity": "sha512-21rQzss/XPMjolTiIezSu3JAjgagXKROtNrYFEOWK109qY1Uv2tVjPTZ1ci2HgvQDA16gHYSthQIJfB+XId/rQ==" + "version": "1.13.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==" + }, + "undici-types": { + "version": "7.18.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==" }, "uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" @@ -1385,41 +5243,112 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved": "https://mirrors.cloud.tencent.com/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "verror": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "14.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "requires": { - "string-width": "^1.0.2 || 2" + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "requires": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + } + }, + "which-builtin-type": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "requires": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + } + }, + "which-collection": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "requires": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + } + }, + "which-typed-array": { + "version": "1.1.20", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index dea3bcead..2a592b954 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "koa-is-json": "^1.0.0", "lodash": "^4.17.20", "moment": "^2.27.0", - "mongoose": "^5.10.4", + "mongoose": "5.10.18", "mongoose-lean-getters": "^0.1.2", "mongoose-lean-virtuals": "^0.7.6", "mongoose-transactions": "^1.1.4", diff --git a/shared/db/GVGLeagueFarm.ts b/shared/db/GVGLeagueFarm.ts index 8e2e423b3..68c69d514 100644 --- a/shared/db/GVGLeagueFarm.ts +++ b/shared/db/GVGLeagueFarm.ts @@ -146,8 +146,8 @@ export default class GVGLeagueFarm extends BaseModel { const fieldResult: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, lockRoleId: roleId, harvestTime: { $lt: nowSeconds() } }).lean(); const _ids = fieldResult.map(cur => cur._id); const result = await GVGLeagueFarmModel.updateMany({ _id: { $in: _ids } }, - { $set: { unlockTime: 0, harvestTime: 0, lockRoleId: '', lockRoleName: '', seedType: 0, index: 0 }}, { new: true }); - if(result.modifiedCount == 0) return []; + { $set: { unlockTime: 0, harvestTime: 0, lockRoleId: '', lockRoleName: '', seedType: 0, index: 0 } }); + if((result as any).nModified == 0) return []; return fieldResult } diff --git a/shared/db/Region.ts b/shared/db/Region.ts index 95f47dad7..8f17f57c5 100644 --- a/shared/db/Region.ts +++ b/shared/db/Region.ts @@ -109,7 +109,10 @@ export default class Region extends BaseModel { } public static async findRegionByEnv(env: string) { + console.log('****** findRegionByEnv env:', env); + console.log('****** findRegionByEnv RegionModel:', RegionModel); const rec: RegionType = await RegionModel.findOne({ env }).select('-_id').lean(); + console.log('****** findRegionByEnv rec:', rec); return rec; } diff --git a/shared/db/Sms.ts b/shared/db/Sms.ts index f3950cb64..410ab9caf 100644 --- a/shared/db/Sms.ts +++ b/shared/db/Sms.ts @@ -11,7 +11,7 @@ const moment = require('moment'); @index({ tel: 1 }) export default class Sms extends BaseModel { - @prop({ required: true, set: (val: string) => aesEncryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV), get: (val: string) => aesDecryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV) }) + @prop({ required: true, set: (val: string) => aesEncryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV), get: (val: string) => aesDecryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV) }) tel: string; @prop({ required: true }) @@ -33,7 +33,11 @@ export default class Sms extends BaseModel { isFixed: boolean; public static async findByTel(tel: string, lean = true) { + console.log(4); + const sms: SmsType = await smsModel.findOne({ tel }).lean(lean); + console.log(sms); + return sms; } @@ -71,17 +75,19 @@ export default class Sms extends BaseModel { public static async fixSms(tel: string) { - const sms: SmsType = await smsModel.findOneAndUpdate({ tel }, { $setOnInsert: { - tel, - code: generateNum(6), - used: false, - updateTime: new Date(), - countToday: 1 - }, $set: { isFixed: true } }, {new: true, upsert: true}).lean({ getters: true }); + const sms: SmsType = await smsModel.findOneAndUpdate({ tel }, { + $setOnInsert: { + tel, + code: generateNum(6), + used: false, + updateTime: new Date(), + countToday: 1 + }, $set: { isFixed: true } + }, { new: true, upsert: true }).lean({ getters: true }); return sms; } } export const smsModel = getModelForClass(Sms); -export interface SmsType extends Pick, keyof Sms>{}; \ No newline at end of file +export interface SmsType extends Pick, keyof Sms> { }; \ No newline at end of file diff --git a/shared/pubUtils/sysUtil.ts b/shared/pubUtils/sysUtil.ts index e7c922068..8fbf1edb1 100644 --- a/shared/pubUtils/sysUtil.ts +++ b/shared/pubUtils/sysUtil.ts @@ -12,13 +12,13 @@ const publicKey = fs.readFileSync(path.resolve(__dirname, `../resource/publicKey export async function checkWhiteList(env: string, ip: string, uid: number) { - if(ip) { + if (ip) { let result = await WhiteListModel.checkIp(env, ip); - if(!!result) return true; + if (!!result) return true; } - if(uid) { + if (uid) { let result = await WhiteListModel.checkUid(env, uid); - if(!!result) return true; + if (!!result) return true; } return false } @@ -30,20 +30,20 @@ export class MsgEncrypt { private encodeV: string = ''; constructor(data: { k?: string, v?: string, encodeK?: string, encodeV?: string, originK?: string, originV?: string }) { - if(data.k && data.v) { + if (data.k && data.v) { this.encodeAndSetKv(data.k, data.v); } - if(data.encodeK && data.encodeV) { + if (data.encodeK && data.encodeV) { this.decodeAndSetKv(data.encodeK, data.encodeV); } - if(data.originK && data.originV) { + if (data.originK && data.originV) { this.k = data.originK; this.v = data.originV; } } public decryptMsg(data: string) { - if(!data) return false + if (!data) return false try { const decodeStr = aesDecrypt(data, this.k, this.v); @@ -51,32 +51,32 @@ export class MsgEncrypt { let body = JSON.parse(decodeStr); return body - } catch(e) { + } catch (e) { console.error(e); return false; } } public encryptMsg(json: Object) { - if(!isJSON(json)) return false; + if (!isJSON(json)) return false; try { const encodeStr = aesEncrypt(JSON.stringify(json), this.k, this.v); // console.log('encode str:', encodeStr); return encodeStr; - } catch(e) { + } catch (e) { console.error(e); return false; } } public decodeAndSetKv(requestK: string, requestV: string) { - if(requestK) { + if (requestK) { this.encodeK = requestK; this.k = this.privateDecrypt(Buffer.from(requestK, 'base64')); } - if(requestV) { + if (requestV) { this.encodeV = requestV; this.v = this.privateDecrypt(Buffer.from(requestV, 'base64')); } @@ -93,26 +93,26 @@ export class MsgEncrypt { private privateDecrypt(encryptMsg: Buffer) { const decryptMsg = crypto.privateDecrypt( - { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, - encryptMsg + { key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, + encryptMsg ); return decryptMsg.toString(); } - + private getRsaEncodedData(original: string) { const encryptMsg = crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(original) - ); + ); return encryptMsg.toString('base64'); } private encodeAndSetKv(k: string, v: string) { - if(k) { + if (k) { this.k = k; this.encodeK = this.getRsaEncodedData(k); } - if(v) { + if (v) { this.v = v; this.encodeV = this.getRsaEncodedData(v); } diff --git a/shared/pubUtils/util.ts b/shared/pubUtils/util.ts index 8f4f891e0..ca01790c6 100644 --- a/shared/pubUtils/util.ts +++ b/shared/pubUtils/util.ts @@ -906,11 +906,28 @@ export function getArrayOfNumber(len: number) { // 比较以 . 分隔的版本号。返回 0 则版本号相等,返回正数则 versionA 大,返回负数则 versionB 大 export function compareVersion(versionA: string, versionB: string) { + if (!versionA && !versionB) { + return 0; + } + if (!versionA) { + return -1; + } + if (!versionB) { + return 1; + } + var vA = versionA.split('.'); var vB = versionB.split('.'); for (var i = 0; i < vA.length; ++i) { var a = parseInt(vA[i]); var b = parseInt(vB[i] || '0'); + if (isNaN(a) || isNaN(b)) { + if (a === b) { + continue; + } else { + return isNaN(a) ? -1 : 1; + } + } if (a === b) { } else { diff --git a/shared/resource/privateKey.bak b/shared/resource/privateKey.bak new file mode 100644 index 000000000..13594c741 --- /dev/null +++ b/shared/resource/privateKey.bak @@ -0,0 +1,19 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA3z9t4t3e7r6u9v8y7x6s5d4f3g2h1j0k9l8m7n6o5p4q3r2t +1u0v9w8x7y6z5a4b3c2d1e0f/g9h8i7j6k5l4m3n2o1p0q/r9s8t7u6v5w4x3y2 +z1a0b9c8d7e6f5g4h3i2j1k0l9m8n7o6p5q4r3s2t1u0v/w8x7y6z5a4b3c2d1e +0f9g8h7i6j5k4l3m2n1o0p9q8r7s6t5u4v3w2x1y0z/a9b8c7d6e5f4g3h2i1j0 +k9l8m7n6o5p4q3r2t1u0v9w8x7y6z5a4b3c2d1e0f8g7h6i5j4k3l2m1n0o9p8q +7r6s5t4u3v2w1x0y9z8a7b6c5d4e3f2g1h0i9j8k7l6m5n4o3p2q1r0s9t8u7v6 +w5x4y3z2a1b0c9d8e7f6g5h4i3j2k1l0m9n8o7p6q5r4s3t2u1v0w9x8y7z6a5b +4c3d2e1f0/g9h8i7j6k5l4m3n2o1p0q9r8s7t6u5v4w3x2y1z0a9b8c7d6e5f4g +3h2i1j0k9l8m7n6o5p4q3r2t1u0v9w8x7y6z5a4b3c2d1e0f7g6h5i4j3k2l1m0 +n9o8p7q6r5s4t3u2v1w0x9y8z7a6b5c4d3e2f1g0h9i8j7k6l5m4n3o2p1q0r9s +8t7u6v5w4x3y2z1a0b9c8d7e6f5g4h3i2j1k0l9m8n7o6p5q4r3s2t1u0v/w8x +7y6z5a4b3c2d1e0f9g8h7i6j5k4l3m2n1o0p9q8r7s6t5u4v3w2x1y0z/a9b8c7 +d6e5f4g3h2i1j0k9l8m7n6o5p4q3r2t1u0v9w8x7y6z5a4b3c2d1e0f8g7h6i5j +4k3l2m1n0o9p8q7r6s5t4u3v2w1x0y9z8a7b6c5d4e3f2g1h0i9j8k7l6m5n4o3 +p2q1r0s9t8u7v6w5x4y3z2a1b0c9d8e7f6g5h4i3j2k1l0m9n8o7p6q5r4s3t2u +1v0w9x8y7z6a5b4c3d2e1f0/g9h8i7j6k5l4m3n2o1p0q9r8s7t6u5v4w3x2y1z +0a9b8c7d6e5f4g3h2i1j0k9l8m7n6o5p4q3r2t1u0v9w8x7y6z5a4b3c2d1e0f7 +-----END RSA PRIVATE KEY----- diff --git a/shared/resource/privateKey.pem b/shared/resource/privateKey.pem new file mode 100644 index 000000000..26590c410 --- /dev/null +++ b/shared/resource/privateKey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDvMNFFkoHvvr7l +/mVXf5znhN8opWTbW5lK6EWi7k0xPKhFxl2WWow+JbowIXRa8UmMZyrk6DUqLLWJ +Ha2B3B/WXHJ00S4LCFE3UO0XF1rLJ3qYCRkDed+O+/AvykcWsNUOG2LApscjOfsd +xuO/RBY6sEkSnZNsvxeEbBXKf7tD2pSo+RwW7/h1RN4zqWRwMP72e4wqqd6yCEEU +rHre900dMoz0lckbtK9uEsqXonsCpkQtVqPNie2hiUcOCXrRQbCoEA9Nirzm+UrV +zqPYDUu+l6sixe8lLSbTRPaCKJ36mjQoWJ9HQN0Nji9THtkbWadBc9P+uc0M3266 +Pa2tHVbHAgMBAAECggEAZpfbyymSDhEUtHWvZh5YYH1/cmGupt/dGmISLFZmSa4o +xvTUg38HFEj+WVKgI7nGwDAoF9L5qsNOgid2mnKePUWd2jk2tIi2vTE64GKmEOk4 +DiooznLhzuSFGxp572OdntVkQBnI5HUkHpuGaC1+E2I1lYR9DXHRVn09w4OSAQHV +4XTODIxhb09o1IB1vMp6OF1b5WBTwHopDWMUSuoJbHv0B8UoO176/FT2qV/53qKn +CjIazDNycn0zl/nFWInvIY3WAAMyANPFWfgjDfBQ/pvY7yF67x8fk16ezSLhKZ6J +GSN+CEaYm6KHg5HsXWNrSy2RM8FCex2m6fJalFi7gQKBgQD0AMGimIofydbyYYH1 +pP8vJfzGXjnzF6z7pS7lKADruHDYUoCfo8QTpsZ7WNBPw1j2QPWpZP+1RC35DhA4 +Wp17riWPLDSTA1XToqPk4V7EQdLXrbv//W14NDHzML0RfXhgmlUq7f38VhmBy/d8 +6ALhl99UPrzgl1ZyXSrciRl9JwKBgQD6831UlFw2Ex1pzx5leZMxlJMPk9NXVRbA +/Hw0FjzZEvZppeDse5JY1FusWmQy35mbQMEtIcs9IypmH3jD0UzDhl/zEB0B6K+Y +OXlGrTYpXcwPqg5zYnPU/n8YHu7xaK4tm8csVP5PyNJca10zqX8E6i2H6oOK2JUd +vE3FeiydYQKBgGxABafwCp9NuXmwvqpPOBMfxEPxO75YS5scznBFzhrFqfKer4ej +bPLW84l3fntUjBw794DeWP9/LvImRhXqRaHAQdOB5hUuzp3kstdxEMz68uJSpmxM +b4t7hImCnu6qfoRFE/HGwf536DsIVVTpzZVt/ltutfbhzS1RnhlXDaLTAoGAH8JM +7DVSbi2BHXDu4dy++hlZezE0H+tO0+GgPl9KGBbERJ6Plp4U6VUGvQs7fwy5PeK2 +D+Yk+HnI1d/Jws5sLpqE7hft893kyxkK9hzZq+aI+rqE1alyC1Sh9QWFK9wZnwAF +9uBSxvodVUDpLK6YuqCAXqEZQKskQ/0ewo0xtEECgYAtLhT7ghs15K4v0SuBrDDL +Jipo4o0cewEEzjxa4J3cHWUzJFE45uFWCH9EgGy/YM7fxeewa+LyyYKPOGYLJ9nw +abb3MFm1nxrzrJgBwGM6x2ORmEaIu00NC5H1ey0yXFj0HLt4OYY0Qlt4yako3Pvr +qHdpsSOk/QkdT4WrZWFsdw== +-----END PRIVATE KEY----- diff --git a/shared/resource/publicKey b/shared/resource/publicKey index 675bfe852..3b485fe6c 100644 --- a/shared/resource/publicKey +++ b/shared/resource/publicKey @@ -1,6 +1,9 @@ -----BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiU143FYs5+uJlIn/AK6gKhOEl -WydR/7OJ1MUSWFJz9yL/acIyNBQ4Ji/0adDaIB01pQ9eqCYFP0Z9SgGMcpST/ejU -LEUbjls7GTwutxoVVe9PUDBkRY601RVAEjXaZmWfZZ7028uWrqfJmeEo3voKhscO -/vCOKII2TM1xC+FMGwIDAQAB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7zDRRZKB776+5f5lV3+c +54TfKKVk21uZSuhFou5NMTyoRcZdllqMPiW6MCF0WvFJjGcq5Og1Kiy1iR2tgdwf +1lxydNEuCwhRN1DtFxdayyd6mAkZA3nfjvvwL8pHFrDVDhtiwKbHIzn7Hcbjv0QW +OrBJEp2TbL8XhGwVyn+7Q9qUqPkcFu/4dUTeM6lkcDD+9nuMKqnesghBFKx63vdN +HTKM9JXJG7SvbhLKl6J7AqZELVajzYntoYlHDgl60UGwqBAPTYq85vlK1c6j2A1L +vperIsXvJS0m00T2giid+po0KFifR0DdDY4vUx7ZG1mnQXPT/rnNDN9uuj2trR1W +xwIDAQAB -----END PUBLIC KEY----- diff --git a/shared/resource/publicKey.bak b/shared/resource/publicKey.bak new file mode 100644 index 000000000..675bfe852 --- /dev/null +++ b/shared/resource/publicKey.bak @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiU143FYs5+uJlIn/AK6gKhOEl +WydR/7OJ1MUSWFJz9yL/acIyNBQ4Ji/0adDaIB01pQ9eqCYFP0Z9SgGMcpST/ejU +LEUbjls7GTwutxoVVe9PUDBkRY601RVAEjXaZmWfZZ7028uWrqfJmeEo3voKhscO +/vCOKII2TM1xC+FMGwIDAQAB +-----END PUBLIC KEY----- diff --git a/shared/resource/publicKey.pem b/shared/resource/publicKey.pem new file mode 100644 index 000000000..3b485fe6c --- /dev/null +++ b/shared/resource/publicKey.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7zDRRZKB776+5f5lV3+c +54TfKKVk21uZSuhFou5NMTyoRcZdllqMPiW6MCF0WvFJjGcq5Og1Kiy1iR2tgdwf +1lxydNEuCwhRN1DtFxdayyd6mAkZA3nfjvvwL8pHFrDVDhtiwKbHIzn7Hcbjv0QW +OrBJEp2TbL8XhGwVyn+7Q9qUqPkcFu/4dUTeM6lkcDD+9nuMKqnesghBFKx63vdN +HTKM9JXJG7SvbhLKl6J7AqZELVajzYntoYlHDgl60UGwqBAPTYq85vlK1c6j2A1L +vperIsXvJS0m00T2giid+po0KFifR0DdDY4vUx7ZG1mnQXPT/rnNDN9uuj2trR1W +xwIDAQAB +-----END PUBLIC KEY----- diff --git a/web-server/.github/workflows/nodejs.yml b/web-server/.github/workflows/nodejs.yml index 81041c4bc..31e86f96a 100644 --- a/web-server/.github/workflows/nodejs.yml +++ b/web-server/.github/workflows/nodejs.yml @@ -5,9 +5,13 @@ name: Node.js CI on: push: - branches: [ master ] + branches: + - main + - master pull_request: - branches: [ master ] + branches: + - main + - master schedule: - cron: '0 2 * * *' @@ -31,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Dependencies - run: npm i -g npminstall && npminstall + run: npm i -g npminstall@5 && npminstall - name: Continuous Integration run: npm run ci diff --git a/web-server/.travis.yml b/web-server/.travis.yml index 9749f42d5..fc5fd2a56 100644 --- a/web-server/.travis.yml +++ b/web-server/.travis.yml @@ -3,7 +3,7 @@ language: node_js node_js: - '8' before_install: - - npm i npminstall -g + - npm i npminstall@5 -g install: - npminstall script: diff --git a/web-server/app.ts b/web-server/app.ts index d5393a644..d1447c8cd 100644 --- a/web-server/app.ts +++ b/web-server/app.ts @@ -1,9 +1,9 @@ import 'reflect-metadata' import * as mongoose from 'mongoose'; import { Application, IBoot } from 'egg'; -import { connectRedis } from './app/pubUtils/redis'; -import { loadGmDb, loadSubDb } from '@db/index'; -import { SDK_TA_CONST, THINKING_DATA_MODE, THINKING_DATA_MODE_LIST } from '@consts'; +import { connectRedis } from '../shared/pubUtils/redis'; +import { loadGmDb, loadSubDb } from '../shared/db/index'; +import { SDK_TA_CONST, THINKING_DATA_MODE, THINKING_DATA_MODE_LIST } from '../shared/consts'; const ThinkingAnalytics = require("thinkingdata-node"); export default class FooBoot implements IBoot { @@ -23,9 +23,11 @@ export default class FooBoot implements IBoot { await this.connectRedis(this.app); this.app.config.realEnv = this.app.config.env; + console.log('****** config.env:', this.app.config.env); if(this.app.config.env == 'local') { this.app.config.realEnv = 'development'; } + console.log('****** config.realEnv:', this.app.config.realEnv); // 如果gm使用的就是本机代理,host不转发到target而只把path替换 if(this.app.config.httpProxy && this.app.config.httpProxy[`/web/${this.app.config.realEnv}/`]) { this.app.config.httpProxy[`/web/${this.app.config.realEnv}/`].changeOrigin = false; @@ -67,11 +69,15 @@ export default class FooBoot implements IBoot { const { url, options } = app.config.mongoose try { if (url) { + // @ts-ignore const connection = await mongoose.connect(url, options) + // @ts-ignore console.log('******connectDB suc', url, options) + // @ts-ignore app.context.connection = connection } } catch(e) { + // @ts-ignore console.log(e) } } @@ -80,12 +86,17 @@ export default class FooBoot implements IBoot { const { url, options } = app.config.gmmongoose try { if (url) { + // @ts-ignore const connection = await mongoose.createConnection(url, options) + // @ts-ignore app.context.connectionGM = connection; + // @ts-ignore loadGmDb(connection); + // @ts-ignore console.log('******connectGMDB suc', url, options) } } catch(e) { + // @ts-ignore console.log(e) } } @@ -94,12 +105,17 @@ export default class FooBoot implements IBoot { const { url, options } = app.config.submongoose||app.config.mongoose try { if (url) { + // @ts-ignore const connection = await mongoose.createConnection(url, options) + // @ts-ignore app.context.connectionGM = connection; + // @ts-ignore loadSubDb(connection); + // @ts-ignore console.log('******connectSubDB suc', url, options) } } catch(e) { + // @ts-ignore console.log(e) } } @@ -107,7 +123,9 @@ export default class FooBoot implements IBoot { public async connectRedis(app: Application) { const { url, pw } = app.config.redis if (url) { + // @ts-ignore const redisClient = connectRedis(url, pw); + // @ts-ignore app.context.redisClient = redisClient; } } @@ -115,11 +133,15 @@ export default class FooBoot implements IBoot { public connectThinkingData(app: Application) { let ta; if(app.config.realEnv != 'development') { + // @ts-ignore if(THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.DEBUG) { + // @ts-ignore ta = ThinkingAnalytics.initWithDebugMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.BATCH) { + // @ts-ignore ta = ThinkingAnalytics.initWithBatchMode(SDK_TA_CONST.APPID, SDK_TA_CONST.SERVER_URL); } else if (THINKING_DATA_MODE == THINKING_DATA_MODE_LIST.LOGGING) { + // @ts-ignore ta = ThinkingAnalytics.initWithLoggingMode(SDK_TA_CONST.LOG_PATH, { pm2: true }); @@ -131,6 +153,7 @@ export default class FooBoot implements IBoot { // mode: THINKING_DATA_MODE // }; // }); + // @ts-ignore app.context.ta = ta; } } diff --git a/web-server/app/controller/game.ts b/web-server/app/controller/game.ts index 802747d84..c6f674055 100644 --- a/web-server/app/controller/game.ts +++ b/web-server/app/controller/game.ts @@ -1,26 +1,26 @@ -import { UserModel } from '@db/User'; -import { LadderMatchRecModel } from '@db/LadderMatchRec'; -import { PvpRecordModel } from '@db/PvpRecord'; -import { BattleRecordModel } from '@db/BattleRecord'; -import { STATUS, WAR_TYPE } from '@consts'; +import { UserModel } from '../../../shared/db/User'; +import { LadderMatchRecModel } from '../../../shared/db/LadderMatchRec'; +import { PvpRecordModel } from '../../../shared/db/PvpRecord'; +import { BattleRecordModel } from '../../../shared/db/BattleRecord'; +import { STATUS, WAR_TYPE } from '../../../shared/consts'; import { Controller } from 'egg'; import * as fs from 'fs'; -import { RoleModel } from '@db/Role'; -import { NoticeModel } from '@db/Notice'; -import { ServerParamWithRole, GroupParam } from '../domain/gameField/serverlist'; -import { reloadResources } from 'app/pubUtils/data'; -import { ServerlistModel } from '@db/Serverlist'; -import { dispatch } from 'app/pubUtils/dispatcher'; +import { RoleModel } from '../../../shared/db/Role'; +import { NoticeModel } from '../../../shared/db/Notice'; +import { ServerParamWithRole, GroupParam } from '../../../shared/domain/gameField/serverlist'; +import { reloadResources } from '../../../shared/pubUtils/data'; +import { ServerlistModel } from '../../../shared/db/Serverlist'; +import { dispatch } from '../../../shared/pubUtils/dispatcher'; import { RedisClient } from 'redis'; -import { REDIS_KEY } from '@consts'; -import { RegionModel } from '@db/Region'; -import { getRandEelmWithWeight } from 'app/pubUtils/util'; -import { getLocalRplUrl, getRemoteRplUrl, getRemoteRplPrefix } from 'app/pubUtils/battleUtils' -import { ChannelInfoModel } from '@db/ChannelInfo'; -import { GVGVestigeRecModel } from '@db/GVGVestigeRec'; -import { GVGBattleRecModel } from '@db/GVGBattleRec'; -import { PackageModel } from '@db/Package'; -import { nowSeconds } from 'app/pubUtils/timeUtil'; +import { REDIS_KEY } from '../../../shared/consts'; +import { RegionModel } from '../../../shared/db/Region'; +import { getRandEelmWithWeight } from '../../../shared/pubUtils/util'; +import { getLocalRplUrl, getRemoteRplUrl, getRemoteRplPrefix } from '../../../shared/pubUtils/battleUtils' +import { ChannelInfoModel } from '../../../shared/db/ChannelInfo'; +import { GVGVestigeRecModel } from '../../../shared/db/GVGVestigeRec'; +import { GVGBattleRecModel } from '../../../shared/db/GVGBattleRec'; +import { PackageModel } from '../../../shared/db/Package'; +import { nowSeconds } from '../../../shared/pubUtils/timeUtil'; const sendToWormhole = require('stream-wormhole'); const pump = require('mz-modules/pump'); @@ -49,12 +49,16 @@ export default class GameController extends Controller { const { ctx } = this; const { version, platformAppid, platformAppId, addressType, platform: clientPlatform } = ctx.request.body; + console.log('****** checkReview realEnv:', this.app.config.realEnv); let curRegion = await RegionModel.findRegionByEnv(this.app.config.realEnv); + console.log('****** checkReview curRegion:', JSON.stringify(curRegion, null, 2)); if(!curRegion) { + console.log('****** checkReview curRegion is null'); return ctx.body = ctx.service.utils.resResult(STATUS.VERSION_ERR); } if(curRegion.addressType != addressType) { + console.log('****** checkReview addressType mismatch:', curRegion.addressType, '!=', addressType); return ctx.body = ctx.service.utils.resResult(STATUS.ADDRESS_ERR); } @@ -202,29 +206,31 @@ export default class GameController extends Controller { const { ctx } = this; const { app, userCode } = ctx; - let redisClient: RedisClient = app.context.redisClient; - let hash = await redisClient.hvalsAsync(REDIS_KEY.SYS_SERVER); - let connectors = hash.map(cur => JSON.parse(cur)); + let redisClient: RedisClient = (app.context as any).redisClient; + let hash = await (redisClient as any).hvalsAsync(REDIS_KEY.SYS_SERVER); + let connectors = hash.map((cur: string) => JSON.parse(cur)); if (!connectors || connectors.length === 0) { ctx.body = ctx.service.utils.resResult(STATUS.CONNECTOR_ERR); return } // select connector - let sum = connectors.reduce((pre, cur) => pre + (cur['num']||0), 0); + let sum = connectors.reduce((pre: number, cur: any) => pre + (cur['num']||0), 0); let res; if(sum > 0) { - let serversWithWeight = connectors.map(cur => ({...cur, weight: sum - (cur['num']||0)})); + let serversWithWeight = connectors.map((cur: any) => ({...cur, weight: sum - (cur['num']||0)})); let randResult = getRandEelmWithWeight(serversWithWeight); res = randResult.dic; } if(!res) { - res = await dispatch(ctx.app.context.redisClient, userCode, connectors, 'connector'); + res = await dispatch((ctx.app.context as any).redisClient, userCode, connectors, 'connector'); } - let { id, serverType, clientHost, clientPort, num = 0 } = res; + // 使用类型断言确保TypeScript知道res是ServerInfo类型 + const serverInfo = res as any; + let { id, serverType, clientHost, clientPort, num = 0 } = serverInfo; - await redisClient.hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: num + 1 })); - ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { host: res.clientHost, port: res.clientPort }); + await (redisClient as any).hsetAsync(REDIS_KEY.SYS_SERVER, id, JSON.stringify({ serverType, clientHost, clientPort, id, num: num + 1 })); + ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { host: serverInfo.clientHost, port: serverInfo.clientPort }); return } diff --git a/web-server/app/controller/sdk.ts b/web-server/app/controller/sdk.ts index 86775875b..808213bd4 100644 --- a/web-server/app/controller/sdk.ts +++ b/web-server/app/controller/sdk.ts @@ -1,5 +1,5 @@ import { Controller } from 'egg'; -import { GetGuildInfoByUserParam, GetRoleByServerParam, GetRoleByUidParam, GetServerAndUidParam, GetServerListParam, GetServerParam, GuildNameCallBackParam, IOSRefundParam, PayCallback37Data, RoleNameCallBackParam, SendGiftCodeParam } from '../domain/sdk'; +import { GetGuildInfoByUserParam, GetRoleByServerParam, GetRoleByUidParam, GetServerAndUidParam, GetServerListParam, GetServerParam, GuildNameCallBackParam, IOSRefundParam, PayCallback37Data, RoleNameCallBackParam, SendGiftCodeParam } from '../../../shared/domain/sdk'; export default class SdkController extends Controller { diff --git a/web-server/app/controller/update.ts b/web-server/app/controller/update.ts index d64e5de8f..a25ea984e 100644 --- a/web-server/app/controller/update.ts +++ b/web-server/app/controller/update.ts @@ -1,7 +1,7 @@ import { Controller } from 'egg'; import { RegionModel } from '@db/Region'; import { STATUS } from '@consts'; -import { checkWhiteList } from 'app/pubUtils/sysUtil'; +import { checkWhiteList } from '@pubUtils/sysUtil'; export default class UpdateController extends Controller { public async getversion() { diff --git a/web-server/app/middleware/checkMainten.ts b/web-server/app/middleware/checkMainten.ts index 7d1bb18d0..daac6509e 100644 --- a/web-server/app/middleware/checkMainten.ts +++ b/web-server/app/middleware/checkMainten.ts @@ -1,11 +1,12 @@ import { STATUS } from '@consts'; import { ServerlistModel } from '@db/Serverlist'; -import { nowSeconds } from 'app/pubUtils/timeUtil'; -import { checkWhiteList } from 'app/pubUtils/sysUtil'; +import { nowSeconds } from '@pubUtils/timeUtil'; +import { checkWhiteList } from '@pubUtils/sysUtil'; import { RoleModel } from '@db/Role'; +import { Context } from 'egg'; module.exports = () => { - return async function checkMainten(ctx, next) { + return async function checkMainten(ctx: Context, next: () => Promise) { const { serverId, version } = ctx.request.body; if (serverId) { let server = await ServerlistModel.findByServerId(serverId); diff --git a/web-server/app/middleware/egg-proxy.ts b/web-server/app/middleware/egg-proxy.ts index 831ff5360..d1b5faa5d 100644 --- a/web-server/app/middleware/egg-proxy.ts +++ b/web-server/app/middleware/egg-proxy.ts @@ -2,6 +2,14 @@ import c2k = require('koa-connect'); import { createProxyMiddleware, Options as ContextOptions } from 'http-proxy-middleware'; import * as micromatch from 'micromatch'; import * as isGlob from 'is-glob'; +import { Context } from 'egg'; + +// 扩展Request接口,添加rawBody属性 +declare module 'egg' { + interface Request { + rawBody: string; + } +} function match(context: string, path: string): boolean { // single path @@ -19,7 +27,7 @@ export interface Options { } export default function (options: Options) { - return async (ctx, next) => { + return async (ctx: Context, next: () => Promise) => { for (const context of Object.keys(options)) { if (match(context, ctx.path)) { const contextOptions: ContextOptions = options[context]; @@ -41,7 +49,7 @@ export default function (options: Options) { return proxyReq; }, }) as any - )(ctx, next); + )(ctx as any, next); } } await next(); diff --git a/web-server/app/middleware/getIp.ts b/web-server/app/middleware/getIp.ts index 6d974c9a2..d3c729d83 100644 --- a/web-server/app/middleware/getIp.ts +++ b/web-server/app/middleware/getIp.ts @@ -1,7 +1,7 @@ import { Context } from 'egg'; module.exports = () => { - return async function parmsDecode(ctx: Context, next) { + return async function parmsDecode(ctx: Context, next: () => Promise) { let clientIp = null; if (ctx.header['x-forwarded-for'] && (typeof ctx.header['x-forwarded-for'] == 'string')) { diff --git a/web-server/app/middleware/gmTokenParser.ts b/web-server/app/middleware/gmTokenParser.ts index a6346ad4a..b8d01ad54 100644 --- a/web-server/app/middleware/gmTokenParser.ts +++ b/web-server/app/middleware/gmTokenParser.ts @@ -2,17 +2,19 @@ import { GMUserModel } from '@db/GMUser'; import { GMGroupModel } from '@db/GMGroup' import { GMRecordModel } from '@db/GMRecord' import { GM_API_TYPE, STATUS } from '@consts'; -import { gameData } from 'app/pubUtils/data'; +import { gameData } from '@pubUtils/data'; +import { Context } from 'egg'; module.exports = () => { - return async function tokenParser(ctx, next) { + return async function tokenParser(ctx: Context, next: () => Promise) { if (!ctx.request.headers || !ctx.request.headers.token) { console.error('token not found'); ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS); return; } - const user = await GMUserModel.getGmAccountByToken(ctx.request.headers.token); + const token = typeof ctx.request.headers.token === 'string' ? ctx.request.headers.token : ctx.request.headers.token[0]; + const user = await GMUserModel.getGmAccountByToken(token); if (!user) { console.error('token invalid'); ctx.body = ctx.service.utils.resResult(STATUS.TOKEN_ERR); diff --git a/web-server/app/middleware/parmsDecode.ts b/web-server/app/middleware/parmsDecode.ts index 371910473..07adfae46 100644 --- a/web-server/app/middleware/parmsDecode.ts +++ b/web-server/app/middleware/parmsDecode.ts @@ -1,39 +1,41 @@ -import { genCode } from 'app/pubUtils/util'; -import { MsgEncrypt } from "app/pubUtils/sysUtil"; +import { genCode } from '../../../shared/pubUtils/util'; +import { MsgEncrypt } from "../../../shared/pubUtils/sysUtil"; import { Context } from 'egg'; -module.exports = options => { - return async function parmsDecode(ctx: Context, next) { +module.exports = (options: any) => { + return async function parmsDecode(ctx: Context, next: () => Promise) { let url = ctx.request.url; ctx.logcode = genCode(10); - if(url.indexOf("/dev") == 0 || url.indexOf("/web") == 0 || url.indexOf("/cb") == 0) { + if (url.indexOf("/dev") == 0 || url.indexOf("/web") == 0 || url.indexOf("/cb") == 0) { ctx.service.utils.log('INFO', `[${ctx.request.url}] [${ctx.logcode}] request: ${JSON.stringify(ctx.request.body)}`); await next(); ctx.service.utils.log('INFO', `[${ctx.request.url}] [${ctx.logcode}] res: ${JSON.stringify(ctx.body)}`) return; - } + } if (options.threshold && ctx.length < options.threshold) return; const reqBody = ctx.request.body; const reqHeader = ctx.request.header; console.log(ctx.app.config.decodeParm) - if(ctx.app.config.decodeParm == false) { + if (ctx.app.config.decodeParm == false) { await next(); return; } if (!reqBody.data) return; - let msgEncrypt = new MsgEncrypt({ encodeK: reqHeader['k'], encodeV: reqHeader['v'] }); + const k = typeof reqHeader['k'] === 'string' ? reqHeader['k'] : reqHeader['k'][0]; + const v = typeof reqHeader['v'] === 'string' ? reqHeader['v'] : reqHeader['v'][0]; + let msgEncrypt = new MsgEncrypt({ encodeK: k, encodeV: v }); console.log(`encode str ${msgEncrypt.encryptMsg(reqBody)}`); try { let decryptResult = msgEncrypt.decryptMsg(reqBody.data); - if(!decryptResult) throw new Error('params parse err'); + if (!decryptResult) throw new Error('params parse err'); ctx.request.body = decryptResult; - console.log('req body', ctx.request.body); + console.log('req body:', ctx.request.body); ctx.service.utils.log('INFO', `[${ctx.request.url}] [${ctx.logcode}] request: ${JSON.stringify(ctx.request.body)}`) } catch (e) { console.error('parms parse err'); @@ -41,9 +43,9 @@ module.exports = options => { } - try{ + try { await next(); - } catch(e) { + } catch (e) { ctx.service.utils.log('ERROR', `[${ctx.request.url}] [${ctx.logcode}] err: ${(e).stack}`); throw e; } diff --git a/web-server/app/middleware/proxy.ts b/web-server/app/middleware/proxy.ts index d7ea0d193..e59b3cd14 100644 --- a/web-server/app/middleware/proxy.ts +++ b/web-server/app/middleware/proxy.ts @@ -1,9 +1,20 @@ import { RegionModel } from '@db/Region'; import { ServerlistModel } from '@db/Serverlist'; import proxy from './egg-proxy'; +import { Context } from 'egg'; + +interface ProxyOptions { + [key: string]: { + target: string; + changeOrigin: boolean; + secure: boolean; + pathRewrite?: (path: string) => string; + headers?: { [key: string]: string }; + }; +} module.exports = () => { - return async function (ctx, next) { + return async function (ctx: Context, next: () => Promise) { if(!ctx.app.config.envToHost) { let envToHost = new Map(); let regions = await RegionModel.getAllRegion(); @@ -16,13 +27,13 @@ module.exports = () => { await getNewHost(ctx); } - let options = {}; + let options: ProxyOptions = {}; for(let [env, webHost] of ctx.app.config.envToHost) { options[`/web/${env}/`] = { target: webHost, changeOrigin: true, secure: true, - pathRewrite: function(path) { + pathRewrite: function(path: string) { console.log('proxy', path, path.replace(`/web/${env}/`, '/web/')) return path.replace(`/web/${env}/`, '/web/') } @@ -37,7 +48,7 @@ module.exports = () => { } if(!!ctx.app.config.sidToHost.get(sid)) { options[url] = { - target: ctx.app.config.sidToHost.get(sid), + target: ctx.app.config.sidToHost.get(sid) as string, changeOrigin: true, secure: true, headers: { "is-proxy": "true" } @@ -50,20 +61,20 @@ module.exports = () => { }; }; - async function getNewHost(ctx) { + async function getNewHost(ctx: Context) { let envToHost = ctx.app.config.envToHost||new Map(); let sidToHost = new Map(); let servers = await ServerlistModel.getAllServerList(); for(let { id, env, isMain } of servers) { let webHost = envToHost.get(env); - sidToHost.set(id.toString(), webHost); - if(isMain) sidToHost.set('main', webHost); + sidToHost.set(id.toString(), webHost as string); + if(isMain) sidToHost.set('main', webHost as string); } - if(!sidToHost.has('main') && servers.length > 0) sidToHost.set('main', envToHost.get(servers[0].env)); + if(!sidToHost.has('main') && servers.length > 0) sidToHost.set('main', envToHost.get(servers[0].env) as string); ctx.app.config.sidToHost = sidToHost; } - function getProxyUrl(url: string) { + function getProxyUrl(url: string): string | undefined { const urls = [ '/cb/treatusername', '/cb/treatguildname', @@ -80,9 +91,10 @@ module.exports = () => { return str; } } + return undefined; } - function getServerId(url: string, ctx: any) { + function getServerId(url: string, ctx: Context): string { switch(url) { case '/cb/treatusername': case '/cb/treatguildname': @@ -99,5 +111,7 @@ module.exports = () => { return ctx.query? ctx.query.dsid.toString(): ctx.request.body.dsid.toString(); case '/cb/getrolebyuid': return 'main'; + default: + return 'main'; } } \ No newline at end of file diff --git a/web-server/app/middleware/tokenParser.ts b/web-server/app/middleware/tokenParser.ts index 2eb4a915e..0f3166862 100644 --- a/web-server/app/middleware/tokenParser.ts +++ b/web-server/app/middleware/tokenParser.ts @@ -1,8 +1,9 @@ import { STATUS } from '@consts'; import { UserModel } from '@db/User'; +import { Context } from 'egg'; module.exports = () => { - return async function tokenParser(ctx, next) { + return async function tokenParser(ctx: Context, next: () => Promise) { if (!ctx.request.body || !ctx.request.body.token) { console.error('token not found'); diff --git a/web-server/app/service/Auth.ts b/web-server/app/service/Auth.ts index 1a2abded1..08496f686 100644 --- a/web-server/app/service/Auth.ts +++ b/web-server/app/service/Auth.ts @@ -1,23 +1,23 @@ -import { COUNTER, DEFAULT_LV, ADULT_AGE, GUEST_MAX_TIME, BLOCK_TYPE, DEBUG_MAGIC_WORD } from '@consts'; -import { RoleModel, WarStar } from '@db/Role'; -import { UserModel, UserType } from '@db/User'; -import { STATUS, GET_SMS_TYPE, ADDICTION_PREVENTION_CODE } from '@consts'; -import { smsModel } from '@db/Sms'; +import { COUNTER, DEFAULT_LV, ADULT_AGE, GUEST_MAX_TIME, BLOCK_TYPE, DEBUG_MAGIC_WORD } from '../../../shared/consts'; +import { RoleModel, WarStar } from '../../../shared/db/Role'; +import { UserModel, UserType } from '../../../shared/db/User'; +import { STATUS, GET_SMS_TYPE, ADDICTION_PREVENTION_CODE } from '../../../shared/consts'; +import { smsModel } from '../../../shared/db/Sms'; import { Service } from 'egg'; -import Counter from '@db/Counter'; -import { gameData, getExpByLv } from '../pubUtils/data'; +import Counter from '../../../shared/db/Counter'; +import { gameData, getExpByLv } from '../../../shared/pubUtils/data'; import { isString } from 'underscore'; -import { getAge, nowSeconds } from '../pubUtils/timeUtil'; -import { isDevelopEnv, resResult } from '../pubUtils/util'; -import { checkTeeanAgerTime } from '../pubUtils/authenticateUtil'; -// import { authenticate } from '../pubUtils/httpUtil'; -import { getChannelId, loginValidata } from '../pubUtils/sdkUtil'; -import { LoginValidateData37 } from 'app/domain/sdk'; -import { ServerlistModel } from '@db/Serverlist'; -import { DicWar } from '../pubUtils/dictionary/DicWar'; -import { RScriptRecordModel } from '@db/RScriptRecord'; -import { deletRole } from '../pubUtils/roleUtil'; +import { getAge, nowSeconds } from '../../../shared/pubUtils/timeUtil'; +import { isDevelopEnv, resResult } from '../../../shared/pubUtils/util'; +import { checkTeeanAgerTime } from '../../../shared/pubUtils/authenticateUtil'; +// import { authenticate } from '../../../shared/pubUtils/httpUtil'; +import { getChannelId, loginValidata } from '../../../shared/pubUtils/sdkUtil'; +import { LoginValidateData37 } from '../../../shared/domain/sdk'; +import { ServerlistModel } from '../../../shared/db/Serverlist'; +import { DicWar } from '../../../shared/pubUtils/dictionary/DicWar'; +import { RScriptRecordModel } from '../../../shared/db/RScriptRecord'; +import { deletRole } from '../../../shared/pubUtils/roleUtil'; /** * Test Service @@ -51,7 +51,7 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } - if(user && user.userCode) { + if (user && user.userCode) { ctx.service.utils.checkOnlineUser(user.userCode); } let param = this.getReturnParam(user, null); @@ -74,7 +74,7 @@ export default class Auth extends Service { if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(user.tel, getuiCID); } - if(user && user.userCode) { + if (user && user.userCode) { ctx.service.utils.checkOnlineUser(user.userCode); } let param = this.getReturnParam(user, oldUser.deviceId); @@ -113,7 +113,7 @@ export default class Auth extends Service { } } - public checkTelNo(telNo) { + public checkTelNo(telNo: string) { if (!isString(telNo)) { return { status: 1, resResult: resResult(STATUS.WRONG_PARMS) }; } @@ -123,7 +123,9 @@ export default class Auth extends Service { return { status: 0 }; } - async sendSmsCodeByGuodu(tel, code) { + async sendSmsCodeByGuodu(tel: string, code: string) { + console.log("准备发送短信..."); + const ctx = this.ctx; const url = `http://221.179.172.68:8000/QxtSms/QxtFirewall?OperID=bantu3&OperPass=c8XcTffG&DesMobile=${tel}&Content=${encodeURIComponent(`【同人游戏】验证码${code},您正在登录赵云传,若非本人操作,请勿泄露`)}&Content_Code=1`; const result = await ctx.curl(url, { @@ -132,7 +134,7 @@ export default class Auth extends Service { return result.data; } - testLimit(sms, interval) { + testLimit(sms: any, interval: number) { if (sms.updateTime.getTime() > Date.now() - interval) { return true; } @@ -146,6 +148,7 @@ export default class Auth extends Service { public async getSms(type: number, tel: string) { const ctx = this.ctx; + console.log("准备发送短信..."); const telVerify = this.checkTelNo(tel); if (telVerify.status !== 0) { @@ -158,8 +161,16 @@ export default class Auth extends Service { return ctx.service.utils.resResult(STATUS.TEL_HAS_USED); } } + console.log(2, tel); + + let sms: any; + try { + sms = await smsModel.findByTel(tel, false); + } catch (error) { + console.log(error); + } + console.log(3, sms); - const sms = await smsModel.findByTel(tel, false); if (sms) { if (await sms.timeLimit(10000)) { return this.ctx.service.utils.resResult(STATUS.SMS_IN_60S); @@ -168,7 +179,7 @@ export default class Auth extends Service { return this.ctx.service.utils.resResult(STATUS.SMS_CNT_LIMIT); } } - + console.log(sms); let code = ''; if (sms && (!sms.used || sms.isFixed)) { code = sms.code; @@ -176,6 +187,7 @@ export default class Auth extends Service { code = this.ctx.service.utils.generateNum(6); } + const smsResult = await this.sendSmsCodeByGuodu(tel, code); console.log(smsResult); await smsModel.updateByTel(tel, code, false, new Date(), sms?.hasSendToday() ? sms.countToday + 1 : 1); @@ -225,11 +237,11 @@ export default class Auth extends Service { // 用户注册登录 const token = ctx.service.utils.generateStr(256); - const {user, deviceId: oldDeviceId} = await UserModel.createOrUpdate(false, tel, token, platform, pkgName, serverType, deviceId, ctx.clientIp); + const { user, deviceId: oldDeviceId } = await UserModel.createOrUpdate(false, tel, token, platform, pkgName, serverType, deviceId, ctx.clientIp); if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } - if(user && user.userCode) { + if (user && user.userCode) { ctx.service.utils.checkOnlineUser(user.userCode); } let param = this.getReturnParam(user, oldDeviceId); @@ -289,12 +301,12 @@ export default class Auth extends Service { // 用户注册登录 const token = ctx.service.utils.generateStr(256); - const {user, deviceId: oldDeviceId} = await UserModel.checkPass(tel, pw, token, deviceId); + const { user, deviceId: oldDeviceId } = await UserModel.checkPass(tel, pw, token, deviceId); if (!user) return ctx.service.utils.resResult(STATUS.PASSWORD_ERR); if (getuiCID) {//更新个推cid await UserModel.updateGetuiCID(tel, getuiCID); } - if(user && user.userCode) { + if (user && user.userCode) { ctx.service.utils.checkOnlineUser(user.userCode); } let param = this.getReturnParam(user, oldDeviceId); @@ -305,14 +317,14 @@ export default class Auth extends Service { const ctx = this.ctx; const { uid } = ctx; let canLogin = await this.ctx.service.utils.validateCanLogin(); - if(!canLogin) return this.ctx.service.utils.resResult(STATUS.ONLINE_USER_MAX); + if (!canLogin) return this.ctx.service.utils.resResult(STATUS.ONLINE_USER_MAX); const role = await RoleModel.findByUid(uid, serverId, 'roleId blockType +closeTime'); if (role) { - if(role.blockType == BLOCK_TYPE.BLOCK) { + if (role.blockType == BLOCK_TYPE.BLOCK) { return ctx.service.utils.resResult(STATUS.BLOCKED); } - if(role.closeTime > 0 && role.closeTime < nowSeconds()) { + if (role.closeTime > 0 && role.closeTime < nowSeconds()) { return ctx.service.utils.resResult(STATUS.ROLE_CLOSED); } return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId }); @@ -325,12 +337,12 @@ export default class Auth extends Service { const ctx = this.ctx; const { uid } = ctx; const exist = await RoleModel.exists({ 'userInfo.uid': uid, serverId }); - if (exist === true) { + if (exist) { return ctx.service.utils.resResult(STATUS.ROLE_EXIST); } const server = await ServerlistModel.findByServerId(serverId); - if(!server) return ctx.service.utils.resResult(STATUS.SERVER_NOT_FOUND); - if(nowSeconds() > server.stopRegisterTime) return ctx.service.utils.resResult(STATUS.SERVER_STOP_REGISTER); + if (!server) return ctx.service.utils.resResult(STATUS.SERVER_NOT_FOUND); + if (nowSeconds() > server.stopRegisterTime) return ctx.service.utils.resResult(STATUS.SERVER_STOP_REGISTER); const roleId = ctx.service.utils.genCode(10); const code = ctx.service.utils.genCode(6); @@ -338,7 +350,7 @@ export default class Auth extends Service { const role = await RoleModel.createRole(uid, serverId, { roleId, code, roleName: "默认玩家名", seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1) || { sum: 0 }).sum || 0 }, distinctId); if (role) { - if(server.isReview) { // 审核服跳关卡 + if (server.isReview) { // 审核服跳关卡 await this.skipPrologueWhenReview(roleId); } return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId }); @@ -348,12 +360,12 @@ export default class Auth extends Service { private async skipPrologueWhenReview(roleId: string) { const fromWarId = 101, toWarId = 103; - let warStars: WarStar[] = []; + let warStars: WarStar[] = []; let insertParams: DicWar[] = []; - for(let i = fromWarId; i <= toWarId; i++) { + for (let i = fromWarId; i <= toWarId; i++) { let dicWar = gameData.war.get(i); insertParams.push(dicWar); - if(i < toWarId) warStars.push({ id: dicWar.war_id, warType: dicWar.warType, star: 0, stars: [] }); + if (i < toWarId) warStars.push({ id: dicWar.war_id, warType: dicWar.warType, star: 0, stars: [] }); } await RScriptRecordModel.insertScripts(roleId, insertParams, [toWarId]); await RoleModel.updateRoleInfo(roleId, { warStar: warStars, mainWarId: toWarId - 1 }) @@ -432,22 +444,22 @@ export default class Auth extends Service { channelType: string, pst: string, clientId: string, deviceId: string, platform: string, platformAppid: string, childGameId: number, pkgName: string, serverType: string, getuiCID: string, distinctId: string }) { const { channelType, pst, clientId, deviceId, platform, platformAppid, childGameId, pkgName, serverType, getuiCID } = params; - + const ctx = this.ctx; let requestResult = await loginValidata(channelType, { clientId, pst, platform, platformAppid, childGameId }); - if(!requestResult) return this.ctx.service.utils.resResult(STATUS.CHANNEL_ERR); + if (!requestResult) return this.ctx.service.utils.resResult(STATUS.CHANNEL_ERR); - if(requestResult.code != 1) { + if (requestResult.code != 1) { return this.ctx.service.utils.resResult(STATUS.VALIDATE_ERR, requestResult); } let channelId = getChannelId(channelType, requestResult.data.uid); const token = ctx.service.utils.generateStr(256); let { user, deviceId: oldDeviceId } = await UserModel.createOrUpdateChannelUser(channelId, channelType, { - ...requestResult.data, childGameId:`${childGameId}`, platformAppid + ...requestResult.data, childGameId: `${childGameId}`, platformAppid }, token, platform, pkgName, serverType, deviceId, ctx.clientIp); - if(user && user.userCode) { + if (user && user.userCode) { ctx.service.utils.checkOnlineUser(user.userCode); } @@ -455,7 +467,7 @@ export default class Auth extends Service { await UserModel.updateGetuiCIDByChannel(channelId, getuiCID); } let channelInfo: any = {}; - if(channelType == '37') { + if (channelType == '37') { channelInfo.uid = (user.channelInfo).uid; } return ctx.service.utils.resResult(STATUS.SUCCESS, { @@ -468,36 +480,36 @@ export default class Auth extends Service { }); } - + public async deleteRole(roleId: string, magicWord: string) { console.log('enter Auth deleteRole'); const ctx = this.ctx; - if(magicWord != DEBUG_MAGIC_WORD) { + if (magicWord != DEBUG_MAGIC_WORD) { return ctx.service.utils.resResult(STATUS.WRONG_PARMS); } - if(!isDevelopEnv(ctx.app.config.realEnv)) { + if (!isDevelopEnv(ctx.app.config.realEnv)) { return ctx.service.utils.resResult(STATUS.DEVELOP_ONLY); } let result = await deletRole(roleId); - if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); + if (!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS); return ctx.service.utils.resResult(STATUS.SUCCESS); } - + public async closeAccount(roleId: string) { const ctx = this.ctx; let role = await RoleModel.findByRoleId(roleId, '+closeTime +cancelCloseTime userInfo'); - if(!role || role.userInfo.uid != ctx.uid ) return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND); - if(role.cancelCloseTime > 0 && role.cancelCloseTime + 24 * 60 * 60 > nowSeconds() ) + if (!role || role.userInfo.uid != ctx.uid) return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND); + if (role.cancelCloseTime > 0 && role.cancelCloseTime + 24 * 60 * 60 > nowSeconds()) return ctx.service.utils.resResult(STATUS.ROLE_CLOSE_COOL_DOWN, `注销冷却中,请${this.getCdTimeStr(role.cancelCloseTime)}后再试`); - if(role.closeTime > 0) return ctx.service.utils.resResult(STATUS.ROLE_CLOSED); + if (role.closeTime > 0) return ctx.service.utils.resResult(STATUS.ROLE_CLOSED); role = await RoleModel.closeAccount(roleId, nowSeconds() + 15 * 24 * 60 * 60); return ctx.service.utils.resResult(STATUS.SUCCESS, { closeTime: role.closeTime }); } private getCdTimeStr(cancelCloseTime: number) { let gap = cancelCloseTime + 24 * 60 * 60 - nowSeconds(); - let h = Math.floor(gap/60/60); - let m = Math.floor((gap - h * 60 * 60 )/60); + let h = Math.floor(gap / 60 / 60); + let m = Math.floor((gap - h * 60 * 60) / 60); let s = gap - h * 60 * 60 - m * 60; return `${h}小时${m}分${s}秒` } @@ -505,10 +517,10 @@ export default class Auth extends Service { public async cancelCloseAccount(roleId: string) { const ctx = this.ctx; let role = await RoleModel.findByRoleId(roleId, '+cancelCloseTime userInfo'); - if(!role || role.userInfo.uid != ctx.uid ) return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND); + if (!role || role.userInfo.uid != ctx.uid) return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND); role = await RoleModel.cancelCloseAccount(roleId, nowSeconds()); - if(!role) return ctx.service.utils.resResult(STATUS.ROLE_CLOSE_TIME_OVER); + if (!role) return ctx.service.utils.resResult(STATUS.ROLE_CLOSE_TIME_OVER); return ctx.service.utils.resResult(STATUS.SUCCESS, { closeTime: role.closeTime }); } diff --git a/web-server/app/service/Sdk.ts b/web-server/app/service/Sdk.ts index ee7ae9d7d..2321a4bb1 100644 --- a/web-server/app/service/Sdk.ts +++ b/web-server/app/service/Sdk.ts @@ -1,24 +1,24 @@ import { Service } from 'egg'; -import { REDIS_KEY, PAY_37_CALLBACK_CODE, SDK_37_CONST, ORDER_STATE, SDK_37_TREAT_CODE, SERVER_STATUS, SDK_37_REFUND_CODE, SDK_37_ACTIVITY_CODE, PUBLIC_ACCOUNT_GIFT, GIFT_GENERATE_TYPE, GIFT_TYPE } from '@consts'; -import { GetGuildInfoByUserParam, GetRoleByServerParam, GetRoleByUidParam, GetServerAndUidParam, GetServerListParam, GetServerParam, GuildNameCallBackParam, IOSRefundParam, PayCallback37Data, RoleNameCallBackParam, SendGiftCodeParam } from '../domain/sdk'; +import { REDIS_KEY, PAY_37_CALLBACK_CODE, SDK_37_CONST, ORDER_STATE, SDK_37_TREAT_CODE, SERVER_STATUS, SDK_37_REFUND_CODE, SDK_37_ACTIVITY_CODE, PUBLIC_ACCOUNT_GIFT, GIFT_GENERATE_TYPE, GIFT_TYPE } from '../../../shared/consts'; +import { GetGuildInfoByUserParam, GetRoleByServerParam, GetRoleByUidParam, GetServerAndUidParam, GetServerListParam, GetServerParam, GuildNameCallBackParam, IOSRefundParam, PayCallback37Data, RoleNameCallBackParam, SendGiftCodeParam } from '../../../shared/domain/sdk'; import { RedisClient } from 'redis'; -import { checkParamPrice, get37GetServerMd5Sign, get37Md5SignA, get37Md5SignB, getChannelId, getRedisSubChannel, md5 } from '../pubUtils/sdkUtil'; -import { UserOrderModel } from '@db/UserOrder'; -import { nowSeconds } from 'app/pubUtils/timeUtil'; -import { RoleModel } from '@db/Role'; -import { gameData } from 'app/pubUtils/data'; -import { resResult } from 'app/pubUtils/util'; -import { UserModel } from '@db/User'; -import { UserGuildModel } from '@db/UserGuild'; -import { GuildModel } from '@db/Guild'; -import { ServerlistModel } from '@db/Serverlist'; +import { checkParamPrice, get37GetServerMd5Sign, get37Md5SignA, get37Md5SignB, getChannelId, getRedisSubChannel, md5 } from '../../../shared/pubUtils/sdkUtil'; +import { UserOrderModel } from '../../../shared/db/UserOrder'; +import { nowSeconds } from '../../../shared/pubUtils/timeUtil'; +import { RoleModel } from '../../../shared/db/Role'; +import { gameData } from '../../../shared/pubUtils/data'; +import { resResult } from '../../../shared/pubUtils/util'; +import { UserModel } from '../../../shared/db/User'; +import { UserGuildModel } from '../../../shared/db/UserGuild'; +import { GuildModel } from '../../../shared/db/Guild'; +import { ServerlistModel } from '../../../shared/db/Serverlist'; import moment = require('moment'); -import { RegionModel } from '@db/Region'; -import { ActivityPublicAccountCodeModel } from '@db/ActivityPublicAccountCode'; -import { GiftCodeDetailModel } from '@db/GiftCodeDetail'; -import { GiftCodeModel } from '@db/GiftCode'; -import { UserGiftCodeDetailModel } from '@db/UserGiftCodeDetail'; +import { RegionModel } from '../../../shared/db/Region'; +import { ActivityPublicAccountCodeModel } from '../../../shared/db/ActivityPublicAccountCode'; +import { GiftCodeDetailModel } from '../../../shared/db/GiftCodeDetail'; +import { GiftCodeModel } from '../../../shared/db/GiftCode'; +import { UserGiftCodeDetailModel } from '../../../shared/db/UserGiftCodeDetail'; /** * Test Service @@ -79,9 +79,9 @@ export default class Sdk extends Service { } ctx.service.utils.log('DEBUG', `[${ctx.request.url}] [${ctx.logcode}] pay37Callback save order check ok`); - let redisClient: RedisClient = app.context.redisClient; + let redisClient: RedisClient = (app.context as any).redisClient; let name = getRedisSubChannel(REDIS_KEY.PAY_CHANNEL, app.config.env); - let result = await redisClient.publishAsync(name, JSON.stringify(params)); + let result = await (redisClient as any).publishAsync(name, JSON.stringify(params)); if(result == 0) { return ctx.service.utils.resResult(PAY_37_CALLBACK_CODE.SERVER_IS_BUSY, ''); } @@ -140,7 +140,7 @@ export default class Sdk extends Service { // let redisClient: RedisClient = app.context.redisClient; // let name = getRedisSubChannel(REDIS_KEY.PAY_CHANNEL, app.config.env); - // let result = await redisClient.publishAsync(name, JSON.stringify(params)); + // let result = await (redisClient as any).publishAsync(name, JSON.stringify(params)); // if(result == 0) { // return ctx.service.utils.resResult(PAY_IOS_37_CALLBACK_CODE.SERVER_IS_BUSY, ''); // } @@ -193,9 +193,9 @@ export default class Sdk extends Service { } console.log('*****refundIOSCallback save order check ok') - let redisClient: RedisClient = app.context.redisClient; + let redisClient: RedisClient = (app.context as any).redisClient; let name = getRedisSubChannel(REDIS_KEY.REFUND_CHANNEL, app.config.env); - let result = await redisClient.publishAsync(name, JSON.stringify(params)); + let result = await (redisClient as any).publishAsync(name, JSON.stringify(params)); if(result == 0) { return ctx.service.utils.resResult(SDK_37_REFUND_CODE.FAIL, ''); } @@ -262,9 +262,9 @@ export default class Sdk extends Service { } // 2. redis发布 - let redisClient: RedisClient = app.context.redisClient; + let redisClient: RedisClient = (app.context as any).redisClient; let name = getRedisSubChannel(REDIS_KEY.TREAT_ROLE_CHANNEL, app.config.env); - let result = await redisClient.publishAsync(name, role.roleId); + let result = await (redisClient as any).publishAsync(name, role.roleId); if(result == 0) { console.error('用户名违规处理, 未发布到订阅频道'); return SDK_37_TREAT_CODE.ERR.code; @@ -288,10 +288,10 @@ export default class Sdk extends Service { } // 2. redis发布 - let redisClient: RedisClient = app.context.redisClient; + let redisClient: RedisClient = (app.context as any).redisClient; let name = getRedisSubChannel(REDIS_KEY.TREAT_GUILD_CHANNEL, app.config.env); let content = JSON.stringify({ code: guild.code, serverId: params.sid, type: params.type }); - let result = await redisClient.publishAsync(name, content); + let result = await (redisClient as any).publishAsync(name, content); if(result == 0) { return SDK_37_TREAT_CODE.ERR.code; } @@ -375,7 +375,7 @@ export default class Sdk extends Service { } public reportTAEventWithDistinctId(distinctId: string, eventName: string, properties: any, ip: string) { - let ta = this.app.context.ta; + let ta = (this.app.context as any).ta; if(!ta) return let event = { // 账号 ID (可选) @@ -390,7 +390,7 @@ export default class Sdk extends Service { ip: ip, // 事件属性 (可选) properties, - callback(err) { + callback(err: any) { console.log('*****测试接入事件', err) } @@ -399,7 +399,7 @@ export default class Sdk extends Service { } public reportTAEventWithRoleIdAndDistinctId(roleId: string, distinctId: string, eventName: string, properties: any, ip?: string) { - let ta = this.app.context.ta; + let ta = (this.app.context as any).ta; if(!ta) return let event = { // 账号 ID (可选) @@ -414,7 +414,7 @@ export default class Sdk extends Service { ip: ip, // 事件属性 (可选) properties, - callback(err) { + callback(err: any) { console.log('*****测试接入事件', err) } @@ -484,7 +484,7 @@ export default class Sdk extends Service { await GiftCodeDetailModel.increaseUsedNum(giftCodeDetail.code); await GiftCodeModel.increaseUsedNum(giftCode.id); - await ctx.service.utils.pushGiftCodeChannel(role.roleId, giftCode.id); + await ctx.service.utils.pushGiftCodeChannel(String(role.roleId), String(giftCode.id)); } return resResult(SDK_37_ACTIVITY_CODE.SUCCESS, []); @@ -564,8 +564,8 @@ export default class Sdk extends Service { let user = await UserModel.findUserByChannel(channelId); if(!user) return resResult(SDK_37_ACTIVITY_CODE.ROLE_NOT_FOUND); - let redisClient: RedisClient = this.ctx.app.context.redisClient; - let servers = await redisClient.hgetallAsync(REDIS_KEY.SERVER); + let redisClient: RedisClient = (this.ctx.app.context as any).redisClient; + let servers = await (redisClient as any).hgetallAsync(REDIS_KEY.SERVER); let roles = await RoleModel.findAllByUid(user.uid); let result = roles .filter(role => !role.closeTime || role.closeTime > nowSeconds()) @@ -661,7 +661,7 @@ export default class Sdk extends Service { } } catch(e) { console.error(e); - return { state: 0, data: null, msg: SDK_37_ACTIVITY_CODE.INTERNAL_ERR }; + return { state: 0, data: null as any, msg: SDK_37_ACTIVITY_CODE.INTERNAL_ERR }; } } diff --git a/web-server/app/service/TurboCore.ts b/web-server/app/service/TurboCore.ts index 03d0926c0..fc460e6c2 100644 --- a/web-server/app/service/TurboCore.ts +++ b/web-server/app/service/TurboCore.ts @@ -57,7 +57,7 @@ export default class TurboCore extends Service { * @param params 参数列表 * @param secret 密钥 */ - private getTurboSign(params, secret) { + private getTurboSign(params: any, secret: string) { const paramsString = this.joinParamsStr(params); let stringToSign = paramsString; @@ -74,7 +74,7 @@ export default class TurboCore extends Service { * 将参数组合成字符串 * @param params 参数列表 */ - private joinParamsStr(params) { + private joinParamsStr(params: any) { const signString = Object.keys(params).filter(function(key) { return params[key] !== undefined && params[key] !== '' && [ 'pfx', 'partner_key', 'sign', 'key' ].indexOf(key) < 0; }).sort() diff --git a/web-server/app/service/Update.ts b/web-server/app/service/Update.ts index 680d1f6ae..42aa7b177 100644 --- a/web-server/app/service/Update.ts +++ b/web-server/app/service/Update.ts @@ -1,5 +1,5 @@ -import { STATUS, } from '@consts'; -import { RegionType } from '@db/Region'; +import { STATUS, } from '../../../shared/consts'; +import { RegionType } from '../../../shared/db/Region'; import { Service } from 'egg'; // let fs = require("fs"); diff --git a/web-server/app/service/Utils.ts b/web-server/app/service/Utils.ts index 13840f840..e546e8a95 100644 --- a/web-server/app/service/Utils.ts +++ b/web-server/app/service/Utils.ts @@ -1,12 +1,12 @@ import { Service } from 'egg'; -import { resResult as pubResult } from '../pubUtils/util'; -import { gameData } from 'app/pubUtils/data'; +import { resResult as pubResult } from '../../../shared/pubUtils/util'; +import { gameData } from '../../../shared/pubUtils/data'; import { RedisClient } from 'redis'; -import { REDIS_KEY, SERVER_STATUS } from '@consts'; -import { getRedisSubChannel } from 'app/pubUtils/sdkUtil'; -import { ServerlistType } from '@db/Serverlist'; -import { nowSeconds } from 'app/pubUtils/timeUtil'; -import { checkWhiteList } from 'app/pubUtils/sysUtil'; +import { REDIS_KEY, SERVER_STATUS } from '../../../shared/consts'; +import { getRedisSubChannel } from '../../../shared/pubUtils/sdkUtil'; +import { ServerlistType } from '../../../shared/db/Serverlist'; +import { nowSeconds } from '../../../shared/pubUtils/timeUtil'; +import { checkWhiteList } from '../../../shared/pubUtils/sysUtil'; const csprng = require('csprng'); /** * Utils Service @@ -21,7 +21,7 @@ export default class Utils extends Service { return `${csprng(len, radix)}`; } - public genCode(len) { + public genCode(len: number) { const chars = '123456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijklmnopqrstuvwxyz'; const charArr = chars.split(''); let code = ''; @@ -43,7 +43,7 @@ export default class Utils extends Service { return code; } - public resResult(status: {code: number, simStr: string}, data?, customMsg?: string) { + public resResult(status: {code: number, simStr: string}, data?: any, customMsg?: string) { return pubResult(status, data, customMsg); } @@ -62,18 +62,18 @@ export default class Utils extends Service { } public async checkOnlineUser(userCode: string) { - let redisClient: RedisClient = this.ctx.app.context.redisClient; - let onlineRoleId = await redisClient.hgetAsync(REDIS_KEY.USER_CODE, userCode); + let redisClient: RedisClient = (this.ctx.app.context as any).redisClient; + let onlineRoleId = await (redisClient as any).hgetAsync(REDIS_KEY.USER_CODE, userCode); let isWhiteList = await checkWhiteList(this.ctx.app.config.realEnv, this.ctx.clientIp, this.ctx.uid); if (!isWhiteList && !!onlineRoleId) { // 多地登陆踢下线 - let str = await redisClient.hgetAsync(REDIS_KEY.ONLINE_USERS, onlineRoleId); + let str = await (redisClient as any).hgetAsync(REDIS_KEY.ONLINE_USERS, onlineRoleId); if(str) { try { let [,sid] = str?.split('|')??[]; let name = getRedisSubChannel(REDIS_KEY.USER_CHANNEL, this.ctx.app.config.env); - await redisClient.publishAsync(name, `${sid}|${onlineRoleId}`); + await (redisClient as any).publishAsync(name, `${sid}|${onlineRoleId}`); } catch(e) { console.error('checkOnlineUser', e); } @@ -82,22 +82,22 @@ export default class Utils extends Service { } public async pushPubAccountGiftChannel(activityId: number, userCode: string, channelId: string) { - let redisClient: RedisClient = this.ctx.app.context.redisClient; + let redisClient: RedisClient = (this.ctx.app.context as any).redisClient; try { let name = getRedisSubChannel(REDIS_KEY.PUBLIC_ACCOUNT_GIFT, this.ctx.app.config.env); - await redisClient.publishAsync(name, `${activityId}|${userCode}|${channelId}`); + await (redisClient as any).publishAsync(name, `${activityId}|${userCode}|${channelId}`); } catch(e) { console.error('pushPubAccountGiftChannel', e); } } public async pushGiftCodeChannel(roleId: string, giftCode: string) { - let redisClient: RedisClient = this.ctx.app.context.redisClient; + let redisClient: RedisClient = (this.ctx.app.context as any).redisClient; try { let name = getRedisSubChannel(REDIS_KEY.SEND_GIFT_CODE, this.ctx.app.config.env); - await redisClient.publishAsync(name, `${roleId}|${giftCode}`); + await (redisClient as any).publishAsync(name, `${roleId}|${giftCode}`); } catch(e) { console.error('pushPubAccountGiftChannel', e); } @@ -109,9 +109,9 @@ export default class Utils extends Service { if(gameData.serverConst.CLOSE_LOGIN == 1) return false; if(gameData.serverConst.CLOSE_LOGIN_WHEN_ONLINE_MAX) { - let redisClient: RedisClient = this.ctx.app.context.redisClient; - let count = await redisClient.hlenAsync(REDIS_KEY.ONLINE_USERS); - const Max = await redisClient.getAsync(REDIS_KEY.MAX_ONLINE_USERS); + let redisClient: RedisClient = (this.ctx.app.context as any).redisClient; + let count = await (redisClient as any).hlenAsync(REDIS_KEY.ONLINE_USERS); + const Max = await (redisClient as any).getAsync(REDIS_KEY.MAX_ONLINE_USERS); console.log('validateCanLogin:', count, Max); if(Max && count >= parseInt(Max)) { @@ -128,11 +128,28 @@ export default class Utils extends Service { // 比较以 . 分隔的版本号。返回 0 则版本号相等,返回正数则 versionA 大,返回负数则 versionB 大 public compareVersion (versionA: string, versionB: string) { + if (!versionA && !versionB) { + return 0; + } + if (!versionA) { + return -1; + } + if (!versionB) { + return 1; + } + var vA = versionA.split('.'); var vB = versionB.split('.'); for (var i = 0; i < vA.length; ++i) { var a = parseInt(vA[i]); var b = parseInt(vB[i] || '0'); + if (isNaN(a) || isNaN(b)) { + if (a === b) { + continue; + } else { + return isNaN(a) ? -1 : 1; + } + } if (a === b) { } else { diff --git a/web-server/app/service/Wjx.ts b/web-server/app/service/Wjx.ts index 6711ad1af..36391d719 100644 --- a/web-server/app/service/Wjx.ts +++ b/web-server/app/service/Wjx.ts @@ -1,7 +1,7 @@ import { SurveyRecModel } from '@db/SurveyRec'; import { SurveyModel } from '@db/Survery'; -import { checkWjxSign, getRedisSubChannel } from 'app/pubUtils/sdkUtil'; +import { checkWjxSign, getRedisSubChannel } from '@pubUtils/sdkUtil'; import { Service } from 'egg'; import { RedisClient } from 'redis'; import { REDIS_KEY } from '@consts'; @@ -33,7 +33,7 @@ export default class Sdk extends Service { rec = await SurveyRecModel.createSurveyRec(roleId, params.activity, params.index, JSON.stringify(params)); // 3. 发邮件 - let redisClient: RedisClient = this.app.context.redisClient; + let redisClient: RedisClient = (this.app.context as any).redisClient; let name = getRedisSubChannel(REDIS_KEY.SURVEY_CHANNEL, this.app.config.env); let result = await redisClient.publishAsync(name, rec.code); if(result == 0) { diff --git a/web-server/appveyor.yml b/web-server/appveyor.yml index c274b7d35..5fd5337de 100644 --- a/web-server/appveyor.yml +++ b/web-server/appveyor.yml @@ -4,7 +4,7 @@ environment: install: - ps: Install-Product node $env:nodejs_version - - npm i npminstall && node_modules\.bin\npminstall + - npm i npminstall@5 && node_modules\.bin\npminstall test_script: - node --version diff --git a/web-server/config/config.alpha.ts b/web-server/config/config.alpha.ts index 6903a6f26..5334dce07 100644 --- a/web-server/config/config.alpha.ts +++ b/web-server/config/config.alpha.ts @@ -7,7 +7,7 @@ export default (appInfo: EggAppInfo) => { config.middleware = [ 'parmsDecode', 'getIp', 'proxy' ]; config.mongoose = { url: 'mongodb://dbop:zyzDev2021@dds-8vb5c74ba4263da41.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5c74ba4263da42.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-506991391', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { diff --git a/web-server/config/config.default.ts b/web-server/config/config.default.ts index 45880f812..3a7437fd3 100644 --- a/web-server/config/config.default.ts +++ b/web-server/config/config.default.ts @@ -2,7 +2,7 @@ import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg'; const path = require('path'); import { sshHost } from './sshHost'; -export default (appInfo: EggAppInfo) => { +export default (appInfo: EggAppInfo): PowerPartial => { const config = {} as PowerPartial; // override config from framework / plugin @@ -23,11 +23,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzGm2021@dds-8vb9964bb4cc7f241.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb9964bb4cc7f242.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?replicaSet=mgset-507933150', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com', // 内网 @@ -64,7 +64,7 @@ export default (appInfo: EggAppInfo) => { config.customLogger = { linkLogger: { file: path.join(appInfo.root, 'logs/web-server/link-log.log'), - formatter(meta) { + formatter(meta: any) { return `[${meta.level}] [${meta.date}] ${meta.message}`; }, }, diff --git a/web-server/config/config.dev.ts b/web-server/config/config.dev.ts index a9aabbc42..ca9e0d763 100644 --- a/web-server/config/config.dev.ts +++ b/web-server/config/config.dev.ts @@ -6,7 +6,7 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzDev2022@dds-8vbc0bc9420028041.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbc0bc9420028042.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-508590620', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb418l8kkju9sis8k.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.local.ts b/web-server/config/config.local.ts index 9a543f208..34218f9e8 100644 --- a/web-server/config/config.local.ts +++ b/web-server/config/config.local.ts @@ -5,16 +5,14 @@ export default (appInfo: EggAppInfo) => { const config = {} as PowerPartial; config.mongoose = { - url: 'mongodb://127.0.0.1/zyz', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + url: 'mongodb://192.168.1.99:27017/zyz', // 内网 }; config.gmmongoose = { - url: 'mongodb://127.0.0.1:27017/zyzgm', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + url: 'mongodb://192.168.1.99:27017/zyzgm', // 内网 }; config.redis = { - url: '127.0.0.1', // 内网 - pw: '' + url: '192.168.1.99', // 内网 + pw: 'Homzy@123' }; config.decodeParm = true; diff --git a/web-server/config/config.sq1.ts b/web-server/config/config.sq1.ts index d377846ca..2dde1db71 100644 --- a/web-server/config/config.sq1.ts +++ b/web-server/config/config.sq1.ts @@ -6,11 +6,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzSQ2021@dds-8vb7d5060bb271d41.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb7d5060bb271d42.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb7d5060bb271d43.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-508112745', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb7l1s8ne4vm6v6x6.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.sq2.ts b/web-server/config/config.sq2.ts index 8428c37e4..1f2a8ef4e 100644 --- a/web-server/config/config.sq2.ts +++ b/web-server/config/config.sq2.ts @@ -7,11 +7,11 @@ export default (appInfo: EggAppInfo) => { config.middleware = [ 'parmsDecode', 'getIp', 'proxy' ]; config.mongoose = { url: 'mongodb://dbop:zyzSQ2021@dds-8vb7d5060bb271d41.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb7d5060bb271d42.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb7d5060bb271d43.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-508112745', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb7l1s8ne4vm6v6x6.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.sq3.ts b/web-server/config/config.sq3.ts index da4c04c68..db06fb961 100644 --- a/web-server/config/config.sq3.ts +++ b/web-server/config/config.sq3.ts @@ -6,11 +6,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzSQ2022@dds-8vb9e0b130444f341.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb9e0b130444f342.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-510195956', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vbq8kgkeqd4bbegwk.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.sq4.ts b/web-server/config/config.sq4.ts index d34c31e42..a5efd2108 100644 --- a/web-server/config/config.sq4.ts +++ b/web-server/config/config.sq4.ts @@ -6,11 +6,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzSQ42022@dds-8vb11ca8d5e88fd41.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb11ca8d5e88fd42.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-510489410', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb9q6zk7bpcvo456g.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.sq7.ts b/web-server/config/config.sq7.ts index f7347636e..d7aae9d84 100644 --- a/web-server/config/config.sq7.ts +++ b/web-server/config/config.sq7.ts @@ -6,11 +6,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzSQ72022@dds-8vbf3dbcaaeec4441.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbf3dbcaaeec4442.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-512156065', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb53gmaww4042b2qb.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.sq9.ts b/web-server/config/config.sq9.ts index 87d7d9def..13f1e4b83 100644 --- a/web-server/config/config.sq9.ts +++ b/web-server/config/config.sq9.ts @@ -6,11 +6,11 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzSQ92023@dds-8vb6eea40c3207641.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb6eea40c3207642.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-515389269', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.gmmongoose = { url: 'mongodb://dbop:zyzSQGm2021@dds-8vb5de93552a67941.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67942.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb5de93552a67943.mongodb.zhangbei.rds.aliyuncs.com:3717/zyzgm?readPreference=secondary&replicaSet=mgset-508112742', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vbjy2v5jepcsozyum.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/config/config.stable.ts b/web-server/config/config.stable.ts index 7ae29f720..2f549ecaf 100644 --- a/web-server/config/config.stable.ts +++ b/web-server/config/config.stable.ts @@ -6,7 +6,7 @@ export default (appInfo: EggAppInfo) => { config.mongoose = { url: 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098', // 内网 - options: { useNewUrlParser: true, useUnifiedTopology: true }, + options: {}, }; config.redis = { url: 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com', // 内网 diff --git a/web-server/package-lock.json b/web-server/package-lock.json index fd7c5f43a..3221acbdd 100644 --- a/web-server/package-lock.json +++ b/web-server/package-lock.json @@ -1,551 +1,1003 @@ { "name": "web-server", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" + "packages": { + "": { + "name": "web-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@types/underscore": "^1.11.3", + "crc": "^3.8.0", + "cross-env": "^7.0.3", + "csprng": "^0.1.2", + "egg": "^2.6.1", + "egg-alinode": "^2.0.1", + "egg-cors": "^2.2.3", + "egg-http-proxy-middleware": "^1.0.3", + "egg-scripts": "^2.6.0", + "egg-view-nunjucks": "^2.2.0", + "egg-xtransit": "^1.2.2", + "minimatch": "^3.0.4", + "moment": "^2.29.1", + "mongoose": "5.10.18", + "mongoose-transactions": "^1.1.4", + "redis": "^3.1.2", + "reflect-metadata": "^0.1.13", + "request": "^2.88.2", + "request-promise": "^4.2.6", + "stream-to-array": "^2.3.0", + "thinkingdata-node": "^1.2.2", + "underscore": "^1.13.1" + }, + "devDependencies": { + "@types/mocha": "^2.2.40", + "@types/node": "^10.0.0", + "@types/redis": "^2.8.31", + "@types/request-promise": "^4.1.47", + "@types/supertest": "^2.0.0", + "autod": "^3.0.1", + "autod-egg": "^1.1.0", + "egg-bin": "^4.11.0", + "egg-ci": "^1.8.0", + "egg-mock": "^3.16.0", + "eslint": "^6.7.2", + "eslint-config-egg": "^8.0.0", + "tslib": "^1.9.0", + "typescript": "^3.0.0" + }, + "engines": { + "node": ">=10.20.1" } }, - "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, - "requires": { - "@babel/types": "^7.11.5", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.0.0-beta.44.tgz", + "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "7.0.0-beta.44", "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "lodash": "^4.2.0", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", + "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", + "dev": true, + "license": "MIT", "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - } + "@babel/helper-get-function-arity": "7.0.0-beta.44", + "@babel/template": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44" } }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "node_modules/@babel/helper-get-function-arity": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", + "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "license": "MIT", + "dependencies": { + "@babel/types": "7.0.0-beta.44" } }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, - "requires": { - "@babel/types": "^7.10.4" + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", + "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", "dev": true, - "requires": { - "@babel/types": "^7.11.0" + "license": "MIT", + "dependencies": { + "@babel/types": "7.0.0-beta.44" } }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", + "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", + "dev": true, + "license": "MIT", + "dependencies": { "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" } }, - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", - "dev": true - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - }, + "license": "MIT", "dependencies": { - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - } - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" + "color-convert": "^1.9.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", "dependencies": { - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } + "engines": { + "node": ">=4" } }, - "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - }, + "license": "MIT", "dependencies": { - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } + "color-name": "1.1.3" } }, - "@eggjs/router": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eggjs/router/-/router-2.0.0.tgz", - "integrity": "sha512-ViFlE/09kgaSMgH+nGozweJYr0bVBUvG72GmTv+i7OPIxK9uj1Z1GpSTT3zB6mBfnvakvErPR5jUBsl2wBrcHA==", - "requires": { - "co": "^4.6.0", + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/parser/node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/template/-/template-7.0.0-beta.44.tgz", + "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "lodash": "^4.2.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "7.0.0-beta.44" + } + }, + "node_modules/@babel/template/node_modules/babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true, + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", + "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/generator": "7.0.0-beta.44", + "@babel/helper-function-name": "7.0.0-beta.44", + "@babel/helper-split-export-declaration": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", "debug": "^3.1.0", + "globals": "^11.1.0", + "invariant": "^2.2.0", + "lodash": "^4.2.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "7.0.0-beta.44" + } + }, + "node_modules/@babel/traverse/node_modules/babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true, + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.0.0-beta.44.tgz", + "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/types/node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@eggjs/router": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@eggjs/router/-/router-2.2.0.tgz", + "integrity": "sha512-EKnOrZ/pHMFQ1gAj3z0Yn1UnGYH/wSsc2jk06H6RrZp6ty9H6RWyP782e7FT8WL3pAevRY+SAQoH7aPh1SDSVA==", + "license": "MIT", + "dependencies": { + "co": "^4.6.0", "http-errors": "^1.3.1", "inflection": "^1.12.0", - "is-type-of": "^1.2.1", "koa-compose": "^3.0.0", "koa-convert": "^1.2.0", "methods": "^1.0.1", - "path-to-regexp": "^1.1.1", + "path-to-regexp": "^1.9.0", "urijs": "^1.19.0", "utility": "^1.15.0" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">= 8.5.0" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT" + }, + "node_modules/@hapi/bourne": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@hapi/bourne/-/bourne-3.0.0.tgz", + "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "25.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "dev": true, + "license": "MIT", + "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" }, - "dependencies": { - "@types/yargs": { - "version": "13.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.10.tgz", - "integrity": "sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - } + "engines": { + "node": ">= 8.3" } }, - "@koa/cors": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-3.1.0.tgz", - "integrity": "sha512-7ulRC1da/rBa6kj6P4g2aJfnET3z8Uf3SWu60cjbtxTA5g8lxRdX/Bd2P92EagGwwAhANeNw8T8if99rJliR6Q==", - "requires": { + "node_modules/@jest/types/node_modules/@types/yargs": { + "version": "15.0.20", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs/-/yargs-15.0.20.tgz", + "integrity": "sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@koa/cors": { + "version": "3.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@koa/cors/-/cors-3.4.3.tgz", + "integrity": "sha512-WPXQUaAeAMVaLTEFpoq3T2O1C+FstkjJnDQqy95Ck1UdILajsRhu6mhJ8H2f4NFPRBoCNN+qywTJfq/gGki5mw==", + "license": "MIT", + "dependencies": { "vary": "^1.1.2" - } - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "requires": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" }, - "dependencies": { - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } + "engines": { + "node": ">= 8.0.0" } }, - "@mrmlnc/readdir-enhanced": { + "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" - }, - "@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "requires": { - "@types/node": "*" }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } + "engines": { + "node": ">=4" } }, - "@types/bluebird": { - "version": "3.5.33", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.33.tgz", - "integrity": "sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==", - "dev": true + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "requires": { + "node_modules/@nodelib/fs.scandir/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/accepts": { + "version": "1.3.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bluebird": { + "version": "3.5.42", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/bluebird/-/bluebird-3.5.42.tgz", + "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "license": "MIT", + "dependencies": { "@types/connect": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } } }, - "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", - "dev": true + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "dev": true, + "license": "MIT" }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "requires": { + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } } }, - "@types/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" + "node_modules/@types/content-disposition": { + "version": "0.5.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/content-disposition/-/content-disposition-0.5.9.tgz", + "integrity": "sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ==", + "license": "MIT" }, - "@types/cookiejar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz", - "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==", - "dev": true + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" }, - "@types/cookies": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", - "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", - "requires": { + "node_modules/@types/cookies": { + "version": "0.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/cookies/-/cookies-0.9.2.tgz", + "integrity": "sha512-1AvkDdZM2dbyFybL4fxpuNCaWyv//0AwsuUk2DWeXyM1/5ZKm6W3z6mQi24RZ4l2ucY+bkSHzbDVpySqPGuV8A==", + "license": "MIT", + "dependencies": { "@types/connect": "*", "@types/express": "*", "@types/keygrip": "*", "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } } }, - "@types/dargs": { + "node_modules/@types/dargs": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha512-2cXlO8pz13kVYMp6Zgr8Z5DACbaGfoBp7svqZqPGcO+qG3LQLWdB5BzPPASj+UI447XxGmFHi6KjLgUB0fzucQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha512-2cXlO8pz13kVYMp6Zgr8Z5DACbaGfoBp7svqZqPGcO+qG3LQLWdB5BzPPASj+UI447XxGmFHi6KjLgUB0fzucQ==", + "license": "MIT" }, - "@types/depd": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/@types/depd/-/depd-1.1.32.tgz", - "integrity": "sha512-kB2cpXs3A0TGWl4a4h74yIwvclYZUTW6Irpee/3Dc1s4Cr5rGPHtpGPpBBpEV1MaKH5z/oul+57oDkEkeRXRnw==", - "requires": { - "@types/node": "*" - }, + "node_modules/@types/depd": { + "version": "1.1.37", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/depd/-/depd-1.1.37.tgz", + "integrity": "sha512-PkEYFHnqDFgs+bJXJX0L8mq7sn3DWh+TP0m8BBJUJfZ2WcjRm7jd7Cq68jIJt+c31R1gX0cwSK1ZXOECvN97Rg==", + "license": "MIT", "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } + "@types/node": "*" } }, - "@types/empower": { - "version": "1.2.30", - "resolved": "https://registry.npmjs.org/@types/empower/-/empower-1.2.30.tgz", - "integrity": "sha1-x8/BSzph5Ux0xnTB+8kbot8NE5I=", - "dev": true + "node_modules/@types/empower": { + "version": "1.2.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/empower/-/empower-1.2.35.tgz", + "integrity": "sha512-CxKOTtOyeeEEvS8E+PrW3C2+pBtmr+1jm1hX0nEp4ZACAsoiQ+Dcn41zIOnhpZhZV9sz6/x2KZQcRym6KsAaJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/empower-core": "*", + "@types/power-assert-formatter": "*" + } }, - "@types/eslint-visitor-keys": { + "node_modules/@types/empower-core": { + "version": "1.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/empower-core/-/empower-core-1.2.4.tgz", + "integrity": "sha512-FUik+m3zw2W2PIJfx/+lfGhxmNHQY74A0KNCLN0SA8Olc+pRn9JrgZxbBkPLV4YS4/IBPNt6/Kmuc0VwLVSy8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint-visitor-keys": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true + "dev": true, + "license": "MIT" }, - "@types/express": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", - "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", - "requires": { + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "license": "MIT", + "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" } }, - "@types/express-serve-static-core": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz", - "integrity": "sha512-EaEdY+Dty1jEU7U6J4CUWwxL+hyEGMkO5jan5gplfegUgCUsIUWqXxqw47uGjimeT4Qgkz/XUfwoau08+fgvKA==", - "requires": { + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "license": "MIT", + "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" - }, - "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } + "@types/range-parser": "*", + "@types/send": "*" } }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "license": "MIT", + "dependencies": { "@types/minimatch": "*", "@types/node": "*" } }, - "@types/http-assert": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", - "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" + "node_modules/@types/http-assert": { + "version": "1.5.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/http-assert/-/http-assert-1.5.6.tgz", + "integrity": "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==", + "license": "MIT" }, - "@types/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==" + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "license": "MIT" }, - "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "requires": { + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "license": "MIT", + "dependencies": { "@types/node": "*" } }, - "@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { "@types/istanbul-lib-coverage": "*" } }, - "@types/istanbul-reports": { + "node_modules/@types/istanbul-reports": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" } }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, - "@types/json5": { + "node_modules/@types/json5": { "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" }, - "@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" + "node_modules/@types/keygrip": { + "version": "1.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/keygrip/-/keygrip-1.0.6.tgz", + "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==", + "license": "MIT" }, - "@types/koa": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.4.tgz", - "integrity": "sha512-Etqs0kdqbuAsNr5k6mlZQelpZKVwMu9WPRHVVTLnceZlhr0pYmblRNJbCgoCMzKWWePldydU0AYEOX4Q9fnGUQ==", - "requires": { + "node_modules/@types/koa": { + "version": "2.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/koa/-/koa-2.15.0.tgz", + "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", + "license": "MIT", + "dependencies": { "@types/accepts": "*", "@types/content-disposition": "*", "@types/cookies": "*", @@ -554,166 +1006,214 @@ "@types/keygrip": "*", "@types/koa-compose": "*", "@types/node": "*" - }, + } + }, + "node_modules/@types/koa-compose": { + "version": "3.2.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/koa-compose/-/koa-compose-3.2.9.tgz", + "integrity": "sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA==", + "license": "MIT", "dependencies": { - "@types/node": { - "version": "14.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.2.tgz", - "integrity": "sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw==" - } - } - }, - "@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "requires": { "@types/koa": "*" } }, - "@types/koa-router": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/koa-router/-/koa-router-7.4.1.tgz", - "integrity": "sha512-Hg78TXz78QYfEgdq3nTeRmQFEwJKZljsXb/DhtexmyrpRDRnl59oMglh9uPj3/WgKor0woANrYTnxA8gaWGK2A==", - "requires": { + "node_modules/@types/koa-router": { + "version": "7.4.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/koa-router/-/koa-router-7.4.9.tgz", + "integrity": "sha512-YibkqJrFWwwF55YtZo6dORpMj/1zfweHHIZA/qpA+2JPcVbBopAvLjejTcO1ojWAJfzf1tPC+CrPnLDuVRkUEA==", + "license": "MIT", + "dependencies": { "@types/koa": "*" } }, - "@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mocha": { - "version": "2.2.48", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", - "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", - "dev": true - }, - "@types/node": { - "version": "7.10.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.12.tgz", - "integrity": "sha512-SieeKQUj5NbRKZtRH/6T3H2XQCraXqSEc+gABTXNtL4uwPtXmoZEaHJ3WJylfwF3vJzj5ha6Aq8h9dbKFBINiQ==" - }, - "@types/power-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/power-assert/-/power-assert-1.5.3.tgz", - "integrity": "sha512-PzV9RX7RRUBYLxp52ipXo9dSvBnqVR09mcvGt3hXuzoJt0EUpPPv0X3btjCQqrhQ1xLbyt0dfPiGfRfrZB4G0A==", + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "2.2.48", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/mocha/-/mocha-2.2.48.tgz", + "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "license": "MIT" + }, + "node_modules/@types/power-assert": { + "version": "1.5.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/power-assert/-/power-assert-1.5.12.tgz", + "integrity": "sha512-dNBQIKnfnCDanT4aP2ZhY33ePEO7dGFZo+u+RPDqwvkoFwnH5GkVjo8Vb8SQ0VKlhylkEE0IgFbTirWEiHKHCw==", + "dev": true, + "license": "MIT", + "dependencies": { "@types/empower": "*", "@types/power-assert-formatter": "*" } }, - "@types/power-assert-formatter": { - "version": "1.4.29", - "resolved": "https://registry.npmjs.org/@types/power-assert-formatter/-/power-assert-formatter-1.4.29.tgz", - "integrity": "sha512-K3kBfCD4xnx+W5xLVbkyiKUKHvkZBL3R2fS3/wSoFJORcXdzN3ir13zTok1wNnH+hbv8Wc+YTWJDyqEdNsEXzg==", - "dev": true + "node_modules/@types/power-assert-formatter": { + "version": "1.4.33", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/power-assert-formatter/-/power-assert-formatter-1.4.33.tgz", + "integrity": "sha512-0SiJHRbxCLyC4jnCrK1NZhtu15Ay1kmf32Dm14UC2NKF5U/XlpgMV1h9XLtxZtr9x5a1+ex+ofmjBvfGcQQJ1g==", + "dev": true, + "license": "MIT" }, - "@types/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==" + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "license": "MIT" }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" }, - "@types/redis": { + "node_modules/@types/redis": { "version": "2.8.32", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.32.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/redis/-/redis-2.8.32.tgz", "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/node": "*" } }, - "@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", - "form-data": "^2.5.0" + "form-data": "^2.5.5" } }, - "@types/request-promise": { - "version": "4.1.47", - "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz", - "integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==", + "node_modules/@types/request-promise": { + "version": "4.1.51", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/request-promise/-/request-promise-4.1.51.tgz", + "integrity": "sha512-qVcP9Fuzh9oaAh8oPxiSoWMFGnWKkJDknnij66vi09Yiy62bsSDqtd+fG5kIM9wLLgZsRP3Y6acqj9O/v2ZtRw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/bluebird": "*", "@types/request": "*" } }, - "@types/serve-static": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", - "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "@types/superagent": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.10.tgz", - "integrity": "sha512-xAgkb2CMWUMCyVc/3+7iQfOEBE75NvuZeezvmixbUw3nmENf2tCnQkW5yQLTYqvXUQ+R6EXxdqKKbal2zM5V/g==", - "dev": true, - "requires": { - "@types/cookiejar": "*", + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "license": "MIT", + "dependencies": { "@types/node": "*" } }, - "@types/supertest": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.10.tgz", - "integrity": "sha512-Xt8TbEyZTnD5Xulw95GLMOkmjGICrOQyJ2jqgkSjAUR3mm7pAIzSR0NFBaMcwlzVvlpCjNwbATcWWwjNiZiFrQ==", + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/superagent/node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.16", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/supertest/-/supertest-2.0.16.tgz", + "integrity": "sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==", + "dev": true, + "license": "MIT", + "dependencies": { "@types/superagent": "*" } }, - "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==", - "dev": true + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" }, - "@types/underscore": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.3.tgz", - "integrity": "sha512-Fl1TX1dapfXyDqFg2ic9M+vlXRktcPJrc4PR7sRc7sdVrjavg/JHlbUXBt8qWWqhJrmSqg3RNAkAPRiOYw6Ahw==" + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" }, - "@types/yargs": { - "version": "12.0.18", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.18.tgz", - "integrity": "sha512-S5zJIrr2/n0DJpbwfpUc7wt9zQF0Y4GYKecxjPZ/25xPfsCIl+u+wD/HjyNZ6QPwmDPcPJmt9uMXtriRW/FiAw==" + "node_modules/@types/underscore": { + "version": "1.13.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/underscore/-/underscore-1.13.0.tgz", + "integrity": "sha512-L6LBgy1f0EFQZ+7uSA57+n2g/s4Qs5r06Vwrwn0/nuK1de+adz00NWaztRQ30aEqw5qOaWbPI8u2cGQ52lj6VA==", + "license": "MIT" }, - "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", - "dev": true + "node_modules/@types/yargs": { + "version": "12.0.20", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs/-/yargs-12.0.20.tgz", + "integrity": "sha512-MjOKUoDmNattFOBJvAZng7X9KXIKSGy6XHoXY9mASkKwCn35X4Ckh+Ugv1DewXZXrWYXMNtLiXhlCfWlpcAV+Q==", + "license": "MIT" }, - "@typescript-eslint/eslint-plugin": { + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz", "integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@typescript-eslint/experimental-utils": "3.10.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", @@ -721,64 +1221,157 @@ "semver": "^7.3.2", "tsutils": "^3.17.1" }, - "dependencies": { - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^3.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true } } }, - "@typescript-eslint/experimental-utils": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/json-schema": "^7.0.3", "@typescript-eslint/types": "3.10.1", "@typescript-eslint/typescript-estree": "3.10.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - } + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" } }, - "@typescript-eslint/parser": { + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/@typescript-eslint/parser": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/parser/-/parser-3.10.1.tgz", "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/experimental-utils": "3.10.1", "@typescript-eslint/types": "3.10.1", "@typescript-eslint/typescript-estree": "3.10.1", "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/types": { + "node_modules/@typescript-eslint/types": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/types/-/types-3.10.1.tgz", "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/typescript-estree": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "@typescript-eslint/types": "3.10.1", "@typescript-eslint/visitor-keys": "3.10.1", "debug": "^4.1.1", @@ -787,402 +1380,811 @@ "lodash": "^4.17.15", "semver": "^7.3.2", "tsutils": "^3.17.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "@yarnpkg/lockfile": { + "node_modules/@xprofiler/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/@xprofiler/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-kNFT4XscrA+Hjh+jSHs49PiG/YGf08a6eNDo16qjSnCaT4B5ngrKDcNtEJ6CnS0sDP/1oZmHCBYECB6wGKP7lg==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.5", + "node-gyp": "9.3.1", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@xprofiler/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@xprofiler/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@xprofiler/node-pre-gyp/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" }, - "a-sync-waterfall": { + "node_modules/a-sync-waterfall": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + "resolved": "https://mirrors.cloud.tencent.com/npm/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" }, - "abbrev": { + "node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "resolved": "https://mirrors.cloud.tencent.com/npm/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "acorn": { + "node_modules/acorn": { "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-5.7.4.tgz", "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "acorn-es7-plugin": { + "node_modules/acorn-es7-plugin": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", - "integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", + "integrity": "sha512-7D+8kscFMf6F2t+8ZRYmv82CncDZETsaZ4dEl5lh3qQez7FVABk2Vz616SAbnIq1PbNsLVaZjl2oSkk5BWAKng==", + "dev": true, + "license": "MIT" }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" } }, - "agentkeepalive": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.3.tgz", - "integrity": "sha512-wn8fw19xKZwdGPO47jivonaHRTd+nGOMP1z11sgGeQzDy2xd5FG0R67dIMcKHDE2cJ5y+YXV30XVGUBPRSY7Hg==", - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", + "node_modules/acorn-walk/node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" } }, - "agentx": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/agentx/-/agentx-1.10.7.tgz", - "integrity": "sha512-RW74AfrErchL0/lqFUgeBYyACFQtFVSAuTTJtRVFn1EQ1zsEhKJKnEoLTNckfm/g+mvWlD+IhaPyfuvPKXbWNw==", - "requires": { + "node_modules/agentx": { + "version": "1.10.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/agentx/-/agentx-1.10.8.tgz", + "integrity": "sha512-uf9NP555ghJKfZw+J+LFpOdrQH/XuIIMkHBNEVqrTE3Njme3CptqIXH9yXF11aqGWaHaOT8itrMiYR1H2eBpxw==", + "license": "MIT", + "dependencies": { "debug": "^3.1.0", "nounou": "^1.2.1", "split2": "^2.2.0", "through2": "^2.0.3", "ws": "^1.1.5" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "bin": { + "agentx": "start_client.js" } }, - "aggregate-error": { + "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { + "license": "MIT", + "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", - "requires": { + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "license": "MIT", + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "dev": true, + "license": "BSD-3-Clause OR MIT", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - } + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "any-promise": { + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/any-promise": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + "resolved": "https://mirrors.cloud.tencent.com/npm/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "optional": true, - "requires": { + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "devOptional": true, + "license": "ISC", + "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "engines": { + "node": ">= 8" } }, - "argparse": { + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/are-we-there-yet/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "sprintf-js": "~1.0.2" } }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, - "arr-diff": { + "node_modules/arr-diff": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "resolved": "https://mirrors.cloud.tencent.com/npm/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "arr-flatten": { + "node_modules/arr-flatten": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "arr-union": { + "node_modules/arr-union": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", - "dev": true - }, - "array-find": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-find/-/array-find-1.0.0.tgz", - "integrity": "sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=", - "dev": true - }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "resolved": "https://mirrors.cloud.tencent.com/npm/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "array-union": { + "node_modules/array-buffer-byte-length": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-filter": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha512-Ene1hbrinPZ1qPoZp7NSx4jQnh4nr7MtY78pHNb+yr8yHbxmTS7ChGW0a55JKA7TkRDeoQxK4GcJaCvBYplSKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-find": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-find/-/array-find-1.0.0.tgz", + "integrity": "sha512-kO/vVCacW9mnpn3WPWbTVlEnOabK2L7LWi2HViURtCM46y1zb6I8UMjx4LgbiqadTgHnLInUronwn3ampNTJtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "license": "MIT", + "dependencies": { "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "array-uniq": { + "node_modules/array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "resolved": "https://mirrors.cloud.tencent.com/npm/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "array-unique": { + "node_modules/array-unique": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "array.prototype.flatmap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", - "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "arrify": { + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.reduce/-/array.prototype.reduce-1.0.8.tgz", + "integrity": "sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "is-string": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + "resolved": "https://mirrors.cloud.tencent.com/npm/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "asap": { + "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "resolved": "https://mirrors.cloud.tencent.com/npm/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { "safer-buffer": "~2.1.0" } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "ast-types": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", - "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", - "requires": { - "tslib": "^2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" - } + "resolved": "https://mirrors.cloud.tencent.com/npm/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "license": "MIT", + "engines": { + "node": ">=0.8" } }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, - "astral-regex": { + "node_modules/assign-symbols": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "autod": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/autod/-/autod-3.1.0.tgz", - "integrity": "sha512-sx9phRpnxeAD4tbsqXyidDLuOWuXRIbRUEj8i9GXO9Izucrq4E+LRFPGXayEVkF4SfUJRumLTNblxiz7KfzxgQ==", + "resolved": "https://mirrors.cloud.tencent.com/npm/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autod": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/autod/-/autod-3.1.2.tgz", + "integrity": "sha512-pxR0lAF6mcuONOjIfsA+DyCy3ZlHj7WbrbwrWK8LLQc1KUhB5a9iqB8oLB1DUsfUhnEyxc8o5Vr/nl54rVENqg==", + "dev": true, + "dependencies": { "babel-core": "^6.26.0", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.24.1", @@ -1199,124 +2201,107 @@ "semver": "^6.0.0", "urllib": "^2.25.1" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "bin": { + "autod": "bin/autod.js" } }, - "autod-egg": { + "node_modules/autod-egg": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/autod-egg/-/autod-egg-1.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/autod-egg/-/autod-egg-1.1.0.tgz", "integrity": "sha512-dZ5ZRiHcHaehQnpEBWmxHTvQfIHKUdr10Qlrs/ZdBfb6NG2lUfNlVUGnqNVkp9wFsJJTGdN7ADmW9gkN8bSLrg==", - "dev": true - }, - "await-event": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/await-event/-/await-event-2.1.0.tgz", - "integrity": "sha1-eOn5JoS65AIvn6C18xShFVD5qnY=" - }, - "await-first": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/await-first/-/await-first-1.0.0.tgz", - "integrity": "sha512-SK20HicVu6lXvNM0nS1flurrs4/1NdhvccvEn52Gf+vpERZnnkKBnJvAQDsYkzJnsHs1bRNNKEiobEet7a/0TA==", - "requires": { - "ee-first": "^1.1.1" + "dev": true, + "engines": { + "node": ">=4.0.0" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "axe-core": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", - "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/await-event": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/await-event/-/await-event-2.1.0.tgz", + "integrity": "sha512-hADm2dFnyugZnfFoJ0Oug2T9xAT2gFdvxZXXnWUOFsHL+VTCvj4Q7oBOinUYzvAFeAD5HN1YSrP78iS3/SQ7iQ==", + "license": "MIT" + }, + "node_modules/await-first": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/await-first/-/await-first-1.0.0.tgz", + "integrity": "sha512-SK20HicVu6lXvNM0nS1flurrs4/1NdhvccvEn52Gf+vpERZnnkKBnJvAQDsYkzJnsHs1bRNNKEiobEet7a/0TA==", + "license": "MIT", + "dependencies": { + "ee-first": "^1.1.1" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "license": "MIT" + }, + "node_modules/axe-core": { + "version": "4.11.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/axe-core/-/axe-core-4.11.1.tgz", + "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", + "dev": true, + "license": "MIT", + "dependencies": { "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } } }, - "babel-core": { + "node_modules/babel-core": { "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-core/-/babel-core-6.26.3.tgz", "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-code-frame": "^6.26.0", "babel-generator": "^6.26.0", "babel-helpers": "^6.24.1", @@ -1336,31 +2321,33 @@ "private": "^0.1.8", "slash": "^1.0.0", "source-map": "^0.5.7" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } } }, - "babel-eslint": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz", - "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", + "node_modules/babel-core/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/babel-core/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-eslint": { + "version": "8.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-eslint/-/babel-eslint-8.2.6.tgz", + "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", + "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", + "dev": true, + "license": "MIT", + "dependencies": { "@babel/code-frame": "7.0.0-beta.44", "@babel/traverse": "7.0.0-beta.44", "@babel/types": "7.0.0-beta.44", @@ -1368,161 +2355,64 @@ "eslint-scope": "3.7.1", "eslint-visitor-keys": "^1.0.0" }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", - "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.44" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", - "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44", - "jsesc": "^2.5.1", - "lodash": "^4.2.0", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", - "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.44", - "@babel/template": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", - "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", - "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.44" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", - "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", - "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "lodash": "^4.2.0" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", - "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/generator": "7.0.0-beta.44", - "@babel/helper-function-name": "7.0.0-beta.44", - "@babel/helper-split-export-declaration": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.2.0" - } - }, - "@babel/types": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", - "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^2.0.0" - } - }, - "babylon": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", - "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } + "engines": { + "node": ">=4" } }, - "babel-generator": { + "node_modules/babel-eslint/node_modules/@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "7.0.0-beta.44" + } + }, + "node_modules/babel-eslint/node_modules/babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://mirrors.cloud.tencent.com/npm/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true, + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/babel-eslint/node_modules/eslint-scope": { + "version": "3.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha512-ivpbtpUgg9SJS4TLjK7KdcDhqc/E3CGItsvQbBNLkNGUeMhd5qnJcryba/brESS+dg3vrLqPuc/UcS7jRJdN5A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/babel-eslint/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/babel-generator": { "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-messages": "^6.23.0", "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", @@ -1533,92 +2423,100 @@ "trim-right": "^1.0.1" } }, - "babel-helper-bindify-decorators": { + "node_modules/babel-helper-bindify-decorators": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha512-TYX2QQATKA6Wssp6j7jqlw4QLmABDN1olRdEHndYvBXdaXM5dcx6j5rN0+nd+aVL+Th40fAEYvvw/Xxd/LETuQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, - "babel-helper-builder-binary-assignment-operator-visitor": { + "node_modules/babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-explode-assignable-expression": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-helper-builder-react-jsx": { + "node_modules/babel-helper-builder-react-jsx": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha512-02I9jDjnVEuGy2BR3LRm9nPRb/+Ja0pvZVLr1eI5TYAA/dB0Xoc+WBo50+aDfhGDLhlBY1+QURjn9uvcFd8gzg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "esutils": "^2.0.2" } }, - "babel-helper-call-delegate": { + "node_modules/babel-helper-call-delegate": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-hoist-variables": "^6.24.1", "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, - "babel-helper-define-map": { + "node_modules/babel-helper-define-map": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "lodash": "^4.17.4" } }, - "babel-helper-explode-assignable-expression": { + "node_modules/babel-helper-explode-assignable-expression": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, - "babel-helper-explode-class": { + "node_modules/babel-helper-explode-class": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha512-SFbWewr0/0U4AiRzsHqwsbOQeLXVa9T1ELdqEa2efcQB5KopTnunAqoj07TuHlN2lfTQNPGO/rJR4FMln5fVcA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-bindify-decorators": "^6.24.1", "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, - "babel-helper-function-name": { + "node_modules/babel-helper-function-name": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-get-function-arity": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", @@ -1626,53 +2524,58 @@ "babel-types": "^6.24.1" } }, - "babel-helper-get-function-arity": { + "node_modules/babel-helper-get-function-arity": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-helper-hoist-variables": { + "node_modules/babel-helper-hoist-variables": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-helper-optimise-call-expression": { + "node_modules/babel-helper-optimise-call-expression": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-helper-regex": { + "node_modules/babel-helper-regex": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "lodash": "^4.17.4" } }, - "babel-helper-remap-async-to-generator": { + "node_modules/babel-helper-remap-async-to-generator": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", @@ -1680,12 +2583,13 @@ "babel-types": "^6.24.1" } }, - "babel-helper-replace-supers": { + "node_modules/babel-helper-replace-supers": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-optimise-call-expression": "^6.24.1", "babel-messages": "^6.23.0", "babel-runtime": "^6.22.0", @@ -1694,169 +2598,191 @@ "babel-types": "^6.24.1" } }, - "babel-helpers": { + "node_modules/babel-helpers": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-messages": { + "node_modules/babel-messages": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-check-es2015-constants": { + "node_modules/babel-plugin-check-es2015-constants": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-syntax-async-functions": { + "node_modules/babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-async-generators": { + "node_modules/babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha512-EbciFN5Jb9iqU9bqaLmmFLx2G8pAUsvpWJ6OzOWBNrSY9qTohXj+7YfZx6Ug1Qqh7tCb1EA7Jvn9bMC1HBiucg==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-class-constructor-call": { + "node_modules/babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha512-EEuBcXz/wZ81Jaac0LnMHtD4Mfz9XWn2oH2Xj+CHwz2SZWUqqdtR2BgWPSdTGMmxN/5KLSh4PImt9+9ZedDarA==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-class-properties": { + "node_modules/babel-plugin-syntax-class-properties": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha512-chI3Rt9T1AbrQD1s+vxw3KcwC9yHtF621/MacuItITfZX344uhQoANjpoSJZleAmW2tjlolqB/f+h7jIqXa7pA==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-decorators": { + "node_modules/babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha512-AWj19x2aDm8qFQ5O2JcD6pwJDW1YdcnO+1b81t7gxrGjz5VHiUqeYWAR4h7zueWMalRelrQDXprv2FrY1dbpbw==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-do-expressions": { + "node_modules/babel-plugin-syntax-do-expressions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha512-HD/5qJB9oSXzl0caxM+aRD7ENICXqcc3Up/8toDQk7zNIDE7TzsqtxC5f4t9Rwhu2Ya8l9l4j6b3vOsy+a6qxg==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-dynamic-import": { + "node_modules/babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha512-MioUE+LfjCEz65Wf7Z/Rm4XCP5k2c+TbMd2Z2JKc7U9uwjBhAfNPE48KC4GTGKhppMeYVepwDBNO/nGY6NYHBA==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-exponentiation-operator": { + "node_modules/babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-export-extensions": { + "node_modules/babel-plugin-syntax-export-extensions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha512-Eo0rcRaIDMld/W6mVhePiudIuLW+Cr/8eveW3mBREfZORScZgx4rh6BAPyvzdEc/JZvQ+LkC80t0VGFs6FX+lg==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-flow": { + "node_modules/babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha512-HbTDIoG1A1op7Tl/wIFQPULIBA61tsJ8Ntq2FAhLwuijrzosM/92kAfgU1Q3Kc7DH/cprJg5vDfuTY4QUL4rDA==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-function-bind": { + "node_modules/babel-plugin-syntax-function-bind": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha512-m8yMoh9LIiNyeLdQs5I9G+3YXo4nqVsKQkk7YplrG4qAFbNi9hkZlow8HDHxhH9QOVFPHmy8+03NzRCdyChIKw==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-jsx": { + "node_modules/babel-plugin-syntax-jsx": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-object-rest-spread": { + "node_modules/babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha512-C4Aq+GaAj83pRQ0EFgTvw5YO6T3Qz2KGrNRwIj9mSoNHVvdZY4KO2uA6HNtNXCw993iSZnckY1aLW8nOi8i4+w==", + "dev": true, + "license": "MIT" }, - "babel-plugin-syntax-trailing-function-commas": { + "node_modules/babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==", + "dev": true, + "license": "MIT" }, - "babel-plugin-transform-async-generator-functions": { + "node_modules/babel-plugin-transform-async-generator-functions": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha512-uT7eovUxtXe8Q2ufcjRuJIOL0hg6VAUJhiWJBLxH/evYAw+aqoJLcYTR8hqx13iOx/FfbCMHgBmXWZjukbkyPg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-remap-async-to-generator": "^6.24.1", "babel-plugin-syntax-async-generators": "^6.5.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-async-to-generator": { + "node_modules/babel-plugin-transform-async-to-generator": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-remap-async-to-generator": "^6.24.1", "babel-plugin-syntax-async-functions": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-class-constructor-call": { + "node_modules/babel-plugin-transform-class-constructor-call": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha512-RvYukT1Nh7njz8P8326ztpQUGCKwmjgu6aRIx1lkvylWITYcskg29vy1Kp8WXIq7FvhXsz0Crf2kS94bjB690A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-class-constructor-call": "^6.18.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-class-properties": { + "node_modules/babel-plugin-transform-class-properties": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha512-n4jtBA3OYBdvG5PRMKsMXJXHfLYw/ZOmtxCLOOwz6Ro5XlrColkStLnz1AS1L2yfPA9BKJ1ZNlmVCLjAL9DSIg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-plugin-syntax-class-properties": "^6.8.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-decorators": { + "node_modules/babel-plugin-transform-decorators": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha512-skQ2CImwDkCHu0mkWvCOlBCpBIHW4/49IZWVwV4A/EnWjL9bB6UBvLyMNe3Td5XDStSZNhe69j4bfEW8dvUbew==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-explode-class": "^6.24.1", "babel-plugin-syntax-decorators": "^6.13.0", "babel-runtime": "^6.22.0", @@ -1864,40 +2790,44 @@ "babel-types": "^6.24.1" } }, - "babel-plugin-transform-do-expressions": { + "node_modules/babel-plugin-transform-do-expressions": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha512-yQwYqYg+Tnj1InA8W1rsItsZVhkv1Euc4KVua9ledtPz5PDWYz7LVyy6rDBpVYUWFZj5k6GUm3YZpCbIm8Tqew==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-do-expressions": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-arrow-functions": { + "node_modules/babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-block-scoped-functions": { + "node_modules/babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-block-scoping": { + "node_modules/babel-plugin-transform-es2015-block-scoping": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-traverse": "^6.26.0", @@ -1905,12 +2835,13 @@ "lodash": "^4.17.4" } }, - "babel-plugin-transform-es2015-classes": { + "node_modules/babel-plugin-transform-es2015-classes": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-define-map": "^6.24.1", "babel-helper-function-name": "^6.24.1", "babel-helper-optimise-call-expression": "^6.24.1", @@ -1922,125 +2853,137 @@ "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-computed-properties": { + "node_modules/babel-plugin-transform-es2015-computed-properties": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-es2015-destructuring": { + "node_modules/babel-plugin-transform-es2015-destructuring": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-duplicate-keys": { + "node_modules/babel-plugin-transform-es2015-duplicate-keys": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-for-of": { + "node_modules/babel-plugin-transform-es2015-for-of": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-function-name": { + "node_modules/babel-plugin-transform-es2015-function-name": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-literals": { + "node_modules/babel-plugin-transform-es2015-literals": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-modules-amd": { + "node_modules/babel-plugin-transform-es2015-modules-amd": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-es2015-modules-commonjs": { + "node_modules/babel-plugin-transform-es2015-modules-commonjs": { "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-transform-strict-mode": "^6.24.1", "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-types": "^6.26.0" } }, - "babel-plugin-transform-es2015-modules-systemjs": { + "node_modules/babel-plugin-transform-es2015-modules-systemjs": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-hoist-variables": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-es2015-modules-umd": { + "node_modules/babel-plugin-transform-es2015-modules-umd": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-transform-es2015-modules-amd": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-es2015-object-super": { + "node_modules/babel-plugin-transform-es2015-object-super": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-replace-supers": "^6.24.1", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-parameters": { + "node_modules/babel-plugin-transform-es2015-parameters": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-call-delegate": "^6.24.1", "babel-helper-get-function-arity": "^6.24.1", "babel-runtime": "^6.22.0", @@ -2049,181 +2992,199 @@ "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-shorthand-properties": { + "node_modules/babel-plugin-transform-es2015-shorthand-properties": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-spread": { + "node_modules/babel-plugin-transform-es2015-spread": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-sticky-regex": { + "node_modules/babel-plugin-transform-es2015-sticky-regex": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-plugin-transform-es2015-template-literals": { + "node_modules/babel-plugin-transform-es2015-template-literals": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-typeof-symbol": { + "node_modules/babel-plugin-transform-es2015-typeof-symbol": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-unicode-regex": { + "node_modules/babel-plugin-transform-es2015-unicode-regex": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "regexpu-core": "^2.0.0" } }, - "babel-plugin-transform-exponentiation-operator": { + "node_modules/babel-plugin-transform-exponentiation-operator": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", "babel-plugin-syntax-exponentiation-operator": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-export-extensions": { + "node_modules/babel-plugin-transform-export-extensions": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha512-mtzELzINaYqdVglyZrDDVwkcFRuE7s6QUFWXxwffKAHB/NkfbJ2NJSytugB43ytIC8UVt30Ereyx+7gNyTkDLg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-export-extensions": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-flow-strip-types": { + "node_modules/babel-plugin-transform-flow-strip-types": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha512-TxIM0ZWNw9oYsoTthL3lvAK3+eTujzktoXJg4ubGvICGbVuXVYv5hHv0XXpz8fbqlJaGYY4q5SVzaSmsg3t4Fg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-flow": "^6.18.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-function-bind": { + "node_modules/babel-plugin-transform-function-bind": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha512-9Ec4KYf1GurT39mlUjDSlN7HWSlB3u3mWRMogQbb+Y88lO0ZM3rJ0ADhPnQwWK9TbO6e/4E+Et1rrfGY9mFimA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-function-bind": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-object-rest-spread": { + "node_modules/babel-plugin-transform-object-rest-spread": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha512-ocgA9VJvyxwt+qJB0ncxV8kb/CjfTcECUY4tQ5VT7nP6Aohzobm8CDFaQ5FHdvZQzLmf0sgDxB8iRXZXxwZcyA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-object-rest-spread": "^6.8.0", "babel-runtime": "^6.26.0" } }, - "babel-plugin-transform-react-display-name": { + "node_modules/babel-plugin-transform-react-display-name": { "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha512-QLYkLiZeeED2PKd4LuXGg5y9fCgPB5ohF8olWUuETE2ryHNRqqnXlEVP7RPuef89+HTfd3syptMGVHeoAu0Wig==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-react-jsx": { + "node_modules/babel-plugin-transform-react-jsx": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha512-s+q/Y2u2OgDPHRuod3t6zyLoV8pUHc64i/O7ZNgIOEdYTq+ChPeybcKBi/xk9VI60VriILzFPW+dUxAEbTxh2w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-helper-builder-react-jsx": "^6.24.1", "babel-plugin-syntax-jsx": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-react-jsx-self": { + "node_modules/babel-plugin-transform-react-jsx-self": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha512-Y3ZHP1nunv0U1+ysTNwLK39pabHj6cPVsfN4TRC7BDBfbgbyF4RifP5kd6LnbuMV9wcfedQMe7hn1fyKc7IzTQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-jsx": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-react-jsx-source": { + "node_modules/babel-plugin-transform-react-jsx-source": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha512-pcDNDsZ9q/6LJmujQ/OhjeoIlp5Nl546HJ2yiFIJK3mYpgNXhI5/S9mXfVxu5yqWAi7HdI7e/q6a9xtzwL69Vw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-jsx": "^6.8.0", "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-regenerator": { + "node_modules/babel-plugin-transform-regenerator": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "regenerator-transform": "^0.10.0" } }, - "babel-plugin-transform-strict-mode": { + "node_modules/babel-plugin-transform-strict-mode": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, - "babel-preset-env": { + "node_modules/babel-preset-env": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-env/-/babel-preset-env-1.7.0.tgz", "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-check-es2015-constants": "^6.22.0", "babel-plugin-syntax-trailing-function-commas": "^6.22.0", "babel-plugin-transform-async-to-generator": "^6.22.0", @@ -2254,31 +3215,35 @@ "browserslist": "^3.2.6", "invariant": "^2.2.2", "semver": "^5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "node_modules/babel-preset-env/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "requires": { + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha512-PQZFJXnM3d80Vq4O67OE6EMVKIw2Vmzy8UXovqulNogCtblWU8rzP7Sm5YgHiCg4uejUxzCkHfNXQ4Z6GI+Dhw==", + "dev": true, + "license": "MIT", + "dependencies": { "babel-plugin-transform-flow-strip-types": "^6.22.0" } }, - "babel-preset-react": { + "node_modules/babel-preset-react": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha512-phQe3bElbgF887UM0Dhz55d22ob8czTL1kbhZFwpCE6+R/X9kHktfwmx9JZb+bBSVRGphP5tZ9oWhVhlgjrX3Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-jsx": "^6.3.13", "babel-plugin-transform-react-display-name": "^6.23.0", "babel-plugin-transform-react-jsx": "^6.24.1", @@ -2287,46 +3252,50 @@ "babel-preset-flow": "^6.23.0" } }, - "babel-preset-stage-0": { + "node_modules/babel-preset-stage-0": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", - "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha512-MJD+xBbpsApbKlzAX0sOBF+VeFaUmv5s8FSOO7SSZpes1QgphCjq/UIGRFWSmQ/0i5bqQjLGCTXGGXqcLQ9JDA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-transform-do-expressions": "^6.22.0", "babel-plugin-transform-function-bind": "^6.22.0", "babel-preset-stage-1": "^6.24.1" } }, - "babel-preset-stage-1": { + "node_modules/babel-preset-stage-1": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha512-rn+UOcd7BHDniq1SVxv2/AVVSVI1NK+hfS0I/iR6m6KbOi/aeBRcqBilqO73pd9VUpRXF2HFtlDuC9F2BEQqmg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-transform-class-constructor-call": "^6.24.1", "babel-plugin-transform-export-extensions": "^6.22.0", "babel-preset-stage-2": "^6.24.1" } }, - "babel-preset-stage-2": { + "node_modules/babel-preset-stage-2": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha512-9F+nquz+37PrlTSBdpeQBKnQfAMNBnryXw+m4qBh35FNbJPfzZz+sjN2G5Uf1CRedU9PH7fJkTbYijxmkLX8Og==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators": "^6.24.1", "babel-preset-stage-3": "^6.24.1" } }, - "babel-preset-stage-3": { + "node_modules/babel-preset-stage-3": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha512-eCbEOF8uN0KypFXJmZXn2sTk7bPV9uM5xov7G/7BM08TbQEObsVs0cEWfy6NQySlfk7JBi/t+XJP1JkruYfthA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-plugin-syntax-trailing-function-commas": "^6.22.0", "babel-plugin-transform-async-generator-functions": "^6.24.1", "babel-plugin-transform-async-to-generator": "^6.24.1", @@ -2334,12 +3303,13 @@ "babel-plugin-transform-object-rest-spread": "^6.22.0" } }, - "babel-register": { + "node_modules/babel-register": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-core": "^6.26.0", "babel-runtime": "^6.26.0", "core-js": "^2.5.0", @@ -2347,35 +3317,26 @@ "lodash": "^4.17.4", "mkdirp": "^0.5.1", "source-map-support": "^0.4.15" - }, - "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - } } }, - "babel-runtime": { + "node_modules/babel-runtime": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" } }, - "babel-template": { + "node_modules/babel-template": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-runtime": "^6.26.0", "babel-traverse": "^6.26.0", "babel-types": "^6.26.0", @@ -2383,12 +3344,13 @@ "lodash": "^4.17.4" } }, - "babel-traverse": { + "node_modules/babel-traverse": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "babel-code-frame": "^6.26.0", "babel-messages": "^6.23.0", "babel-runtime": "^6.26.0", @@ -2398,53 +3360,61 @@ "globals": "^9.18.0", "invariant": "^2.2.2", "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } } }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "node_modules/babel-traverse/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/babel-traverse/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "license": "MIT", + "dependencies": { "babel-runtime": "^6.26.0", "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" } }, - "babylon": { + "node_modules/babylon": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "dev": true, + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, - "base": { + "node_modules/base": { "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", "component-emitter": "^1.2.1", @@ -2453,226 +3423,368 @@ "mixin-deep": "^1.2.0", "pascalcase": "^0.1.1" }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">=0.10.0" } }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" - }, - "bash-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bash-glob/-/bash-glob-2.0.0.tgz", - "integrity": "sha512-53/NJ+t2UAkEYgQPO6aFjbx1Ue8vNNXCYaA4EljNKP1SR8A9dSQQoBmYWR8BLXO0/NDRJEMSJ4BxWihi//m3Kw==", - "requires": { - "bash-path": "^1.0.1", - "component-emitter": "^1.2.1", - "cross-spawn": "^5.1.0", - "each-parallel-async": "^1.0.0", - "extend-shallow": "^2.0.1", - "is-extglob": "^2.1.1", - "is-glob": "^4.0.0" + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.0" }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + { + "type": "consulting", + "url": "https://feross.org/support" } - } + ], + "license": "MIT" }, - "bash-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bash-path/-/bash-path-1.0.3.tgz", - "integrity": "sha512-mGrYvOa6yTY/qNCiZkPFJqWmODK68y6kmVRAJ1NNbWlNoJrUrsFxu7FU2EKg7gbrer6ttrKkF2s/E/lhRy7/OA==", - "requires": { - "arr-union": "^3.1.0", - "is-windows": "^1.0.1" - } - }, - "bcrypt-pbkdf": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { "tweetnacl": "^0.14.3" } }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "optional": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "black-hole-stream": { + "node_modules/bl": { + "version": "2.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/black-hole-stream": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/black-hole-stream/-/black-hole-stream-0.0.1.tgz", - "integrity": "sha1-M7ega58edFPWBBuCl0SB0hUq6kI=" + "resolved": "https://mirrors.cloud.tencent.com/npm/black-hole-stream/-/black-hole-stream-0.0.1.tgz", + "integrity": "sha512-FQSWhFQZmddoqWkwPMFeR5hJo9waZE796MuO7b0poStaPrm0Qr2em9FT4/TF1+0rOA1dRFabX+88rdX8YHxDTA==", + "license": "MIT" }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "node_modules/bluebird": { + "version": "3.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "license": "MIT" }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "browser-stdout": { + "node_modules/browser-stdout": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, - "browserslist": { + "node_modules/browserslist": { "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "caniuse-lite": "^1.0.30000844", "electron-to-chromium": "^1.3.47" + }, + "bin": { + "browserslist": "cli.js" } }, - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "node_modules/bson": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.6.19" } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, - "busboy": { + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "dependencies": { "dicer": "0.2.5", "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" } }, - "byte": { + "node_modules/byte": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/byte/-/byte-2.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/byte/-/byte-2.0.0.tgz", "integrity": "sha512-rNiK8YxOMvquToaBubKxA10sjRIZ/taDqtc/1jLQA4X7aNDlA1XGx4Ciml3YxL8DskFz1XX3WFskSp0peKYSKg==", - "requires": { + "license": "MIT", + "dependencies": { "debug": "^3.1.0", "long": "^4.0.0", "utility": "^1.13.1" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">= 8.0.0" } }, - "bytes": { + "node_modules/bytes": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", - "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=" + "resolved": "https://mirrors.cloud.tencent.com/npm/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha512-zGRpnr2l5w/s8PxkrquUJoVeR06KvqPelrYqiSyQV7QEBqCYivpb6UzXYWC6JDBVtNFOT0rzJRFhkfJgxzmILA==", + "license": "MIT" }, - "cache-base": { + "node_modules/c8": { + "version": "7.14.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/c8/-/c8-7.14.0.tgz", + "integrity": "sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/c8/node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cache-base": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", "get-value": "^2.0.6", @@ -2682,105 +3794,208 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "cache-content-type": { + "node_modules/cache-content-type": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/cache-content-type/-/cache-content-type-1.0.1.tgz", "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "requires": { + "license": "MIT", + "dependencies": { "mime-types": "^2.1.18", "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" } }, - "cache-require-paths": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/cache-require-paths/-/cache-require-paths-0.3.0.tgz", - "integrity": "sha1-EqYHWj5JiNpMIvIY4pSFZj5MSmM=", - "dev": true + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "call-matcher": { + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-matcher": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-matcher/-/call-matcher-1.1.0.tgz", "integrity": "sha512-IoQLeNwwf9KTNbtSA7aEBb1yfDbdnzwjCetjkC8io5oGeOmK2CBNdg0xr+tadRYKO0p7uQyZzvon0kXlZbvGrw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "deep-equal": "^1.0.0", "espurify": "^1.6.0", "estraverse": "^4.0.0" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "node_modules/call-matcher/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "call-signature": { + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-signature": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", - "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/call-signature/-/call-signature-0.0.2.tgz", + "integrity": "sha512-qvYvkAVcoae0obt8OsZn0VEBHeEpvYIZDy1gGYtZDJG0fHawew+Mi0dBjieFz8F8dzQ2Kr19+nsDm+T5XFVs+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "callsites": { + "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "camel-case": { + "node_modules/camel-case": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0", "upper-case": "^1.1.1" } }, - "camelcase": { + "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "caniuse-lite": { - "version": "1.0.30001131", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz", - "integrity": "sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==", - "dev": true + "node_modules/caniuse-lite": { + "version": "1.0.30001776", + "resolved": "https://mirrors.cloud.tencent.com/npm/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", + "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" }, - "caseless": { + "node_modules/caseless": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "resolved": "https://mirrors.cloud.tencent.com/npm/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" }, - "cfork": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/cfork/-/cfork-1.8.0.tgz", - "integrity": "sha512-DrCPQ4GWbaz4cJWRKh7YycAa0o2V1pFJyUNpCGWSzMGKlLY1+yRnnbBQzz/2BIafcu4UUDFoNIme8pF6b15fGg==", - "requires": { + "node_modules/cfork": { + "version": "1.11.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cfork/-/cfork-1.11.0.tgz", + "integrity": "sha512-pYyWhuXPq5OoaVPaQZXFf243oQ/+eCXu7ufOZxqi8HFI7TcTxbsi1/16CpT75dSuk78ErMJQlTkpzz9O82G/Ig==", + "license": "MIT", + "dependencies": { "utility": "^1.12.0" + }, + "engines": { + "node": ">= 0.12.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "chan": { + "node_modules/chan": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/chan/-/chan-0.6.1.tgz", - "integrity": "sha1-7ArRMuW8YsJ+8QzL/E2NzYygBkA=" + "resolved": "https://mirrors.cloud.tencent.com/npm/chan/-/chan-0.6.1.tgz", + "integrity": "sha512-/TdBP2UhbBmw7qnqkzo9Mk4rzvwRv4dlNPXFerqWy90T8oBspKagJNZxrDbExKHhx9uXXHjo3f9mHgs9iKO3nQ==", + "license": "MIT" }, - "change-case": { + "node_modules/change-case": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/change-case/-/change-case-3.1.0.tgz", "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==", - "requires": { + "license": "MIT", + "dependencies": { "camel-case": "^3.0.0", "constant-case": "^2.0.0", "dot-case": "^2.1.0", @@ -2801,270 +4016,603 @@ "upper-case-first": "^1.1.0" } }, - "chardet": { + "node_modules/chardet": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "dev": true, + "license": "MIT" }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "optional": true, - "requires": { - "anymatch": "~3.1.1", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.6.0" }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "optional": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "chownr": { + "node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "circular-json-for-egg": { + "node_modules/circular-json-for-egg": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/circular-json-for-egg/-/circular-json-for-egg-1.0.0.tgz", - "integrity": "sha512-BzMR1dg0+YqcFoMETHq0gFeQNNKliXI1Oe+C0nx/4npLaohsR7/Oj3UFht65MLwF7zs6x13gOr+f4+JeYni6vw==" + "resolved": "https://mirrors.cloud.tencent.com/npm/circular-json-for-egg/-/circular-json-for-egg-1.0.0.tgz", + "integrity": "sha512-BzMR1dg0+YqcFoMETHq0gFeQNNKliXI1Oe+C0nx/4npLaohsR7/Oj3UFht65MLwF7zs6x13gOr+f4+JeYni6vw==", + "license": "MIT" }, - "class-utils": { + "node_modules/class-utils": { "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "arr-union": "^3.1.0", "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "engines": { + "node": ">=0.10.0" } }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "cli-cursor": { + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" } }, - "cli-width": { + "node_modules/cli-width": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10" } }, - "cluster-client": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cluster-client/-/cluster-client-3.0.1.tgz", - "integrity": "sha512-j5xReT5tECbiUME8TCNDU5ise34vSqbhWMs7Ni06VDKlKvRVAlUbrgYCFQc27Bw7MF8H+QEJ/8GJtk/HGx4u6w==", - "requires": { + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cluster-client": { + "version": "3.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cluster-client/-/cluster-client-3.7.0.tgz", + "integrity": "sha512-n0pLGPWlAjaGDJrLKTenjF1qoHbDjuYFlvX4UBoWCt9NjUTZGQhfNafF6Gw4Rj7oJqqdBGrdiIdHSvtOMQX5AA==", + "license": "MIT", + "dependencies": { "byte": "^2.0.0", "co": "^4.6.0", - "debug": "^4.1.1", - "egg-logger": "^2.3.2", - "is-type-of": "^1.2.1", + "egg-logger": "^3.5.0", + "is-type-of": "^1.4.0", "json-stringify-safe": "^5.0.1", "long": "^4.0.0", - "mz-modules": "^2.1.0", - "sdk-base": "^3.5.1", + "sdk-base": "^4.2.1", "serialize-json": "^1.0.3", - "tcp-base": "^3.1.0", - "utility": "^1.15.0" + "tcp-base": "^3.2.0", + "utility": "^2.1.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "cluster-reload": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cluster-reload/-/cluster-reload-1.0.2.tgz", - "integrity": "sha1-NGv1hJ0Y5FkLzBsw7kcNTKvxXBA=" + "node_modules/cluster-client/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "co": { + "node_modules/cluster-client/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cluster-client/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cluster-client/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/cluster-client/node_modules/egg-logger": { + "version": "3.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-logger/-/egg-logger-3.6.1.tgz", + "integrity": "sha512-lGiEumARJAT7NiwMm577NFiOEBMX9FlZzfuBsLLS6eu14R9udcTI1IzXLGJ63SrCmFIXB+zsWLQv5U11e8fq0Q==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "circular-json-for-egg": "^1.0.0", + "depd": "^2.0.0", + "egg-errors": "^2.3.1", + "iconv-lite": "^0.6.3", + "utility": "^2.1.0" + }, + "engines": { + "node": ">=14.17.0" + } + }, + "node_modules/cluster-client/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cluster-client/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cluster-client/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cluster-client/node_modules/utility": { + "version": "2.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/utility/-/utility-2.5.0.tgz", + "integrity": "sha512-lDbOVde5UAKgtxrSyZNhqrTA7f7anba6DTqbsDWgUFk6PZlmr7djqPYw0FnL5a6TbJvRt38VmYqt07zVLzXG2A==", + "license": "MIT", + "dependencies": { + "escape-html": "^1.0.3", + "unescape": "^1.0.1", + "ylru": "^2.0.0" + }, + "engines": { + "node": ">= 16.0.0" + } + }, + "node_modules/cluster-client/node_modules/ylru": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ylru/-/ylru-2.0.0.tgz", + "integrity": "sha512-T6hTrKcr9lKeUG0MQ/tO72D3UGptWVohgzpHG8ljU1jeBt2RCjcWxvsTPD8ZzUq1t1FvwROAw1kxg2euvg/THg==", + "license": "MIT", + "engines": { + "node": ">= 18.19.0" + } + }, + "node_modules/cluster-reload": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cluster-reload/-/cluster-reload-1.1.0.tgz", + "integrity": "sha512-lY3n9ohbJvDsDoaGGx/ER6eqaDKgVVmYjgoSL+XPxI0NHhkr4Ag60RSqVD1B9yZJz/q3FjB94bLfnuGuFuh7aw==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "resolved": "https://mirrors.cloud.tencent.com/npm/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } }, - "co-body": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", - "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", - "requires": { + "node_modules/co-body": { + "version": "6.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/co-body/-/co-body-6.2.0.tgz", + "integrity": "sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA==", + "license": "MIT", + "dependencies": { + "@hapi/bourne": "^3.0.0", "inflation": "^2.0.0", "qs": "^6.5.2", "raw-body": "^2.3.3", "type-is": "^1.6.16" + }, + "engines": { + "node": ">=8.0.0" } }, - "co-busboy": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/co-busboy/-/co-busboy-1.4.1.tgz", - "integrity": "sha512-ec1GTa1psuvngN+821rEYeEahresYHzUB74f6kRzaoD4ZcmMuhJkgVns9YW9Zt2cgcQVtGOFraRzJscO8zbDyw==", - "requires": { + "node_modules/co-busboy": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/co-busboy/-/co-busboy-1.5.0.tgz", + "integrity": "sha512-FCI+YRNcdPt1pH+/5jSHCP0goJpf8vpuKN52gFJy0Az9dnoomdT976O1PcldzOn+MQcYI6xT2lI1lt3Co1C9IA==", + "license": "MIT", + "dependencies": { "black-hole-stream": "~0.0.1", "busboy": "^0.2.8", - "chan": "^0.6.1" + "chan": "^0.6.1", + "inflation": "^2.0.0" } }, - "co-mocha": { + "node_modules/co-mocha": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/co-mocha/-/co-mocha-1.2.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/co-mocha/-/co-mocha-1.2.2.tgz", "integrity": "sha512-ocdJRn3sxonOqpdjSU2VwTwWzjTSoatzsTqCWiC3eGvJFNs8ZNMlZwfgYolQCdfddMz4muiZl99KIV9gKoNvxg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "co": "^4.0.0", "is-generator": "^1.0.1" + }, + "peerDependencies": { + "mocha": ">=1.18 <6" } }, - "code-point-at": { + "node_modules/code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "coffee": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/coffee/-/coffee-5.4.0.tgz", - "integrity": "sha512-YI0t6g78gf2YroH+hjees7LfiQfo7XnTwYAShp0PHp6fUgxV6wkbolIX+z1+mbNws48TfWVp59OpLeb/bWqvNw==", + "resolved": "https://mirrors.cloud.tencent.com/npm/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffee": { + "version": "5.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/coffee/-/coffee-5.5.1.tgz", + "integrity": "sha512-ZKt9b/Iq0jhe7tYpDMXJggx8l/+YIcQFi2C+LvJRQ7lUSJnzayir1BGbsoHELKKyV+zevWMCsfmGAI1fREyRbw==", + "dev": true, + "license": "MIT", + "dependencies": { "cross-spawn": "^6.0.5", "debug": "^4.1.0", "is-type-of": "^1.2.1" + }, + "engines": { + "node": ">= 6.0.0" } }, - "collection-visit": { + "node_modules/coffee/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/coffee/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/coffee/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/coffee/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/coffee/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffee/node_modules/shebang-regex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffee/node_modules/which": { + "version": "1.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "license": "MIT", + "dependencies": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" } }, - "color-name": { + "node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-support": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } }, - "commandx": { + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/commandx": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/commandx/-/commandx-1.5.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/commandx/-/commandx-1.5.4.tgz", "integrity": "sha512-DTb4nXLwTTSa500Ga3zn2bdVNsGV9L2bcsnZPs6Sx/M5OC57EoEgHR7J6J3VZtBnMJ6qJBOd7oGr0CpCe0pA7w==", - "requires": { + "license": "MIT", + "dependencies": { "formstream": "^1.1.0", "tunnel-agent": "^0.6.0", "urllib": "^2.22.0" } }, - "comment-parser": { + "node_modules/comment-parser": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.5.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/comment-parser/-/comment-parser-0.5.5.tgz", "integrity": "sha512-oB3TinFT+PV3p8UwDQt71+HkG03+zwPwikDlKU6ZDmql6QX2zFlQ+G0GGSDqyJhdZi4PSlzFBm+YJ+ebOX3Vgw==", - "dev": true + "dev": true, + "license": "MIT" }, - "common-bin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/common-bin/-/common-bin-2.9.0.tgz", - "integrity": "sha512-VYKiPMPx+hrd53QVJmwm7mpdbIHM4ZPaHXjHE34s4vfGDgAAKHr2v4PRzqM2crEA3vZO9pLSs4eJIXrYCFmKXg==", - "requires": { + "node_modules/common-bin": { + "version": "2.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/common-bin/-/common-bin-2.9.2.tgz", + "integrity": "sha512-fw6YBX8dr4wgMCHqcOR5eIqWZxoZa6+0JAiqjZuOZFCh/pz9hW6EY2EGFc3QpHwp/DlLuw/du/Sr2InhrfAYSQ==", + "license": "MIT", + "dependencies": { "@types/dargs": "^5.1.0", "@types/node": "^10.12.18", "@types/yargs": "^12.0.4", @@ -3075,594 +4623,999 @@ "debug": "^4.1.0", "is-type-of": "^1.2.1", "semver": "^5.5.1", - "yargs": "^12.0.2", - "yargs-parser": "^11.0.0" + "yargs": "^13.3.0", + "yargs-parser": "^13.1.2" }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/common-bin/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", "dependencies": { - "@types/node": { - "version": "10.17.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.34.tgz", - "integrity": "sha512-DlT8xondSSUixRxkdXQ3+dIZmCWkM6PX8kqIx1Zqp+FA/GmHJwqPixMeF89OirKVCFBh7U1m1I1Oj4gSrUW5oQ==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/common-bin/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/common-bin/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/common-bin/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/common-bin/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/common-bin/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "node_modules/common-bin/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "license": "MIT" }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "requires": { - "mime-db": ">= 1.43.0 < 2" + "node_modules/common-bin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "constant-case": { + "node_modules/common-bin/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", - "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/common-bin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/common-bin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/common-bin/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/common-bin/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/common-bin/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/common-bin/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/common-bin/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/common-bin/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, + "node_modules/constant-case": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/constant-case/-/constant-case-2.0.0.tgz", + "integrity": "sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==", + "license": "MIT", + "dependencies": { "snake-case": "^2.1.0", "upper-case": "^1.1.1" } }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" } }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true, - "requires": { - "safe-buffer": "~5.1.1" + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "requires": { + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "license": "MIT", + "dependencies": { "depd": "~2.0.0", "keygrip": "~1.1.0" }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } + "engines": { + "node": ">= 0.8" } }, - "copy-descriptor": { + "node_modules/copy-descriptor": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "resolved": "https://mirrors.cloud.tencent.com/npm/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "copy-to": { + "node_modules/copy-to": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==", + "license": "MIT" }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true, + "license": "MIT" }, - "core-js-pure": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", - "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", - "dev": true + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "crc": { + "node_modules/crc": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/crc/-/crc-3.8.0.tgz", "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "requires": { + "license": "MIT", + "dependencies": { "buffer": "^5.1.0" } }, - "crequire": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/crequire/-/crequire-1.8.1.tgz", - "integrity": "sha1-rIHyBHhrXyARlOsWmM9EGxCktX0=", - "dev": true + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" }, - "cron-parser": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.16.3.tgz", - "integrity": "sha512-XNJBD1QLFeAMUkZtZQuncAAOgJFWNhBdIbwgD22hZxrcWOImBFMKgPC66GzaXpyoJs7UvYLLgPH/8BRk/7gbZg==", - "requires": { + "node_modules/crequire": { + "version": "1.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/crequire/-/crequire-1.8.1.tgz", + "integrity": "sha512-GbElTY148ZRQbC3E3XlMAitKE9rEyO/2mIkkjwgqzIucRmHiaAMF2Ynpwsuxzp08SdAbeN4pTrEqZs0MWRN6/w==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/cron-parser": { + "version": "2.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cron-parser/-/cron-parser-2.18.0.tgz", + "integrity": "sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==", + "license": "MIT", + "dependencies": { "is-nan": "^1.3.0", "moment-timezone": "^0.5.31" + }, + "engines": { + "node": ">=0.8" } }, - "cross-env": { + "node_modules/cross-env": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "requires": { + "license": "MIT", + "dependencies": { "cross-spawn": "^7.0.1" }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "csprng": { + "node_modules/csprng": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/csprng/-/csprng-0.1.2.tgz", - "integrity": "sha1-S8aPEvo2jSUqWYQcusqXSxirReI=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/csprng/-/csprng-0.1.2.tgz", + "integrity": "sha512-D3WAbvvgUVIqSxUfdvLeGjuotsB32bvfVPd+AaaTWMtyUeC9zgCnw5xs94no89yFLVsafvY9dMZEhTwsY/ZecA==", + "license": "MIT", + "dependencies": { "sequin": "*" + }, + "engines": { + "node": ">=0.6.0" } }, - "csrf": { + "node_modules/csrf": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/csrf/-/csrf-3.1.0.tgz", "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", - "requires": { + "license": "MIT", + "dependencies": { "rndm": "1.2.0", "tsscmp": "1.0.6", "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.8" } }, - "cssfilter": { + "node_modules/cssfilter": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" + "resolved": "https://mirrors.cloud.tencent.com/npm/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", + "license": "MIT" }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" } }, - "damerau-levenshtein": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", - "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", - "dev": true + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" }, - "dargs": { + "node_modules/dargs": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.1.0.tgz", - "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/dargs/-/dargs-6.1.0.tgz", + "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } }, - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==" + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "debounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", - "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { "ms": "^2.1.1" } }, - "decamelize": { + "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "resolved": "https://mirrors.cloud.tencent.com/npm/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" }, - "default-user-agent": { + "node_modules/default-user-agent": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", - "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==", + "license": "MIT", + "dependencies": { "os-name": "~1.0.3" + }, + "engines": { + "node": ">= 0.10.0" } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "define-property": { + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">=0.10.0" } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" } }, - "delayed-stream": { + "node_modules/delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "resolved": "https://mirrors.cloud.tencent.com/npm/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "denque": { + "node_modules/denque": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" } }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "requires": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==", + "dev": true, + "license": "MIT", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/detect-port/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "dicer": { + "node_modules/dicer": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "dependencies": { "readable-stream": "1.1.x", "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", - "dev": true - }, - "digest-header": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz", - "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", - "requires": { - "utility": "0.1.11" }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/digest-header": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/digest-header/-/digest-header-1.1.0.tgz", + "integrity": "sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==", + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/dir-glob": { + "version": "2.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "license": "MIT", "dependencies": { - "utility": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz", - "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", - "requires": { - "address": ">=0.0.1" - } - } - } - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "requires": { - "arrify": "^1.0.1", "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "doctrine": { + "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "dot-case": { + "node_modules/dot-case": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", - "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/dot-case/-/dot-case-2.1.1.tgz", + "integrity": "sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0" } }, - "dot-prop": { + "node_modules/dot-prop": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/dot-prop/-/dot-prop-4.2.1.tgz", "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "is-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } }, - "duplexify": { + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/duplexify": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "requires": { + "license": "MIT", + "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "each-parallel-async": { + "node_modules/duplexify/node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/each-parallel-async/-/each-parallel-async-1.0.0.tgz", - "integrity": "sha512-P/9kLQiQj0vZNzphvKKTgRgMnlqs5cJsxeAiuog1jrUnwv0Z3hVUwJDQiP7MnLb2I9S15nR9SRUceFT9IxtqRg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, - "eastasianwidth": { + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, - "ecc-jsbn": { + "node_modules/ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "ee-first": { + "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, - "egg": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/egg/-/egg-2.28.0.tgz", - "integrity": "sha512-vFzVx7iX+eegE+EXEaPY0N3tsLYuN6tXGOAw4MsFjjSZvswEIo9tKnYo6C5DE9EFxEPArkYuVwx07x4IolypjQ==", - "requires": { + "node_modules/egg": { + "version": "2.37.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg/-/egg-2.37.0.tgz", + "integrity": "sha512-PQU6Z9cji4Q2eV+1pyO4BLdnszDUyPZkj3v7RfMIACzYFcEKHj3agdTrjtpI74zNZqhO6LWOqvEKIgC+37v1lA==", + "license": "MIT", + "dependencies": { "@types/accepts": "^1.3.5", "@types/koa": "^2.0.48", "@types/koa-router": "^7.0.40", @@ -3677,6 +5630,7 @@ "egg-cookies": "^2.3.0", "egg-core": "^4.18.0", "egg-development": "^2.4.2", + "egg-errors": "^2.3.0", "egg-i18n": "^2.0.0", "egg-jsonp": "^2.0.0", "egg-logger": "^2.3.2", @@ -3690,7 +5644,7 @@ "egg-view": "^2.1.2", "egg-watcher": "^3.1.0", "extend2": "^1.0.0", - "graceful": "^1.0.2", + "graceful": "^1.1.0", "humanize-ms": "^1.2.1", "is-type-of": "^1.2.1", "koa-bodyparser": "^4.2.1", @@ -3704,446 +5658,739 @@ "urllib": "^2.33.0", "utility": "^1.15.0", "ylru": "^1.2.1" + }, + "engines": { + "node": ">= 8.5.0" } }, - "egg-alinode": { + "node_modules/egg-alinode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/egg-alinode/-/egg-alinode-2.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-alinode/-/egg-alinode-2.0.1.tgz", "integrity": "sha512-ZzZdFITE8qlZ+W4yFzKYCCieKPV8CqNRIfDCxtq+0OEQZiYVv4FBUTTsr2AII5Dx5e1NbmS22HG5jEx97NEZQw==", - "requires": { + "dependencies": { "agentx": "^1.8.4", "commandx": "^1.3.3", "mkdirp": "^0.5.1", "moment": "^2.17.1", "mz": "^2.6.0", "node-homedir": "^1.1.0" + }, + "engines": { + "node": ">=6.0.0" } }, - "egg-bin": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/egg-bin/-/egg-bin-4.15.0.tgz", - "integrity": "sha512-g+u7B1bRZpi1EMYNGN6YZlCWQsntoq05yDRLSxWNL5bC2bj7PLaPiUEnM1kS4qLJz5DJuwMGXzXJKsSvczeGYg==", + "node_modules/egg-bin": { + "version": "4.20.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-bin/-/egg-bin-4.20.0.tgz", + "integrity": "sha512-PVvJtt7XrUFeyo2ueGTzGgofN0EVLQSkv8lbRbuWyINQO9FQtjL6Wd4UGyno4xn4nUoIkeXjUiiOhbpessRusw==", "dev": true, - "requires": { - "autod": "^3.1.0", - "chalk": "^2.4.2", + "dependencies": { + "c8": "^7.11.0", + "chalk": "^4.1.1", "co-mocha": "^1.2.2", "common-bin": "^2.9.0", - "debug": "^4.1.1", + "debug": "^4.3.1", "detect-port": "^1.3.0", - "egg-ts-helper": "^1.25.2", + "egg-ts-helper": "^1.25.9", "egg-utils": "^2.4.1", - "espower-typescript": "9.0.1", + "espower-source": "^2.3.0", "globby": "^9.2.0", "inspector-proxy": "^1.2.1", - "intelli-espower-loader": "^1.0.1", - "jest-changed-files": "^24.7.0", + "intelli-espower-loader": "^1.1.0", + "jest-changed-files": "^25.5.0", + "minimatch": "^3.0.4", "mocha": "^6.0.2", "mz-modules": "^2.1.0", "nyc": "^13.3.0", "power-assert": "^1.6.1", - "semver": "^6.0.0", + "semver": "^7.3.5", + "source-map-support": "^0.5.19", "test-exclude": "^5.1.0", "ts-node": "^7", "ypkgfiles": "^1.6.0" }, + "bin": { + "c8": "bin/c8.js", + "egg-bin": "bin/egg-bin.js", + "ets": "bin/ets.js", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/egg-bin/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "egg-ts-helper": { - "version": "1.25.8", - "resolved": "https://registry.npmjs.org/egg-ts-helper/-/egg-ts-helper-1.25.8.tgz", - "integrity": "sha512-aRD1f4mP3ALqsqTcbET5vU1W5RCWNoGnP36QnIwW3qNb6qNRZo+czY0HjKpvOblzGKdcr+DIP0xEmp672lkJtQ==", - "dev": true, - "requires": { - "cache-require-paths": "^0.3.0", - "chalk": "^2.4.2", - "chokidar": "^2.0.1", - "commander": "^2.15.1", - "debug": "^3.1.0", - "dot-prop": "^4.2.0", - "enquirer": "^2.3.0", - "globby": "^8.0.1", - "mkdirp": "^0.5.1", - "ts-node": "^7.0.0", - "tslib": "^1.9.3", - "typescript": "^3.0.0", - "yn": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - } - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - }, - "dependencies": { - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/egg-bin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/egg-bin/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/egg-bin/node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/egg-bin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/egg-bin/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "optional": true } } }, - "egg-ci": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/egg-ci/-/egg-ci-1.18.0.tgz", - "integrity": "sha512-WqUG5vuSGsqNlBLD2uYB8rqXlC8J59ct+fuhbJFDZvSpvPQrNGqGOpcchMt/sAnOXLumtLHvlnltxvA9VhOsEA==", + "node_modules/egg-bin/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/egg-bin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/egg-bin/node_modules/he": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/egg-bin/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/egg-bin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/egg-bin/node_modules/mkdirp": { + "version": "0.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/egg-bin/node_modules/mocha": { + "version": "6.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.4", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/egg-bin/node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/egg-bin/node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/egg-bin/node_modules/mocha/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/egg-bin/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/egg-bin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/egg-bin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/egg-bin/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/egg-bin/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/egg-bin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-bin/node_modules/supports-color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-bin/node_modules/which": { + "version": "1.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/egg-bin/node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/egg-bin/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/egg-bin/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/egg-bin/node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-bin/node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-ci": { + "version": "1.19.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-ci/-/egg-ci-1.19.1.tgz", + "integrity": "sha512-evfuh7k4fQKjgN8uSsnybtITYPCbOrVIyAouq7ImbECAoaYk1vjeipoYyu66PPi9CjUZal0t2S6+MOPo799FjQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { "nunjucks": "^3.1.3" } }, - "egg-cluster": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/egg-cluster/-/egg-cluster-1.26.0.tgz", - "integrity": "sha512-+HJ2vT28HI+Dlt11/aJN2WpudvuJ/snwdsq5PAoyC61jl8SP4bhZQvAfojsEY1RVFctLq0ky4My0cujDk0SUlQ==", - "requires": { + "node_modules/egg-cluster": { + "version": "1.27.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-cluster/-/egg-cluster-1.27.1.tgz", + "integrity": "sha512-zKZV7WS5HwQYXU8TG5lwXe9+iQTw3jZYI4bMzLnRcOuxAhsx0fw1mgeR85Uj9WE+FP0/nexNNjcfFzb6jkzbsw==", + "license": "MIT", + "dependencies": { "await-event": "^2.1.0", "cfork": "^1.7.1", "cluster-reload": "^1.0.2", @@ -4162,45 +6409,56 @@ "sendmessage": "^1.1.0", "utility": "^1.15.0" }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/egg-cluster/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "egg-cookies": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/egg-cookies/-/egg-cookies-2.4.2.tgz", - "integrity": "sha512-NxGwoH+d62SHDfD8fOMdG2tmBwCKhHUnhUZRbMLKW7KbJx3JDxYZmGl9RkAtVJiEVwMWbEwj2WzJEgGwaQQfKQ==", - "requires": { - "debug": "^3.1.0", + "node_modules/egg-cluster/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/egg-cookies": { + "version": "2.10.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-cookies/-/egg-cookies-2.10.1.tgz", + "integrity": "sha512-fjlGF9jIu0GmU0bA+ZGOoz8OhbUECy18Y69wgpt8secmtaFzSbKay3DhKA13evqUDoiag5vQXQaN+N7Pp8vFsA==", + "license": "MIT", + "dependencies": { "scmp": "^2.0.0", "should-send-same-site-none": "^2.0.2", "utility": "^1.14.0" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">= 10.0.0" } }, - "egg-core": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/egg-core/-/egg-core-4.19.1.tgz", - "integrity": "sha512-oqIhXmJnm/m718fEHgD/7fKcDez9L3irXKNggANZP0KY1Xm9Op96ZiCtjvQ8Ao5D26yp7YEhcj8VqUOHOIcfWA==", - "requires": { + "node_modules/egg-core": { + "version": "4.31.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-core/-/egg-core-4.31.0.tgz", + "integrity": "sha512-qm80BhhXt3VbQQ70EW/t5UzD8FW7CO7w+JGNrv5L14QeglzCPMjMtgwT9BOPqDtGrI+TRhUrxxZjMiseslskMg==", + "license": "MIT", + "dependencies": { "@eggjs/router": "^2.0.0", "@types/depd": "^1.1.32", "@types/koa": "^2.0.48", @@ -4210,177 +6468,310 @@ "egg-logger": "^2.4.1", "egg-path-matching": "^1.0.1", "extend2": "^1.0.0", + "gals": "^1.0.2", "get-ready": "^2.0.1", - "globby": "^8.0.2", + "globby": "^10.0.2", "is-type-of": "^1.2.1", - "koa": "^2.7.0", + "koa": "^2.14.0", "koa-convert": "^1.2.0", "node-homedir": "^1.1.1", "ready-callback": "^2.1.0", + "tsconfig-paths": "^4.1.1", "utility": "^1.16.1" }, + "engines": { + "node": ">= 8.9.0" + } + }, + "node_modules/egg-core/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/egg-core/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "egg-cors": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/egg-cors/-/egg-cors-2.2.3.tgz", - "integrity": "sha512-MLG4pQekZpycLXR45ZAIgFpFYshosBxu1CMdhXAzqPzxUn0xI21gVzqLqcxUrzzulaErCwG6qMXaS1eFyj9u2w==", - "requires": { - "@koa/cors": "^3.0.0" + "node_modules/egg-core/node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "egg-development": { + "node_modules/egg-core/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/egg-core/node_modules/globby": { + "version": "10.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-core/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/egg-core/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-core/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-cors": { + "version": "2.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-cors/-/egg-cors-2.2.4.tgz", + "integrity": "sha512-6yc3pEbpZVLiCRdvR/Y+fT1sIO8/IldA31xQJeQDtgPrPWS99LXGyxWkszSovUS77yOpciSlcnpNoY9HAUP9hA==", + "dependencies": { + "@koa/cors": "^3.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/egg-development": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/egg-development/-/egg-development-2.7.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-development/-/egg-development-2.7.0.tgz", "integrity": "sha512-vPkC+Wngm/a48bj0rXpvTOmSjslBnygCsjBG7qahJ1PuCs0f10KrOGOGY9JzOW6KpfjKSPb+Y21mpzkxBJ9q2Q==", - "requires": { + "license": "MIT", + "dependencies": { "debounce": "^1.1.0", "multimatch": "^2.1.0", "mz": "^2.7.0", "mz-modules": "^2.1.0", "utility": "^1.13.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-http-proxy-middleware": { + "node_modules/egg-errors": { + "version": "2.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-errors/-/egg-errors-2.3.2.tgz", + "integrity": "sha512-E+Sx7IBVrfRyHSjFXaq4sCZ3Uk3ka9PYySaQ8VbRZmLEt9ENBCD99yVzLIeWUH2QfzvkrjY9El1eHmLeRx7cfw==", + "license": "MIT", + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/egg-http-proxy-middleware": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/egg-http-proxy-middleware/-/egg-http-proxy-middleware-1.0.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-http-proxy-middleware/-/egg-http-proxy-middleware-1.0.3.tgz", "integrity": "sha512-mS5MGg8sBNMaWGieJ8DJ/+f51dQTl303v7wvxSM+w4yE5AsQx8Lh9pIY2PpBk/OvvPBHpwEuMNU23tSH7qQcQQ==", - "requires": { + "license": "MIT", + "dependencies": { "http-proxy-middleware": "^1.0.4", "is-glob": "^4.0.1", "koa-connect": "^2.1.0", "micromatch": "^4.0.2" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } } }, - "egg-i18n": { + "node_modules/egg-i18n": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/egg-i18n/-/egg-i18n-2.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-i18n/-/egg-i18n-2.1.1.tgz", "integrity": "sha512-rpKP2nrUzeTOkjQObvlrLbb/BZAMtP7zeoGggwJLN9+zKbFKVkeF6Q0BrpuucDSekD+2oHQz7fC3w/5eQY1g8w==", - "requires": { + "license": "MIT", + "dependencies": { "debug": "^3.1.0", "koa-locales": "^1.11.0" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">= 8.0.0" } }, - "egg-jsonp": { + "node_modules/egg-jsonp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/egg-jsonp/-/egg-jsonp-2.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-jsonp/-/egg-jsonp-2.0.0.tgz", "integrity": "sha512-dno7BXAvSFO0WTb3GJD0aci9MFlaQhdgvEznwARam75GGJdLpg1K0XQq88/dEvYWHxEHa+iGIOXcNx5NOyyUHw==", - "requires": { + "license": "MIT", + "dependencies": { "is-type-of": "^1.2.0", "jsonp-body": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-logger": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/egg-logger/-/egg-logger-2.4.2.tgz", - "integrity": "sha512-HsZjAqafizTVujCkaBulT9b6Nrc5S97BvH30iXeFJz9eL2pHQpzsMCw5s1k5e1RxrvhidtNUX+avJmmfRpXnTQ==", - "requires": { + "node_modules/egg-logger": { + "version": "2.9.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-logger/-/egg-logger-2.9.1.tgz", + "integrity": "sha512-TPYdNthc7yGV+08A2U4g1T1wgRAjfTnsYC53JgfdKiYukaH3na1KPXEu+TEWni7IooqkFGkQ0t0WY+ylWFnvbw==", + "license": "MIT", + "dependencies": { "chalk": "^2.4.1", "circular-json-for-egg": "^1.0.0", "debug": "^2.6.9", "depd": "^2.0.0", + "egg-errors": "^2.2.0", "iconv-lite": "^0.4.24", "mkdirp": "^0.5.1", "utility": "^1.15.0" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "engines": { + "node": ">=8.5.0" } }, - "egg-logrotator": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/egg-logrotator/-/egg-logrotator-3.1.0.tgz", - "integrity": "sha512-3kUmUO9UxFiiN4lSvRqzu44UjfTHYD3wqBKsQU7e5PtjSwdQTkbjSp4YvGcbaTlQp0Yp3i/aEc/rBcYH/e/gjw==", - "requires": { - "debug": "^4.1.1", + "node_modules/egg-logger/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-logger/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-logger/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/egg-logger/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/egg-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/egg-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/egg-logger/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-logrotator": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-logrotator/-/egg-logrotator-3.2.0.tgz", + "integrity": "sha512-2KYN4wwBd15FYbNtLxL7IoIkFL7JuHHA3eXWZd5zVKfWgeoy4J+oTnCLDixW1UhVIdehL0q1oQxEldWm5af1Eg==", + "license": "MIT", + "dependencies": { "moment": "^2.24.0", "mz": "^2.7.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-mock": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/egg-mock/-/egg-mock-3.25.1.tgz", - "integrity": "sha512-2euNxl9sQhdk7SWix2/yw/EWVqYLB1n4V1L9fOmqr0LViBZLeb/wrzXSAd6JJG0qj8ki5FHwxTzSTWxOtGUOfg==", + "node_modules/egg-mock": { + "version": "3.26.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-mock/-/egg-mock-3.26.0.tgz", + "integrity": "sha512-ip7OhhKrgXp8awgl3n8jUGc+06P5jjHPj0n/E49PFIt9LH7n8pLijqDbbH8cwYlyPUDI66NCbCbG1Br652j7ng==", "dev": true, - "requires": { + "dependencies": { "@types/power-assert": "^1.5.0", "@types/supertest": "^2.0.7", "await-event": "^2.1.0", @@ -4403,57 +6794,34 @@ "supertest": "^4.0.2", "urllib": "^2.33.3" }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/egg-mock/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", "dependencies": { - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - } - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "egg-multipart": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/egg-multipart/-/egg-multipart-2.10.3.tgz", - "integrity": "sha512-+Ce2RE7YzdUv6G2+u8ke+ZMkyqSfIC3g2lKhSA1zKVetcRJ8GNfxPCoSuEFJMoUePdsJofasnp0EvWYstTpVbw==", - "requires": { + "node_modules/egg-multipart": { + "version": "2.13.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-multipart/-/egg-multipart-2.13.1.tgz", + "integrity": "sha512-WZKJN3/6O0PKnSHvz22TSk7t8vWvEcexdhpb/zoKsKSoDAZgd0ffk3dy+dZR4+woePEth/gibHY8QZgp1CUFlA==", + "license": "MIT", + "dependencies": { "co-busboy": "^1.4.0", "egg-path-matching": "^1.0.1", "humanize-bytes": "^1.0.1", @@ -4461,45 +6829,57 @@ "mz": "^2.7.0", "mz-modules": "^2.1.0", "stream-wormhole": "^1.1.0", - "uuid": "^3.3.2" + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 8.0.0" } }, - "egg-onerror": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/egg-onerror/-/egg-onerror-2.1.0.tgz", - "integrity": "sha512-ujsqFfcXjWZPiYbZAz4bfaCribV6V3DkltYUvwiTV7Qi4g16w6+L9eMHk/eHq8+3Frlis8WT6CcJL0zKUDmLUQ==", - "requires": { - "cookie": "^0.3.1", + "node_modules/egg-onerror": { + "version": "2.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-onerror/-/egg-onerror-2.4.0.tgz", + "integrity": "sha512-btmUsP1m6H9awd1IaAlvlzqN+uIbUKzaxJ8ArZI71r5FQ9LShZGv2pOT5fhL9mSnGkrvHUsjb9I5KoX2AY63bA==", + "dependencies": { + "cookie": "^0.7.2", "koa-onerror": "^4.0.0", "mustache": "^2.3.0", "stack-trace": "^0.0.10" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-path-matching": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/egg-path-matching/-/egg-path-matching-1.0.1.tgz", - "integrity": "sha512-XhwWldfhbjKvdDE9kUA6ywxgcxcLFHNaNKP1VZAE9oYTcKGB+piEn99R18zZWvBbk7eXXKHcxT1PQYpqu9GR7A==", - "requires": { - "path-to-regexp": "^1.7.0" + "node_modules/egg-path-matching": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-path-matching/-/egg-path-matching-1.2.0.tgz", + "integrity": "sha512-u88hY0tH8GfWu4iocWFxux/abXvi7bh4lr/GIRlUHCTJFk8RQNCCfk5H3Vm67pqTBljtBOCl0lLykOsxj8trXQ==", + "license": "MIT", + "dependencies": { + "path-to-regexp": "^1.9.0" } }, - "egg-schedule": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/egg-schedule/-/egg-schedule-3.6.5.tgz", - "integrity": "sha512-ARGF7XCEtZcWFk86aFqanFhoT/SClT+Y8/OImh2t4ERh81mESYG8XORjS8w4VMyRsIX64qi1fif+o94O8meK6g==", - "requires": { + "node_modules/egg-schedule": { + "version": "3.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-schedule/-/egg-schedule-3.7.0.tgz", + "integrity": "sha512-kXnqOOk+IpXpov9gpy4Bv1977iiwlk4kRNHPcp2O/Lp934tw9Lx1A2CDxv9lDrazhY7BqQFY7Nq+j8x74yog0w==", + "license": "MIT", + "dependencies": { "cron-parser": "^2.16.3", "humanize-ms": "^1.2.1", "is-type-of": "^1.2.1", "safe-timers": "^1.1.0", "utility": "^1.16.3" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-scripts": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/egg-scripts/-/egg-scripts-2.13.0.tgz", - "integrity": "sha512-oxFjb2V9G5EVIFWPK3EkQoAHV+eMDbBGi1FnOH32MkGP+IRe/Y/Nnj4jbuxzJzpwsLLYvtNEk3FRpokEOC3V3A==", - "requires": { + "node_modules/egg-scripts": { + "version": "2.17.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-scripts/-/egg-scripts-2.17.0.tgz", + "integrity": "sha512-2OHW0HuKKhOsl3yczYW6vcweyDrtFVOBccJ5xfuZRJOM3wTLRKAIfvXO/oNV1Mo0LSVuphhHiWmrUp481hcRXA==", + "license": "MIT", + "dependencies": { "await-event": "^2.1.0", "common-bin": "^2.8.0", "debug": "^4.1.0", @@ -4511,13 +6891,57 @@ "runscript": "^1.3.0", "source-map-support": "^0.5.9", "zlogger": "^1.1.0" + }, + "bin": { + "egg-scripts": "bin/egg-scripts.js", + "eggctl": "bin/egg-scripts.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "egg-security": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/egg-security/-/egg-security-2.8.0.tgz", - "integrity": "sha512-Qv+wwHy8C0x2IQzTUBzef+/G3fe5lkrOAKdAilDMbG5UADg+y9wGdJL7Nl3V23xB3lb3yQzJ//7mxngEWeQYJw==", - "requires": { + "node_modules/egg-scripts/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/egg-scripts/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/egg-scripts/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/egg-security": { + "version": "2.11.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-security/-/egg-security-2.11.0.tgz", + "integrity": "sha512-htXi+R5Ik8/oKSy55LzmpFDzrzxSHLpfjbDtgSMGKYGl4uNuvb3kN2h00sl1rOz3pG/LzJvZhqxW1oIBQ7leXg==", + "license": "MIT", + "dependencies": { "csrf": "^3.0.6", "debug": "^4.1.1", "delegates": "^1.0.0", @@ -4528,227 +6952,849 @@ "koa-compose": "^4.0.0", "matcher": "^1.1.1", "methods": "^1.1.2", - "nanoid": "^2.0.1", + "nanoid": "^3.3.2", "platform": "^1.3.4", "statuses": "^1.5.0", "type-is": "^1.6.15", "xss": "^1.0.3" }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/egg-security/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "egg-session": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/egg-session/-/egg-session-3.2.0.tgz", - "integrity": "sha512-YzwqYJoDZLzsMuev+yYPgpeQh2BSNImJtsoJ3W5IcvB0RU1Cmy3I805KMUY+Hsv3jc17AqyCFPUQIBLIO1WEYg==", - "requires": { + "node_modules/egg-security/node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "license": "MIT" + }, + "node_modules/egg-session": { + "version": "3.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-session/-/egg-session-3.3.0.tgz", + "integrity": "sha512-RCPWHLWi0Ak+xI/zXN71Wpva/wsqevmKDvkOGk2uu5UdwRHw5lKuTtYm161NMDGZi6lvcnzR2lN7xRcDuhGiIw==", + "dependencies": { "koa-session": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/egg-static/-/egg-static-2.2.0.tgz", - "integrity": "sha512-9Qzllp78ILUfnsnNIQD74xBzsmp5dF/iLMv/qKGPXRK8YefjzCn0UzKDhjSuw7BOH3or3VmEgI4U5zThPnuNUQ==", - "requires": { + "node_modules/egg-static": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-static/-/egg-static-2.3.1.tgz", + "integrity": "sha512-OODn2ccm4znFM/EdhiPUmIpgCkYvAdtjuVAy3N/Ub4cSRgqIPcjXajmDsbhEo43mCieukPhsOxgWD3vKZurzHQ==", + "license": "MIT", + "dependencies": { "is-type-of": "^1.2.1", "koa-compose": "^4.1.0", "koa-range": "^0.3.0", "koa-static-cache": "^5.1.2", - "mkdirp": "^0.5.1", - "ylru": "^1.2.1" + "ylru": "^1.3.2" }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/egg-static/node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "license": "MIT" + }, + "node_modules/egg-ts-helper": { + "version": "1.35.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-ts-helper/-/egg-ts-helper-1.35.2.tgz", + "integrity": "sha512-KSNjFt/7QjieFf56rhDnoL7kAJSp78rQwwRKNzg+P3caFGR1LHxkTU+GWjrJk2iZfYQrP/pUPQ7Q4BeQhxG4zA==", + "dev": true, + "license": "MIT", "dependencies": { - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + "chalk": "^2.4.2", + "chokidar": "^3.0.0", + "commander": "^2.15.1", + "dot-prop": "^4.2.0", + "enquirer": "^2.3.0", + "globby": "^11.0.0", + "json5": "^2.2.0", + "ts-node": "^10.9.1", + "tslib": "^2.0.0", + "typescript": "^4.0.0", + "yn": "^3.0.0" + }, + "bin": { + "ets": "dist/bin.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/egg-ts-helper/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/egg-ts-helper/node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/egg-ts-helper/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-ts-helper/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-ts-helper/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-ts-helper/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/egg-ts-helper/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/egg-ts-helper/node_modules/diff": { + "version": "4.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/egg-ts-helper/node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-ts-helper/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/egg-ts-helper/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/egg-ts-helper/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/egg-ts-helper/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/egg-ts-helper/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-ts-helper/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/egg-ts-helper/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/egg-ts-helper/node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true } } }, - "egg-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/egg-utils/-/egg-utils-2.4.1.tgz", - "integrity": "sha512-M7KIuzZdlN7AsL2mFvx0jpyEGcKTeQ5j+YT3eAhJOpBvBH9f4by2nKnb30huTRZIeJpjXWPdEzjGck/uj2N0jw==", - "requires": { + "node_modules/egg-ts-helper/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/egg-ts-helper/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/egg-utils": { + "version": "2.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-utils/-/egg-utils-2.5.0.tgz", + "integrity": "sha512-zQDXcqD0v+6IDBxcxzpTWoDTMg0G3iISSSeOHN7dZzyJWXXmw4ijBPAwKQPVvqBoXB6jAXj5f8B8/LVM9AN//A==", + "license": "MIT", + "dependencies": { "mkdirp": "^0.5.1", - "utility": "^1.13.1" + "utility": "^1.15.0" } }, - "egg-view": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/egg-view/-/egg-view-2.1.2.tgz", - "integrity": "sha512-C/EpRwjcstv/qaOJtpphNKeCgjd7AbHayqirY65eICG+0EaH4EiFUoh4b1WhIBiYNJHoV/DkkAW78Uiyr+XkEA==", - "requires": { + "node_modules/egg-view": { + "version": "2.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-view/-/egg-view-2.1.4.tgz", + "integrity": "sha512-8zJ/S7YU5SK3EbAYESlUCixLpDZPnyKimoowavrgW2vONnh8AJVuDGqgKCYmuymvWq3uaHoNx7mYbdMQwMTZ6A==", + "license": "MIT", + "dependencies": { "mz": "^2.7.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "egg-view-nunjucks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/egg-view-nunjucks/-/egg-view-nunjucks-2.2.0.tgz", - "integrity": "sha512-csuqQSFRpR1G+nu8OxDgHDba1v8RVJ8i4fadX66o73mnclKN6EXPdX9c9igegPeXXucUdDAPAHfJo6nZMJaghw==", - "requires": { - "nunjucks": "^3.1.2" + "node_modules/egg-view-nunjucks": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-view-nunjucks/-/egg-view-nunjucks-2.3.0.tgz", + "integrity": "sha512-f4WiE7PY60rW1Kr+7QAJyDr5Zo2VkXkczUkdRD/rnlUfWFpz8GAU1OBd/LsAdo9qFH9E0TJsozzkivnT7cyhfg==", + "license": "MIT", + "dependencies": { + "nunjucks": "^3.2.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "egg-watcher": { + "node_modules/egg-watcher": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/egg-watcher/-/egg-watcher-3.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-watcher/-/egg-watcher-3.1.1.tgz", "integrity": "sha512-fLo8f2GD9kSrAKeDoXaCckl9MaMMwTEkqU9gVDYWYGPYLsmX79ugA+Wo/2RGQkytsxSCk3bn8YqhPdMzsozgWA==", - "requires": { + "dependencies": { "camelcase": "^5.0.0", "sdk-base": "^3.5.0", "wt": "^1.2.0" + }, + "engines": { + "node": ">= 8.0.0" } }, - "egg-xtransit": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/egg-xtransit/-/egg-xtransit-1.2.2.tgz", - "integrity": "sha512-j9ygHMes3hn5ijFCZUp2W54CDsWGZSLSNOFW/zS7FpTRPZZc/255W21e5pp/Se1KlUvCV1FfBrntEc9OqcXmhw==", - "requires": { - "xprofiler": "^1.2.4", - "xtransit": "^1.2.0" + "node_modules/egg-watcher/node_modules/sdk-base": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/sdk-base/-/sdk-base-3.6.0.tgz", + "integrity": "sha512-jxHUIrRLlAoRFRwiXKhOGjd6BeFWO/jz7tv+E7lbMSef6F9jzFN2Sv3hLW58oDDKscKaBGG6vQdkbXn7isE7fw==", + "license": "MIT", + "dependencies": { + "await-event": "^2.1.0", + "await-first": "^1.0.0", + "co": "^4.6.0", + "is-type-of": "^1.2.1" } }, - "electron-to-chromium": { - "version": "1.3.570", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz", - "integrity": "sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg==", - "dev": true + "node_modules/egg-xtransit": { + "version": "1.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/egg-xtransit/-/egg-xtransit-1.2.4.tgz", + "integrity": "sha512-Y9v68tPci7qMHQ3fRfnZalRynbELIyKWDGm/ly+/zgWFif5V+wLTaEofJubAeGS/32WIbVlzB+JUfovMRDDChg==", + "license": "MIT", + "dependencies": { + "xprofiler": "^1.4.0", + "xtransit": "^1.4.0" + }, + "engines": { + "node": ">=10.0.0" + } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "node_modules/egg/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "empower": { + "node_modules/egg/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://mirrors.cloud.tencent.com/npm/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/empower": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/empower/-/empower-1.3.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/empower/-/empower-1.3.1.tgz", "integrity": "sha512-uB6/ViBaawOO/uujFADTK3SqdYlxYNn+N4usK9MRKZ4Hbn/1QSy8k2PezxCA2/+JGbF8vd/eOfghZ90oOSDZCA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "empower-core": "^1.2.0" } }, - "empower-assert": { + "node_modules/empower-assert": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/empower-assert/-/empower-assert-1.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/empower-assert/-/empower-assert-1.1.0.tgz", "integrity": "sha512-Ylck0Q6p8y/LpNzYeBccaxAPm2ZyuqBgErgZpO9KT0HuQWF0sJckBKCLmgS1/DEXEiyBi9XtYh3clZm5cAdARw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "estraverse": "^4.2.0" } }, - "empower-core": { + "node_modules/empower-assert/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/empower-core": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/empower-core/-/empower-core-1.2.0.tgz", "integrity": "sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "call-signature": "0.0.2", "core-js": "^2.0.0" } }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { "once": "^1.4.0" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, - "requires": { - "ansi-colors": "^4.1.1" + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" } }, - "eol": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", - "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/enquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/enquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eol": { + "version": "0.10.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/eol/-/eol-0.10.0.tgz", + "integrity": "sha512-+w3ktYrOphcIqC1XKmhQYvM+o2uxgQFiimL7B6JPZJlWVxf7Lno9e/JWLPIgbHo7DoZ+b7jsf/NzrUcNe6ZTZQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ryanve" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", + "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" } }, - "es6-iterator": { + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://mirrors.cloud.tencent.com/npm/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "resolved": "https://mirrors.cloud.tencent.com/npm/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, - "es6-map": { + "node_modules/es6-map": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "d": "1", "es5-ext": "~0.10.14", "es6-iterator": "~2.0.1", @@ -4757,137 +7803,179 @@ "event-emitter": "~0.3.5" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "node_modules/es6-set": { + "version": "0.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/es6-set/-/es6-set-0.1.6.tgz", + "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - }, + "license": "ISC", "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - } - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { "d": "^1.0.1", - "ext": "^1.1.2" + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" } }, - "es6-weak-map": { + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "d": "1", "es5-ext": "^0.10.46", "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.1" } }, - "escallmatch": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/escallmatch/-/escallmatch-1.5.0.tgz", - "integrity": "sha1-UAmdhugJGwkt+N37w/mm+wWgJNA=", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "requires": { - "call-matcher": "^1.0.0", - "esprima": "^2.0.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - } + "license": "MIT", + "engines": { + "node": ">=6" } }, - "escape-html": { + "node_modules/escallmatch": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/escallmatch/-/escallmatch-1.5.0.tgz", + "integrity": "sha512-iMF4I4I2E16DPusKDgTtQeIBNX0oOS53Ih6sr/2fh+1SDRsXvG8Y3ZOXGWlDkNNo066XBIkfaDRLfZpqcD+vGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-matcher": "^1.0.0", + "esprima": "^2.0.0" + } + }, + "node_modules/escallmatch/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } }, - "escodegen": { + "node_modules/escodegen": { "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/escodegen/-/escodegen-1.14.3.tgz", "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "requires": { + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "optionator": "^0.8.1" }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - } + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escope": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/escope/-/escope-3.6.0.tgz", + "integrity": "sha512-75IUQsusDdalQEW/G/2esa87J7raqdJF+Ca0/Xm5C3Q58Nr4yVYjZGp/P1+2xiEVgXRrA39dpRb8LcshajbqDQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { "es6-map": "^0.1.3", "es6-weak-map": "^2.0.1", "esrecurse": "^4.1.0", "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=0.4.0" } }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "node_modules/escope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "6.8.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", "chalk": "^2.1.0", @@ -4926,66 +8014,22 @@ "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "eslint-config-egg": { + "node_modules/eslint-config-egg": { "version": "8.1.2", - "resolved": "https://registry.npmjs.org/eslint-config-egg/-/eslint-config-egg-8.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-config-egg/-/eslint-config-egg-8.1.2.tgz", "integrity": "sha512-7mVlTBsQZNEheNNnTwHqbhho6js6EbgIHGKHy2qfWdd/Yr5mXMOD7buRjvEH/sy83x0b6+LsqhHa1JBeXbKj4A==", "dev": true, - "requires": { + "dependencies": { "@typescript-eslint/eslint-plugin": "^3.0.0", "@typescript-eslint/parser": "^3.0.0", "babel-eslint": "^8.2.6", @@ -4994,321 +8038,510 @@ "eslint-plugin-jsdoc": "^4.1.1", "eslint-plugin-jsx-a11y": "^6.1.1", "eslint-plugin-react": "^7.11.1" + }, + "engines": { + "node": ">=10.0.0" } }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, + "license": "MIT", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true } } }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-eggache": { + "node_modules/eslint-plugin-eggache": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-eggache/-/eslint-plugin-eggache-1.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-plugin-eggache/-/eslint-plugin-eggache-1.0.0.tgz", "integrity": "sha512-LPTrTvITFDZggiXAIdMPL4bJo0wvXUgJqC3f6UIskJxzHZze2aBTvjWQJ7TgEbkfpk++KWhcOl+lels+qAPKDg==", - "dev": true - }, - "eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - } + "license": "MIT", + "engines": { + "node": ">=6.0.0" } }, - "eslint-plugin-jsdoc": { + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc": { "version": "4.8.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-4.8.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-4.8.4.tgz", "integrity": "sha512-VDP+BI2hWpKNNdsJDSPofSQ9q7jGLgWbDMI0LzOeEcfsTjSS7jQtHDUuVLQ5E+OV2MPyQPk/3lnVcHfStXk5yA==", "dev": true, - "requires": { + "license": "BSD-3-Clause", + "dependencies": { "comment-parser": "^0.5.4", "jsdoctypeparser": "3.1.0", "lodash": "^4.17.11" - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz", - "integrity": "sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "aria-query": "^4.2.2", - "array-includes": "^3.1.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^3.5.4", - "axobject-query": "^2.1.2", - "damerau-levenshtein": "^1.0.6", - "emoji-regex": "^9.0.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "language-tags": "^1.0.5" }, - "dependencies": { - "emoji-regex": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.0.0.tgz", - "integrity": "sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==", - "dev": true - } + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": ">=4.14.0" } }, - "eslint-plugin-react": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz", - "integrity": "sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg==", + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.17.0", - "string.prototype.matchall": "^4.0.2" + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - } + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "eslint-scope": { + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "eslint-utils": { + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-utils/-/eslint-utils-1.4.3.tgz", "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" } }, - "eslint-visitor-keys": { + "node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=4" + } }, - "espower": { + "node_modules/eslint/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/eslint/node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/which": { + "version": "1.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/espower": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/espower/-/espower-2.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/espower/-/espower-2.1.2.tgz", "integrity": "sha512-2qa3aEFtcgPB782jTKDPu82hOdw8+zJsWdOn12Tey8XlexHTqsYUIdLC2B7cUECENXly0vZblH1CEZcqttPNjw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "array-find": "^1.0.0", "escallmatch": "^1.5.0", "escodegen": "^1.7.0", @@ -5320,48 +8553,43 @@ "type-name": "^2.0.0" } }, - "espower-loader": { + "node_modules/espower-loader": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/espower-loader/-/espower-loader-1.2.2.tgz", - "integrity": "sha1-7bRsPFmga6yOpzppXIblxaC8gto=", + "resolved": "https://mirrors.cloud.tencent.com/npm/espower-loader/-/espower-loader-1.2.2.tgz", + "integrity": "sha512-b2S362kHB3hDc8DIW7j3K6fIO+fMhwN+/1HimzmTRRe5Tl9Ox83WvVNjO4QL+HdplbSCw5VvHJpMIxgzEu+Rcw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "convert-source-map": "^1.1.0", "espower-source": "^2.0.0", "minimatch": "^3.0.0", "source-map-support": "^0.4.0", "xtend": "^4.0.0" }, - "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - } + "engines": { + "node": ">= 0.8.0" } }, - "espower-location-detector": { + "node_modules/espower-location-detector": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/espower-location-detector/-/espower-location-detector-1.0.0.tgz", - "integrity": "sha1-oXt+zFnTDheeK+9z+0E3cEyzMbU=", + "resolved": "https://mirrors.cloud.tencent.com/npm/espower-location-detector/-/espower-location-detector-1.0.0.tgz", + "integrity": "sha512-Y/3H6ytYwqC3YcOc0gOU22Lp3eI5GAFGOymTdzFyfaiglKgtsw2dePOgXY3yrV+QcLPMPiVYwBU9RKaDoh2bbQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "is-url": "^1.2.1", "path-is-absolute": "^1.0.0", "source-map": "^0.5.0", "xtend": "^4.0.0" } }, - "espower-source": { + "node_modules/espower-source": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/espower-source/-/espower-source-2.3.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/espower-source/-/espower-source-2.3.0.tgz", "integrity": "sha512-Wc4kC4zUAEV7Qt31JRPoBUc5jjowHRylml2L2VaDQ1XEbnqQofGWx+gPR03TZAPokAMl5dqyL36h3ITyMXy3iA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "acorn": "^5.0.0", "acorn-es7-plugin": "^1.0.10", "convert-source-map": "^1.1.1", @@ -5373,112 +8601,157 @@ "multi-stage-sourcemap": "^0.2.1", "path-is-absolute": "^1.0.0", "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.8.0", + "npm": ">=1.2.10" } }, - "espower-typescript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/espower-typescript/-/espower-typescript-9.0.1.tgz", - "integrity": "sha512-WmEm8Hs0SX06izEdi4Qlu3GPOgshejXXA22OA5i+9oN0yC9pWLxlomyPkNkksAQl+ZV5dOGyTdC4gBAEfwqBww==", + "node_modules/espower-source/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "requires": { - "espower-source": "^2.3.0", - "minimatch": "^3.0.3", - "source-map-support": "^0.5.9", - "ts-node": "^7.0.1" + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, - "espree": { + "node_modules/espower/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/espree/-/espree-6.2.1.tgz", "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "acorn": "^7.1.1", "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.1.0" }, - "dependencies": { - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", - "dev": true - } + "engines": { + "node": ">=6.0.0" } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + "node_modules/espree/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "espurify": { + "node_modules/espree/node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/espurify": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.8.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/espurify/-/espurify-1.8.1.tgz", "integrity": "sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0" } }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, - "requires": { + "license": "BSD-3-Clause", + "dependencies": { "estraverse": "^5.1.0" }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "engines": { + "node": ">=0.10" } }, - "esrecurse": { + "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "estraverse": "^5.2.0" }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "engines": { + "node": ">=4.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "license": "MIT", + "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, - "event-stream": { + "node_modules/event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "license": "MIT", + "dependencies": { "duplexer": "~0.1.1", "from": "~0", "map-stream": "~0.1.0", @@ -5488,30 +8761,41 @@ "through": "~2.3.1" } }, - "eventemitter3": { + "node_modules/eventemitter3": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "resolved": "https://mirrors.cloud.tencent.com/npm/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "node_modules/execa": { + "version": "3.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": "^8.12.0 || >=9.7.0" } }, - "expand-brackets": { + "node_modules/expand-brackets": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "license": "MIT", + "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", @@ -5520,81 +8804,110 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "engines": { + "node": ">=0.10.0" } }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { - "type": "^2.0.0" - }, + "license": "MIT", "dependencies": { - "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - } + "ms": "2.0.0" } }, - "extend": { + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "resolved": "https://mirrors.cloud.tencent.com/npm/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, - "extend-shallow": { + "node_modules/extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "extend2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/extend2/-/extend2-1.0.0.tgz", - "integrity": "sha1-BCWpibTawqSGoyJX9RQBA3Vqejw=" + "node_modules/extend2": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend2/-/extend2-1.0.1.tgz", + "integrity": "sha512-ISoKeVhtewd5YHzMo+r9KC3Zx0fdpNBqoRzot+6BeEQ3bWQYQQOt0jkkY5gLveI2e7j+vdCJKeszHJIbg2Uceg==", + "license": "MIT" }, - "external-editor": { + "node_modules/external-editor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" } }, - "extglob": { + "node_modules/extglob": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", @@ -5604,1880 +8917,171 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">=0.10.0" } }, - "extsprintf": { + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" }, - "fast-deep-equal": { + "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, - "fast-glob": { + "node_modules/fast-glob": { "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-2.2.7.tgz", "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "@mrmlnc/readdir-enhanced": "^2.2.1", "@nodelib/fs.stat": "^1.1.2", "glob-parent": "^3.1.0", "is-glob": "^4.0.0", "merge2": "^1.2.3", "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/fast-glob/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" + "license": "MIT", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { + "node_modules/fast-glob/node_modules/fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" - }, - "follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "dev": true - }, - "formstream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/formstream/-/formstream-1.1.0.tgz", - "integrity": "sha1-UfOXDyYTbrCtRDBN5M67UCB7RHk=", - "requires": { - "destroy": "^1.0.4", - "mime": "^1.3.4", - "pause-stream": "~0.0.11" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "optional": true - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "get-ready": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-2.0.1.tgz", - "integrity": "sha1-pIxBh1PjnPTQHzpCDPG3V93MZI8=", - "requires": { - "is-type-of": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { + "node_modules/fast-glob/node_modules/glob-parent": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "license": "ISC", + "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } } }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "graceful": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/graceful/-/graceful-1.0.2.tgz", - "integrity": "sha512-oRX5662cb/o89rj6R591DS7CGYB9A3vZKDI5ycmO0o6Ub56yM31LySCzIx8N1GHMcMq9J7JqaMLK5U7EIUWB6Q==", - "requires": { - "humanize-ms": "^1.2.1", - "ps-tree": "^1.1.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "graceful-process": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/graceful-process/-/graceful-process-1.2.0.tgz", - "integrity": "sha512-sH5WMY74gxObrKf+5SaqyI1sYv4AF1W5odeW+rA+kHuvKEiqaRgVIUKV2O/CT1NQr6zIhgbtEGOgJORjEHEcdw==", - "requires": { - "is-type-of": "^1.2.0", - "once": "^1.4.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/fast-glob/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, + "license": "MIT", "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-extglob": "^2.1.0" }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "engines": { + "node": ">=0.10.0" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "header-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", - "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=", - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.3" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "http-assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", - "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", - "requires": { - "deep-equal": "~1.0.1", - "http-errors": "~1.7.2" - }, - "dependencies": { - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } - } - }, - "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "http-proxy-middleware": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", - "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", - "requires": { - "@types/http-proxy": "^1.17.5", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "humanize-bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/humanize-bytes/-/humanize-bytes-1.0.1.tgz", - "integrity": "sha1-IfV8oxjSEaAG3JeYpGWE+vLZfpw=", - "requires": { - "bytes": "~2.2.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", - "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "inspector-proxy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/inspector-proxy/-/inspector-proxy-1.2.1.tgz", - "integrity": "sha512-/4X2XWYM2huvpQzSMuM3SLykvhpsS7LOnV5wKPNaOdXUBi6Vg1Aor5M4BBLnQ1Q7OdrgbbiQ3Ld8N3OFeW7voQ==", - "dev": true, - "requires": { - "cfork": "^1.6.1", - "debug": "^3.0.1", - "tcp-proxy.js": "^1.0.5", - "urllib": "^2.24.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "intelli-espower-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/intelli-espower-loader/-/intelli-espower-loader-1.0.1.tgz", - "integrity": "sha1-LHsDFGvB1GvyENCgOXxckatMorA=", - "dev": true, - "requires": { - "espower-loader": "^1.0.0" - } - }, - "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-buffer": { + "node_modules/fast-glob/node_modules/is-buffer": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" }, - "is-callable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", - "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", - "dev": true + "node_modules/fast-glob/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } }, - "is-class-hotfix": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", - "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { + "node_modules/fast-glob/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { "kind-of": "^3.0.2" }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "engines": { + "node": ">=0.10.0" } }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "node_modules/fast-glob/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "engines": { + "node": ">=0.10.0" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-generator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", - "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", - "dev": true - }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-lower-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", - "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", - "requires": { - "lower-case": "^1.1.0" - } - }, - "is-nan": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", - "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", - "requires": { - "define-properties": "^1.1.3" - } - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-type-of": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz", - "integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==", - "requires": { - "core-util-is": "^1.0.2", - "is-class-hotfix": "~0.0.6", - "isstream": "~0.1.2" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-upper-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", - "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", - "requires": { - "upper-case": "^1.1.0" - } - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsdoctypeparser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-3.1.0.tgz", - "integrity": "sha512-JNbkKpDFqbYjg+IU3FNo7qjX7Opy7CwjHywT32zgAcz/d4lX6Umn5jOHVETUdnNNgGrMk0nEx1gvP0F4M0hzlQ==", - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonp-body": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jsonp-body/-/jsonp-body-1.0.0.tgz", - "integrity": "sha1-5hD7b86nnPDMnye6p7Vjd9SwuzY=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "requires": { - "tsscmp": "1.0.6" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "ko-sleep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ko-sleep/-/ko-sleep-1.0.3.tgz", - "integrity": "sha1-KKKgoUhei39BX/SI3uF9JHiKsII=", - "requires": { - "ms": "^2.0.0" - } - }, - "koa": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz", - "integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==", - "requires": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.8.0", - "debug": "~3.1.0", - "delegates": "^1.0.0", - "depd": "^1.1.2", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^1.2.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "koa-bodyparser": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", - "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", - "requires": { - "co-body": "^6.0.0", - "copy-to": "^2.0.1" - } - }, - "koa-compose": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", - "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", - "requires": { - "any-promise": "^1.1.0" - } - }, - "koa-connect": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/koa-connect/-/koa-connect-2.1.0.tgz", - "integrity": "sha512-O9pcFafHk0oQsBevlbTBlB9co+2RUQJ4zCzu3qJPmGlGoeEZkne+7gWDkecqDPSbCtED6LmhlQladxs6NjOnMQ==" - }, - "koa-convert": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", - "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", - "requires": { - "co": "^4.6.0", - "koa-compose": "^3.0.0" - } - }, - "koa-is-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", - "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=" - }, - "koa-locales": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/koa-locales/-/koa-locales-1.12.0.tgz", - "integrity": "sha512-lalx0OuvdZ39JppTVqHnYKIgJJbByon9xpt5KSKFOL6/VQS+XBMklMX83+fgkCXzsNacynWaN75ihWP2EGsWIQ==", - "requires": { - "debug": "^2.6.0", - "humanize-ms": "^1.2.0", - "ini": "^1.3.4", - "object-assign": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "koa-onerror": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-onerror/-/koa-onerror-4.1.0.tgz", - "integrity": "sha512-UDvOkkXiyVtlhRIvo9wbqKG/pTiiVE5x2uIFpG5e6OmBawxBSURG/PeFa6e6UZjjxinXde3BmPWVSIVePMG6TA==", - "requires": { - "escape-html": "^1.0.3", - "stream-wormhole": "^1.1.0" - } - }, - "koa-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/koa-override/-/koa-override-3.0.0.tgz", - "integrity": "sha512-w2rWCfapbQUZ8TrRBarj6iwryCTooEcdw9lr1hYC1q4FnaCZcAOhpjB1VpqtbODALVMgY3JGlzLSeYRXc5Ky0Q==", - "requires": { - "methods": "^1.1.2" - } - }, - "koa-range": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", - "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", - "requires": { - "stream-slice": "^0.1.2" - } - }, - "koa-session": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/koa-session/-/koa-session-6.0.0.tgz", - "integrity": "sha512-mEj2ximzLqoypk0Q+/JLu0j7fuMk/fL+yiBM0RKmxBqdImKxq3hfnpHLwpMhwya05z/W8i7vawpFl+lsYTZbAg==", - "requires": { - "crc": "^3.4.4", - "debug": "^3.1.0", - "is-type-of": "^1.0.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "koa-static-cache": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/koa-static-cache/-/koa-static-cache-5.1.4.tgz", - "integrity": "sha512-abVWOHY6z6qSTvNtapWMAnvHS9SUiUCaQQQubClSAT9ybQPsZ6ioKcRarnownS4fMD0sXQgQ5ey8CYEuwoa1Yg==", - "requires": { - "compressible": "^2.0.6", - "debug": "^3.1.0", - "fs-readdir-recursive": "^1.0.0", - "mime-types": "^2.1.8", - "mz": "^2.7.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "language-subtag-registry": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", - "integrity": "sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "requires": { - "invert-kv": "^2.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "log4js": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-5.3.0.tgz", - "integrity": "sha512-PZHXaXJKMKEscvQxSnTjM4UosQalSDlNpMw63eCKW+/DiAFKIZPW1jGyIPXZDjiEYFusMfiI7zzvnxeGozUcAw==", - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.2" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" - }, - "lower-case-first": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", - "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", - "requires": { - "lower-case": "^1.1.2" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "matcher": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", - "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", - "requires": { - "escape-string-regexp": "^1.0.4" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-estraverse-visitors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/merge-estraverse-visitors/-/merge-estraverse-visitors-1.0.0.tgz", - "integrity": "sha1-65aDOLXe1c7tgs7AMH3sui2OqZQ=", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { + "node_modules/fast-glob/node_modules/micromatch": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", @@ -7492,242 +9096,3881 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/file-stream-rotator": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true } } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "mimic-fn": { + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/formstream": { + "version": "1.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/formstream/-/formstream-1.5.2.tgz", + "integrity": "sha512-NASf0lgxC1AyKNXQIrXTEYkiX99LhCEXTkiGObXAkpBui86a4u8FjH1o2bGb3PpqI3kafC+yw4zWeK6l6VHTgg==", + "license": "MIT", + "dependencies": { + "destroy": "^1.0.4", + "mime": "^2.5.2", + "node-hex": "^1.0.1", + "pause-stream": "~0.0.11" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", + "license": "MIT" + }, + "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "license": "MIT" }, - "minipass": { + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gals": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/gals/-/gals-1.0.2.tgz", + "integrity": "sha512-h5c1Q6Q2cnRkO2v8ZxbuFCNRpM96CjGxGuoNcThoNF3dAEEYagF166EqJmaa9r2/I+ryij8TO3yMmqrMvQ1YXw==", + "license": "MIT", + "engines": { + "node": ">= 16.0.0" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-ready": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-ready/-/get-ready-2.0.1.tgz", + "integrity": "sha512-q2zoHPGbHognNvofksty0SOrviWowfUVxYcv3j3+Mf1BRRMHmq6q/1pciravEf8jkSL5iovloMWnonEc2QOpqA==", + "license": "MIT", + "dependencies": { + "is-type-of": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true, + "license": "BSD" + }, + "node_modules/globals": { + "version": "9.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "9.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/graceful/-/graceful-1.1.0.tgz", + "integrity": "sha512-sImEQVLLBo8hSeX4Vp6HVdWSdqCkHoVlZwBuBL65tNwcPTvnMaW40iWs1vdCbyP0znkCEuvv6rZ37QPloPi9Fw==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1", + "ps-tree": "^1.1.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graceful-process": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-process/-/graceful-process-1.3.0.tgz", + "integrity": "sha512-tlldpcdxQgSgVD/A+OawlyjGU9Z+wbBTI6QroGo4u6znQNLgglp+V2KnixRHUXRttnrCpbQSSCJ6wvsMkzR9Aw==", + "license": "MIT", + "dependencies": { + "is-type-of": "^1.2.0", + "once": "^1.4.0" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.x" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/he/-/he-1.1.1.tgz", + "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/header-case": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/header-case/-/header-case-1.0.1.tgz", + "integrity": "sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==", + "license": "MIT", + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.3" + } + }, + "node_modules/home-or-tmp": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "license": "MIT", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware": { + "version": "1.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", + "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/humanize-bytes": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/humanize-bytes/-/humanize-bytes-1.0.1.tgz", + "integrity": "sha512-OZMIHt5YhQM4S3R82KGoKnWv4vaNnWuEhPAK+u5v7rD2tRM3DU2NghYEHipAPYwyTR6+fMVZQ9ETpZIZeZUapQ==", + "license": "MIT", + "dependencies": { + "bytes": "~2.2.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==", + "dev": true + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC" + }, + "node_modules/inflation": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/inflation/-/inflation-2.1.0.tgz", + "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ], + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inspector-proxy": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/inspector-proxy/-/inspector-proxy-1.2.3.tgz", + "integrity": "sha512-5YkxR72v8oVpSE3nL3dhpO2WNS9Gg1Pp1mWulC1BCNNG8g+SiDzuJTkUgM3xckUmz6jS0YOSpgcYM6fJxbz5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cfork": "^1.6.1", + "debug": "^3.0.1", + "tcp-proxy.js": "^1.0.5", + "urllib": "^2.24.0" + }, + "bin": { + "inspector-proxy": "bin/bin.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/intelli-espower-loader": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/intelli-espower-loader/-/intelli-espower-loader-1.1.0.tgz", + "integrity": "sha512-GmnpIM5tRU5n8R4bQAcu2gJMlfRukrtklbE1auRN8qGK9KSLboGdmHSLSLLnIHKrnRmgWRBXNqy5sIOrbT2l8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "espower-loader": "^1.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ip": { + "version": "1.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "license": "MIT" + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha512-G56jBpbJeg7ds83HW1LuShNs8J73Fv3CPz/bmROHOHlnKkN8sWb9ujiagjmxxMUywftgq48HlBZELKKqFLk0oA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT" + }, + "node_modules/is-lower-case": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-lower-case/-/is-lower-case-1.1.3.tgz", + "integrity": "sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==", + "license": "MIT", + "dependencies": { + "lower-case": "^1.1.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-type-of": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-type-of/-/is-type-of-1.4.0.tgz", + "integrity": "sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==", + "license": "MIT", + "dependencies": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-upper-case": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-upper-case/-/is-upper-case-1.1.2.tgz", + "integrity": "sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==", + "license": "MIT", + "dependencies": { + "upper-case": "^1.1.0" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-instrument/node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jest-changed-files": { + "version": "25.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jest-changed-files/-/jest-changed-files-25.5.0.tgz", + "integrity": "sha512-EOw9QEqapsDT7mKF162m8HFzRPbmP8qJQny6ldVOdOVBz3ACgPm/1nAn5fPQ/NDaYhX/AHkrGwwkCncpAVSXcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^25.5.0", + "execa": "^3.2.0", + "throat": "^5.0.0" + }, + "engines": { + "node": ">= 8.3" + } + }, + "node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, + "node_modules/jsdoctypeparser": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsdoctypeparser/-/jsdoctypeparser-3.1.0.tgz", + "integrity": "sha512-JNbkKpDFqbYjg+IU3FNo7qjX7Opy7CwjHywT32zgAcz/d4lX6Umn5jOHVETUdnNNgGrMk0nEx1gvP0F4M0hzlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/jsesc": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/json5": { + "version": "0.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonp-body": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsonp-body/-/jsonp-body-1.1.0.tgz", + "integrity": "sha512-ZQyNWgHI8vvqclzz0l4/PatmeGureejrdMiLQGxTupMw0yQMHf+pQwS/7d5tpo2NBHsuwLCmXvZeNiz2RKdklA==", + "license": "MIT", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/kareem": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/kareem/-/kareem-2.3.1.tgz", + "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==", + "license": "Apache-2.0" + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ko-sleep": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/ko-sleep/-/ko-sleep-1.1.4.tgz", + "integrity": "sha512-s05WGpvvzyTuRlRE8fM7ru2Z3O+InbJuBcckTWKg2W+2c1k6SnFa3IfiSSt0/peFrlYAXgNoxuJWWVNmWh+K/A==", + "license": "MIT", + "dependencies": { + "ms": "*" + } + }, + "node_modules/koa": { + "version": "2.16.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa/-/koa-2.16.4.tgz", + "integrity": "sha512-3An0GCLDSR34tsCO4H8Tef8Pp2ngtaZDAZnsWJYelqXUK5wyiHvGItgK/xcSkmHLSTn1Jcho1mRQs2ehRzvKKw==", + "license": "MIT", + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.9.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-bodyparser": { + "version": "4.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-bodyparser/-/koa-bodyparser-4.4.1.tgz", + "integrity": "sha512-kBH3IYPMb+iAXnrxIhXnW+gXV8OTzCu8VPDqvcDHW9SQrbkHmqPQtiZwrltNmSq6/lpipHnT7k7PsjlVD7kK0w==", + "license": "MIT", + "dependencies": { + "co-body": "^6.0.0", + "copy-to": "^2.0.1", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/koa-compose": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-compose/-/koa-compose-3.2.1.tgz", + "integrity": "sha512-8gen2cvKHIZ35eDEik5WOo8zbVp9t4cP8p4hW4uE55waxolLRexKKrqfCpwhGVppnB40jWeF8bZeTVg99eZgPw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.1.0" + } + }, + "node_modules/koa-connect": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-connect/-/koa-connect-2.1.1.tgz", + "integrity": "sha512-ejvbGKYS6di4LUSS+6E+Z5ZVev9RqThLm3NfZjb9QHZMASLvnr4eDTImKcGlQXFrtVpMTyTovZ+Hcl6JbBuFNA==", + "license": "MIT" + }, + "node_modules/koa-convert": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-convert/-/koa-convert-1.2.0.tgz", + "integrity": "sha512-K9XqjmEDStGX09v3oxR7t5uPRy0jqJdvodHa6wxWTHrTfDq0WUNnYTOOUZN6g8OM8oZQXprQASbiIXG2Ez8ehA==", + "license": "MIT", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^3.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/koa-is-json": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==", + "license": "MIT" + }, + "node_modules/koa-locales": { + "version": "1.12.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-locales/-/koa-locales-1.12.0.tgz", + "integrity": "sha512-lalx0OuvdZ39JppTVqHnYKIgJJbByon9xpt5KSKFOL6/VQS+XBMklMX83+fgkCXzsNacynWaN75ihWP2EGsWIQ==", + "license": "MIT", + "dependencies": { + "debug": "^2.6.0", + "humanize-ms": "^1.2.0", + "ini": "^1.3.4", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/koa-locales/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/koa-locales/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/koa-onerror": { + "version": "4.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-onerror/-/koa-onerror-4.2.0.tgz", + "integrity": "sha512-D15tp5rxevHqqcvOiEDbtQolG6z3NpBNupz3EUZz43pjYv5SGMom2Xz1FKM8oTya56+aq+hejPW/iBrNnC/UGQ==", + "license": "MIT", + "dependencies": { + "escape-html": "^1.0.3", + "stream-wormhole": "^1.1.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/koa-override": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-override/-/koa-override-3.0.0.tgz", + "integrity": "sha512-w2rWCfapbQUZ8TrRBarj6iwryCTooEcdw9lr1hYC1q4FnaCZcAOhpjB1VpqtbODALVMgY3JGlzLSeYRXc5Ky0Q==", + "license": "MIT", + "dependencies": { + "methods": "^1.1.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/koa-range": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-range/-/koa-range-0.3.0.tgz", + "integrity": "sha512-Ich3pCz6RhtbajYXRWjIl6O5wtrLs6kE3nkXc9XmaWe+MysJyZO7K4L3oce1Jpg/iMgCbj+5UCiMm/rqVtcDIg==", + "license": "MIT", + "dependencies": { + "stream-slice": "^0.1.2" + }, + "engines": { + "node": ">=7" + } + }, + "node_modules/koa-session": { + "version": "6.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-session/-/koa-session-6.4.0.tgz", + "integrity": "sha512-h/dxmSOvNEXpHQPRs4TV03TZVFyZIjmYQiTAW5JBFTYBOZ0VdpZ8QEE6Dud75g8z9JNGXi3m++VqRmqToB+c2A==", + "license": "MIT", + "dependencies": { + "crc": "^3.8.0", + "debug": "^4.3.3", + "is-type-of": "^1.2.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/koa-session/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/koa-static-cache": { + "version": "5.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-static-cache/-/koa-static-cache-5.1.4.tgz", + "integrity": "sha512-abVWOHY6z6qSTvNtapWMAnvHS9SUiUCaQQQubClSAT9ybQPsZ6ioKcRarnownS4fMD0sXQgQ5ey8CYEuwoa1Yg==", + "license": "MIT", + "dependencies": { + "compressible": "^2.0.6", + "debug": "^3.1.0", + "fs-readdir-recursive": "^1.0.0", + "mime-types": "^2.1.8", + "mz": "^2.7.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/koa/node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "license": "MIT" + }, + "node_modules/koa/node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "license": "MIT", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://mirrors.cloud.tencent.com/npm/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://mirrors.cloud.tencent.com/npm/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "license": "MIT" + }, + "node_modules/lower-case-first": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/lower-case-first/-/lower-case-first-1.0.2.tgz", + "integrity": "sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==", + "license": "MIT", + "dependencies": { + "lower-case": "^1.1.2" + } + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matcher": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/matcher/-/matcher-1.1.1.tgz", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT", + "optional": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-estraverse-visitors": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge-estraverse-visitors/-/merge-estraverse-visitors-1.0.0.tgz", + "integrity": "sha512-YcT59TImpdL2qe+I7OWI+ESjBVov9CWTQjK9Issk58BNQzyputg2s8wOE+DDvxtgmPHG4L6xAl0yAwbNCyXszg==", + "dev": true, + "license": "MIT", + "dependencies": { + "estraverse": "^4.0.0" + } + }, + "node_modules/merge-estraverse-visitors/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { "yallist": "^4.0.0" }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } + "engines": { + "node": ">=8" } }, - "minizlib": { + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { + "license": "MIT", + "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } + "engines": { + "node": ">= 8" } }, - "mixin-deep": { + "node_modules/mixin-deep": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "mm": { + "node_modules/mm": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mm/-/mm-2.5.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mm/-/mm-2.5.0.tgz", "integrity": "sha512-ilm+lGEBNm7Cw45um9ax0tbApiNwQV3PY6Yk1ol+wtA8c98hHuJqTgmdKB6rYQJTUC2QrhBfoWwN+/766ZlrYA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "is-type-of": "^1.0.0", "ko-sleep": "^1.0.2", "muk-prop": "^1.0.0", "thenify": "^3.2.1" - } - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, - "moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "mongoose-transactions": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", - "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "muk-prop": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/muk-prop/-/muk-prop-1.2.1.tgz", - "integrity": "sha512-NdkOVav3GoIkBZqMUneU435HW0a90zitpuO1erPRhOQdPtl65dXD3G9/1k46G6/0ZMau4CJFFUHkMKVsyNZT+w==", - "dev": true - }, - "multi-stage-sourcemap": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", - "integrity": "sha1-sJ/IWG6qF/gdV1xK0C4Pej9rEQU=", - "dev": true, - "requires": { - "source-map": "^0.1.34" }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mocha": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/mocha/node_modules/commander": { + "version": "2.15.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "5.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://mirrors.cloud.tencent.com/npm/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "3.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "license": "Apache-2.0", + "dependencies": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4" + }, + "optionalDependencies": { + "saslprep": "^1.0.0" + }, + "peerDependenciesMeta": { + "aws4": { + "optional": true + }, + "bson-ext": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "mongodb-extjson": { + "optional": true + }, + "snappy": { + "optional": true } } }, - "multimatch": { + "node_modules/mongoose": { + "version": "5.10.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose/-/mongoose-5.10.18.tgz", + "integrity": "sha512-vaLUzBpUxqacoCqP/xXWMg/uVwCDrlc8LvYjDXCf8hdApvX/CXa0HLa7v2ieFaVd5Fgv3W2QXODLoC4Z/abbNw==", + "license": "MIT", + "dependencies": { + "bson": "^1.1.4", + "kareem": "2.3.1", + "mongodb": "3.6.3", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.7.0", + "mquery": "3.2.2", + "ms": "2.1.2", + "regexp-clone": "1.0.0", + "safe-buffer": "5.2.1", + "sift": "7.0.1", + "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "mongoose": "*" + } + }, + "node_modules/mongoose-transactions": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mongoose-transactions/-/mongoose-transactions-1.1.4.tgz", + "integrity": "sha512-ktEQPjMju7YJSmE2MtnUkTYFHYRWLPyByrm6VvhkD+16t2ghkvitO+q7OtGP4rGjP6ggip45sjhmYJOJYqIpiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "mongoose": ">=4.11.1" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/mpath": { + "version": "0.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mpath/-/mpath-0.7.0.tgz", + "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/mquery/-/mquery-3.2.2.tgz", + "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", + "license": "MIT", + "dependencies": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/mquery/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/muk-prop": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/muk-prop/-/muk-prop-1.2.1.tgz", + "integrity": "sha512-NdkOVav3GoIkBZqMUneU435HW0a90zitpuO1erPRhOQdPtl65dXD3G9/1k46G6/0ZMau4CJFFUHkMKVsyNZT+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/multi-stage-sourcemap": { + "version": "0.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", + "integrity": "sha512-umaOM+8BZByZIB/ciD3dQLzTv50rEkkGJV78ta/tIVc/J/rfGZY5y1R+fBD3oTaolx41mK8rRcyGtYbDXlzx8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "^0.1.34" + } + }, + "node_modules/multi-stage-sourcemap/node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/multimatch": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha512-0mzK8ymiWdehTBiJh0vClAzGyQbdtyWqzSVx//EK4N/D+599RFlGfTAsKw2zMSABtDG9C6Ul2+t8f2Lbdjf5mA==", + "license": "MIT", + "dependencies": { "array-differ": "^1.0.0", "array-union": "^1.0.1", "arrify": "^1.0.0", "minimatch": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "mustache": { + "node_modules/mustache": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", - "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/mustache/-/mustache-2.3.2.tgz", + "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + }, + "engines": { + "npm": ">=1.4.0" + } }, - "mute-stream": { + "node_modules/mute-stream": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "dev": true, + "license": "ISC" }, - "mz": { + "node_modules/mz": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { + "license": "MIT", + "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, - "mz-modules": { + "node_modules/mz-modules": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mz-modules/-/mz-modules-2.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/mz-modules/-/mz-modules-2.1.0.tgz", "integrity": "sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==", - "requires": { + "license": "MIT", + "dependencies": { "glob": "^7.1.2", "ko-sleep": "^1.0.3", "mkdirp": "^0.5.1", "pump": "^3.0.0", "rimraf": "^2.6.1" + }, + "engines": { + "node": ">=6.0.0" } }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true + "node_modules/mz-modules/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } }, - "nanoid": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", - "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" + "node_modules/nan": { + "version": "2.25.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/nan/-/nan-2.25.0.tgz", + "integrity": "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==", + "license": "MIT" }, - "nanomatch": { + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", @@ -7740,191 +12983,479 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "natural-compare": { + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" }, - "ndir": { + "node_modules/ndir": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/ndir/-/ndir-0.1.5.tgz", - "integrity": "sha1-EgiR12l7u+ghTP7/CWAgYNNFRVg=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, - "nmtree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/nmtree/-/nmtree-1.0.6.tgz", - "integrity": "sha512-SUPCoyX5w/lOT6wD/PZEymR+J899984tYEOYjuDqQlIOeX5NSb1MEsCcT0az+dhZD0MLAj5hGBZEpKQxuDdniA==", - "requires": { - "commander": "^2.11.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/ndir/-/ndir-0.1.5.tgz", + "integrity": "sha512-GEdViSiVHi63HASUGaQXNBbUNe5KDnuAYvOGBlY7y+CCCRT3NBeMWQlODb2GVV2cKwEIwHzo9KOCMsPBXlKsOg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "no-case": { + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nmtree": { + "version": "1.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/nmtree/-/nmtree-1.0.6.tgz", + "integrity": "sha512-SUPCoyX5w/lOT6wD/PZEymR+J899984tYEOYjuDqQlIOeX5NSb1MEsCcT0az+dhZD0MLAj5hGBZEpKQxuDdniA==", + "license": "MIT", + "dependencies": { + "commander": "^2.11.0" + }, + "bin": { + "nmtree": "bin/nmtree.js" + } + }, + "node_modules/no-case": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/no-case/-/no-case-2.3.2.tgz", "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "requires": { + "license": "MIT", + "dependencies": { "lower-case": "^1.1.1" } }, - "node-environment-flags": { + "node_modules/node-environment-flags": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" - }, + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true } } }, - "node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", - "requires": { - "whatwg-url": "^5.0.0" + "node_modules/node-gyp": { + "version": "9.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" } }, - "node-homedir": { + "node_modules/node-gyp/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/node-gyp/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-hex": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-hex/-/node-hex-1.0.1.tgz", + "integrity": "sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/node-homedir": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-homedir/-/node-homedir-1.1.1.tgz", - "integrity": "sha512-Xsmf94D/DdeDISAECUaxXVxhh+kHdbOQE4CnP4igo3HXL3BSmmUpD5M7orH434EZZwBTFF2xe5SgsQr/wOBuNw==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" + "resolved": "https://mirrors.cloud.tencent.com/npm/node-homedir/-/node-homedir-1.1.1.tgz", + "integrity": "sha512-Xsmf94D/DdeDISAECUaxXVxhh+kHdbOQE4CnP4igo3HXL3BSmmUpD5M7orH434EZZwBTFF2xe5SgsQr/wOBuNw==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" } }, - "normalize-package-data": { + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, - "normalize-path": { + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "nounou": { + "node_modules/nounou": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/nounou/-/nounou-1.2.1.tgz", - "integrity": "sha1-qQR++kQF4m7H52iHW9JYD8Sl8I8=" - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/nounou/-/nounou-1.2.1.tgz", + "integrity": "sha512-eoFoZGmZ8RaHG8hVtcfhdqPea4TC4U0UcKyRtFEi9pCLkhqz/tg5FB+wSreLHY3y9B5cxa2vA5I7BLYiME3Jow==", + "license": "MIT", + "bin": { + "nounou": "bin/nounou" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "number-is-nan": { + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "resolved": "https://mirrors.cloud.tencent.com/npm/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "nunjucks": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", - "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", - "requires": { + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { "a-sync-waterfall": "^1.0.0", "asap": "^2.0.3", - "chokidar": "^3.3.0", "commander": "^5.1.0" }, - "dependencies": { - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true } } }, - "nyc": { + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/nyc": { "version": "13.3.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/nyc/-/nyc-13.3.0.tgz", "integrity": "sha512-P+FwIuro2aFG6B0Esd9ZDWUd51uZrAEoGutqZxzrVmYl3qSfkLgcQpBPBjtDFsUQLFY1dvTQJPOyeqr8S9GF8w==", + "bundleDependencies": [ + "archy", + "arrify", + "caching-transform", + "convert-source-map", + "find-cache-dir", + "find-up", + "foreground-child", + "glob", + "istanbul-lib-coverage", + "istanbul-lib-hook", + "istanbul-lib-report", + "istanbul-lib-source-maps", + "istanbul-reports", + "make-dir", + "merge-source-map", + "resolve-from", + "rimraf", + "signal-exit", + "spawn-wrap", + "test-exclude", + "uuid", + "yargs", + "yargs-parser" + ], "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "archy": "^1.0.0", "arrify": "^1.0.1", "caching-transform": "^3.0.1", @@ -7950,1494 +13481,2134 @@ "yargs": "^12.0.5", "yargs-parser": "^11.1.1" }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "append-transform": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "default-require-extensions": "^2.0.0" - } - }, - "archy": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "arrify": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "async": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "caching-transform": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "hasha": "^3.0.0", - "make-dir": "^1.3.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.3.0" - } - }, - "camelcase": { - "version": "5.0.0", - "bundled": true, - "dev": true - }, - "cliui": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "commander": { - "version": "2.17.1", - "bundled": true, - "dev": true, - "optional": true - }, - "commondir": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cross-spawn": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "default-require-extensions": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "strip-bom": "^3.0.0" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "bundled": true, - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es6-error": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "execa": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "bundled": true, - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "find-cache-dir": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "foreground-child": { - "version": "1.5.6", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.15", - "bundled": true, - "dev": true - }, - "handlebars": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "async": "^2.5.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "hasha": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "is-stream": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "bundled": true, - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "invert-kv": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "istanbul-lib-hook": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "append-transform": "^1.0.0" - } - }, - "istanbul-lib-report": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "supports-color": "^6.0.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "bundled": true, - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "rimraf": "^2.6.2", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "istanbul-reports": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "handlebars": "^4.1.0" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "lcid": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "bundled": true, - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "bundled": true, - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "bundled": true, - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "bundled": true, - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^2.0.0" - } - }, - "merge-source-map": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true - } - } - }, - "mimic-fn": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.10", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "bundled": true, - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optimist": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "p-is-promise": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "p-limit": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "package-hash": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "bundled": true, - "dev": true - }, - "path-type": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "read-pkg": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "release-zalgo": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "resolve": { - "version": "1.10.0", - "bundled": true, - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "spawn-wrap": { - "version": "1.4.2", - "bundled": true, - "dev": true, - "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "spdx-correct": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.3", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "test-exclude": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "arrify": "^1.0.1", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^1.0.1" - } - }, - "uglify-js": { - "version": "3.4.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "uuid": { - "version": "3.3.2", - "bundled": true, - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "bundled": true, - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "write-file-atomic": { - "version": "2.4.2", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "y18n": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "yargs": { - "version": "12.0.5", - "bundled": true, - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "bundled": true, - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=6" } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "node_modules/nyc/node_modules/ansi-regex": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "object-assign": { + "node_modules/nyc/node_modules/append-transform": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "default-require-extensions": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/arrify": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/async": { + "version": "2.6.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.11" + } + }, + "node_modules/nyc/node_modules/balanced-match": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nyc/node_modules/caching-transform": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasha": "^3.0.0", + "make-dir": "^1.3.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/camelcase": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/nyc/node_modules/code-point-at": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/commander": { + "version": "2.17.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/nyc/node_modules/commondir": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/convert-source-map": { + "version": "1.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/nyc/node_modules/cross-spawn": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/nyc/node_modules/debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } }, - "object-copy": { + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/default-require-extensions": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/end-of-stream": { + "version": "1.4.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/nyc/node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/nyc/node_modules/es6-error": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/execa": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/nyc/node_modules/find-cache-dir": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/foreground-child": { + "version": "1.5.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/nyc/node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/get-caller-file": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/get-stream": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nyc/node_modules/graceful-fs": { + "version": "4.1.15", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/handlebars": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/nyc/node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/hasha": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-stream": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/hosted-git-info": { + "version": "2.7.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/nyc/node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/nyc/node_modules/inherits": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/invert-kv": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/is-stream": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/istanbul-lib-coverage": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-hook": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "append-transform": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-report": { + "version": "2.0.4", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-source-maps": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/istanbul-reports": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "handlebars": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/json-parse-better-errors": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/lcid": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/load-json-file": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/lodash": { + "version": "4.17.11", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/lodash.flattendeep": { + "version": "4.4.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/lru-cache": { + "version": "4.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/map-age-cleaner": { + "version": "0.1.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/mem": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/merge-source-map": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/nyc/node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/mimic-fn": { + "version": "1.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/minimatch": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nyc/node_modules/minimist": { + "version": "0.0.10", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/mkdirp": { + "version": "0.5.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/nyc/node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/ms": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/nice-try": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/normalize-package-data": { + "version": "2.5.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/nyc/node_modules/npm-run-path": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/number-is-nan": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/once": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/nyc/node_modules/optimist": { + "version": "0.6.1", + "dev": true, + "inBundle": true, + "license": "MIT/X11", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/nyc/node_modules/os-homedir": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/os-locale": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-defer": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/p-finally": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/p-is-promise": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/p-try": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/package-hash": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/parse-json": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/path-key": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/path-parse": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/path-type": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/pify": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/pkg-dir": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/pseudomap": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/pump": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/nyc/node_modules/read-pkg": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/read-pkg-up": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/release-zalgo": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/require-main-filename": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/resolve": { + "version": "1.10.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/rimraf": { + "version": "2.6.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nyc/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/nyc/node_modules/semver": { + "version": "5.6.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nyc/node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/shebang-command": { + "version": "1.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/shebang-regex": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/signal-exit": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/spawn-wrap": { + "version": "1.4.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "node_modules/nyc/node_modules/spdx-correct": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/nyc/node_modules/spdx-exceptions": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/nyc/node_modules/spdx-expression-parse": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/nyc/node_modules/spdx-license-ids": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/nyc/node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nyc/node_modules/strip-eof": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/test-exclude": { + "version": "5.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/uglify-js": { + "version": "3.4.9", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nyc/node_modules/uglify-js/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/uuid": { + "version": "3.3.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/nyc/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/nyc/node_modules/which": { + "version": "1.3.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/nyc/node_modules/which-module": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/wordwrap": { + "version": "0.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/write-file-atomic": { + "version": "2.4.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yargs": { + "version": "12.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "11.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "license": "MIT", + "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "license": "MIT", "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true + "node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" }, - "object-keys": { + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved": "https://mirrors.cloud.tencent.com/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "object-visit": { + "node_modules/object-visit": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "license": "MIT", + "dependencies": { "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" } }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.9.tgz", + "integrity": "sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "license": "MIT", + "dependencies": { + "array.prototype.reduce": "^1.0.8", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "gopd": "^1.2.0", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "object.pick": { + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.pick": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "once": { + "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { "wrappy": "1" } }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" } }, - "only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "optionator": { + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" + }, + "node_modules/optionator": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "options": { + "node_modules/options": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/options/-/options-0.0.6.tgz", + "integrity": "sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==", + "engines": { + "node": ">=0.4.0" } }, - "os-name": { + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-name": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", - "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==", + "license": "MIT", + "dependencies": { "osx-release": "^1.0.0", "win-release": "^1.0.0" + }, + "bin": { + "os-name": "cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "os-tmpdir": { + "node_modules/os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "osx-release": { + "node_modules/osx-release": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", - "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==", + "license": "MIT", + "dependencies": { "minimist": "^1.1.0" + }, + "bin": { + "osx-release": "cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" + "node_modules/p-finally": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "p-map": { + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { + "license": "MIT", + "dependencies": { "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-try": { + "node_modules/p-timeout": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-timeout/-/p-timeout-4.1.0.tgz", + "integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "pac-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", - "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", - "requires": { - "agent-base": "^4.2.0", - "debug": "^4.1.1", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" + "resolved": "https://mirrors.cloud.tencent.com/npm/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, - "param-case": { + "node_modules/param-case": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0" } }, - "parent-module": { + "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "parse-json": { + "node_modules/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "resolved": "https://mirrors.cloud.tencent.com/npm/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" } }, - "parseurl": { + "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "pascal-case": { + "node_modules/pascal-case": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", - "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/pascal-case/-/pascal-case-2.0.1.tgz", + "integrity": "sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==", + "license": "MIT", + "dependencies": { "camel-case": "^3.0.0", "upper-case-first": "^1.1.0" } }, - "pascalcase": { + "node_modules/pascalcase": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "resolved": "https://mirrors.cloud.tencent.com/npm/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "path-case": { + "node_modules/path-case": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", - "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/path-case/-/path-case-2.1.1.tgz", + "integrity": "sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0" } }, - "path-dirname": { + "node_modules/path-dirname": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "resolved": "https://mirrors.cloud.tencent.com/npm/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true, + "license": "MIT" }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { "isarray": "0.0.1" } }, - "path-type": { + "node_modules/path-type": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "pause-stream": { + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "license": [ + "MIT", + "Apache2" + ], + "dependencies": { "through": "~2.3" } }, - "performance-now": { + "node_modules/performance-now": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "resolved": "https://mirrors.cloud.tencent.com/npm/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT" }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "optional": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "license": "ISC" }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "platform": { + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/platform": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" }, - "posix-character-classes": { + "node_modules/posix-character-classes": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "resolved": "https://mirrors.cloud.tencent.com/npm/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "power-assert": { + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/power-assert": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/power-assert/-/power-assert-1.6.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert/-/power-assert-1.6.1.tgz", "integrity": "sha512-VWkkZV6Y+W8qLX/PtJu2Ur2jDPIs0a5vbP0TpKeybNcIXmT4vcKoVkyTp5lnQvTpY/DxacAZ4RZisHRHLJcAZQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "define-properties": "^1.1.2", "empower": "^1.3.1", "power-assert-formatter": "^1.4.1", @@ -9445,22 +15616,24 @@ "xtend": "^4.0.0" } }, - "power-assert-context-formatter": { + "node_modules/power-assert-context-formatter": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-context-formatter/-/power-assert-context-formatter-1.2.0.tgz", "integrity": "sha512-HLNEW8Bin+BFCpk/zbyKwkEu9W8/zThIStxGo7weYcFkKgMuGCHUJhvJeBGXDZf0Qm2xis4pbnnciGZiX0EpSg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "power-assert-context-traversal": "^1.2.0" } }, - "power-assert-context-reducer-ast": { + "node_modules/power-assert-context-reducer-ast": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-context-reducer-ast/-/power-assert-context-reducer-ast-1.2.0.tgz", "integrity": "sha512-EgOxmZ/Lb7tw4EwSKX7ZnfC0P/qRZFEG28dx/690qvhmOJ6hgThYFm5TUWANDLK5NiNKlPBi5WekVGd2+5wPrw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "acorn": "^5.0.0", "acorn-es7-plugin": "^1.0.12", "core-js": "^2.0.0", @@ -9468,22 +15641,44 @@ "estraverse": "^4.2.0" } }, - "power-assert-context-traversal": { + "node_modules/power-assert-context-reducer-ast/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/power-assert-context-traversal": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-context-traversal/-/power-assert-context-traversal-1.2.0.tgz", "integrity": "sha512-NFoHU6g2umNajiP2l4qb0BRWD773Aw9uWdWYH9EQsVwIZnog5bd2YYLFCVvaxWpwNzWeEfZIon2xtyc63026pQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "estraverse": "^4.1.0" } }, - "power-assert-formatter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", - "integrity": "sha1-XcEl7VCj37HdomwZNH879Y7CiEo=", + "node_modules/power-assert-context-traversal/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/power-assert-formatter": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-formatter/-/power-assert-formatter-1.4.1.tgz", + "integrity": "sha512-c2QzTk1a6BUumuzjffFUrsMlx2gqLEoeEMrx6gVaHzQ/zTBTibQGblaQslbv72eq9RJNFQXRryjTHoffIEz+ww==", + "dev": true, + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "power-assert-context-formatter": "^1.0.7", "power-assert-context-reducer-ast": "^1.0.7", @@ -9493,28 +15688,31 @@ "power-assert-renderer-file": "^1.0.7" } }, - "power-assert-renderer-assertion": { + "node_modules/power-assert-renderer-assertion": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.2.0.tgz", "integrity": "sha512-3F7Q1ZLmV2ZCQv7aV7NJLNK9G7QsostrhOU7U0RhEQS/0vhEqrRg2jEJl1jtUL4ZyL2dXUlaaqrmPv5r9kRvIg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "power-assert-renderer-base": "^1.1.1", "power-assert-util-string-width": "^1.2.0" } }, - "power-assert-renderer-base": { + "node_modules/power-assert-renderer-base": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", - "integrity": "sha1-lqZQxv0F7hvB9mtUrWFELIs/Y+s=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz", + "integrity": "sha512-aGCUi0NuNd/fVS6KKMLTjRP58cdlHlQKgXV4WKl3YlUhnN0d9QBEYOyvmiumdjk+5GuZmozvEmBIcTAcxEZqnw==", + "dev": true, + "license": "MIT" }, - "power-assert-renderer-comparison": { + "node_modules/power-assert-renderer-comparison": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-renderer-comparison/-/power-assert-renderer-comparison-1.2.0.tgz", "integrity": "sha512-7c3RKPDBKK4E3JqdPtYRE9cM8AyX4LC4yfTvvTYyx8zSqmT5kJnXwzR0yWQLOavACllZfwrAGQzFiXPc5sWa+g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "diff-match-patch": "^1.0.0", "power-assert-renderer-base": "^1.1.1", @@ -9522,431 +15720,705 @@ "type-name": "^2.0.1" } }, - "power-assert-renderer-diagram": { + "node_modules/power-assert-renderer-diagram": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.2.0.tgz", "integrity": "sha512-JZ6PC+DJPQqfU6dwSmpcoD7gNnb/5U77bU5KgNwPPa+i1Pxiz6UuDeM3EUBlhZ1HvH9tMjI60anqVyi5l2oNdg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "power-assert-renderer-base": "^1.1.1", "power-assert-util-string-width": "^1.2.0", "stringifier": "^1.3.0" } }, - "power-assert-renderer-file": { + "node_modules/power-assert-renderer-file": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-renderer-file/-/power-assert-renderer-file-1.2.0.tgz", "integrity": "sha512-/oaVrRbeOtGoyyd7e4IdLP/jIIUFJdqJtsYzP9/88R39CMnfF/S/rUc8ZQalENfUfQ/wQHu+XZYRMaCEZmEesg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "power-assert-renderer-base": "^1.1.1" } }, - "power-assert-util-string-width": { + "node_modules/power-assert-util-string-width": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/power-assert-util-string-width/-/power-assert-util-string-width-1.2.0.tgz", "integrity": "sha512-lX90G0igAW0iyORTILZ/QjZWsa1MZ6VVY3L0K86e2eKun3S4LKPH4xZIl8fdeMYLfOjkaszbNSzf1uugLeAm2A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "eastasianwidth": "^0.2.0" } }, - "prelude-ls": { + "node_modules/prelude-ls": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "printable": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/printable/-/printable-0.0.3.tgz", - "integrity": "sha1-9lPLObIUt4BJrhQD4vsF10ptUOA=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "resolved": "https://mirrors.cloud.tencent.com/npm/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, - "requires": { + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/printable": { + "version": "0.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/printable/-/printable-0.0.3.tgz", + "integrity": "sha512-Cktn7HXEFXaH5CLCywmCXYOAdfQDIO3kwxnjm5yalaDlU4+XL+6d+nDEikK7S2wM+u7277KR7gL4RLZeDtvu7w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" } }, - "proxy-agent": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", - "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", - "requires": { - "agent-base": "^4.2.0", - "debug": "4", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^3.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "ps-tree": { + "node_modules/ps-tree": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/ps-tree/-/ps-tree-1.2.0.tgz", "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "requires": { + "license": "MIT", + "dependencies": { "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" + }, + "engines": { + "node": ">= 0.10" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "pumpify": { + "node_modules/pumpify": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "requires": { + "license": "MIT", + "dependencies": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, - "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "random-bytes": { + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/random-bytes": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } + "resolved": "https://mirrors.cloud.tencent.com/npm/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" } }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "license": "MIT", + "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "read-pkg-up": { + "node_modules/read-pkg-up": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/read-pkg-up/-/read-pkg-up-4.0.0.tgz", "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "readable-stream": { + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", + "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "optional": true, - "requires": { + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "ready-callback": { + "node_modules/ready-callback": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ready-callback/-/ready-callback-2.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/ready-callback/-/ready-callback-2.1.0.tgz", "integrity": "sha512-pyoQjeks8RvkzHbdDgSS1Faw+3xByvnWxccsIiBLOtFX+sp6pkpdSuIZJzfIgpzpOSOdVFVxrFEL+VcNL3+bBQ==", - "requires": { + "license": "MIT", + "dependencies": { "debug": "^2.6.0", "get-ready": "^2.0.0", "once": "^1.4.0", "uuid": "^3.0.1" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "engines": { + "node": ">=4.0.0" } }, - "redis": { + "node_modules/ready-callback/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ready-callback/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/ready-callback/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/redis": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis/-/redis-3.1.2.tgz", "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", - "requires": { + "license": "MIT", + "dependencies": { "denque": "^1.5.0", "redis-commands": "^1.7.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" } }, - "redis-commands": { + "node_modules/redis-commands": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==", + "license": "MIT" }, - "redis-errors": { + "node_modules/redis-errors": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" } }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0" }, - "regenerator-runtime": { + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerator-runtime": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "dev": true, + "license": "MIT" }, - "regenerator-transform": { + "node_modules/regenerator-transform": { "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", "dev": true, - "requires": { + "license": "BSD", + "dependencies": { "babel-runtime": "^6.18.0", "babel-types": "^6.19.0", "private": "^0.1.6" } }, - "regex-not": { + "node_modules/regex-not": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" } }, - "regexpp": { + "node_modules/regexp-clone": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexpp/-/regexpp-2.0.1.tgz", "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=6.5.0" + } + }, + "node_modules/regexpu-core": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==", + "dev": true, + "license": "MIT", + "dependencies": { "regenerate": "^1.2.1", "regjsgen": "^0.2.0", "regjsparser": "^0.1.4" } }, - "regjsgen": { + "node_modules/regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "resolved": "https://mirrors.cloud.tencent.com/npm/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==", + "dev": true, + "license": "BSD", + "dependencies": { "jsesc": "~0.5.0" }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } + "bin": { + "regjsparser": "bin/parser" } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, - "requires": { - "is-finite": "^1.0.0" + "bin": { + "jsesc": "bin/jsesc" } }, - "request": { + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request": { "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "license": "Apache-2.0", + "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", @@ -9968,370 +16440,805 @@ "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - } + "engines": { + "node": ">= 6" } }, - "request-promise": { + "node_modules/request-promise": { "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise/-/request-promise-4.2.6.tgz", "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "requires": { + "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "license": "ISC", + "dependencies": { "bluebird": "^3.5.0", "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "request-promise-core": { + "node_modules/request-promise-core": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/request-promise-core/-/request-promise-core-1.1.4.tgz", "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "requires": { + "license": "ISC", + "dependencies": { "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } }, - "require-main-filename": { + "node_modules/request/node_modules/qs": { + "version": "6.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require_optional": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" + "resolved": "https://mirrors.cloud.tencent.com/npm/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "license": "Apache-2.0", + "dependencies": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" } }, - "resolve-files": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/resolve-files/-/resolve-files-1.0.2.tgz", - "integrity": "sha1-WnIRi5L6c5T/LYYF0fw3Ppw+kO8=", + "node_modules/require_optional/node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require_optional/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-files": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-files/-/resolve-files-1.0.2.tgz", + "integrity": "sha512-Q5cbKgzFCGB630+3BaK/vT2tNw5XkPXrO0hB/mozZmOP/tiL7xFJaJ9phds0hBzLxCh37Svr1NdUFtew0pMd+g==", + "dev": true, + "license": "MIT", + "dependencies": { "crequire": "^1.8.0", "debug": "^2.6.3" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "engines": { + "node": ">=4.0.0" } }, - "resolve-from": { + "node_modules/resolve-files/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/resolve-files/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "resolve-url": { + "node_modules/resolve-url": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true, + "license": "MIT" }, - "restore-cursor": { + "node_modules/restore-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "ret": { + "node_modules/ret": { "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" + "resolved": "https://mirrors.cloud.tencent.com/npm/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12" } }, - "rndm": { + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rndm": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" + "resolved": "https://mirrors.cloud.tencent.com/npm/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==", + "license": "MIT" }, - "run-async": { + "node_modules/run-async": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "runscript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/runscript/-/runscript-1.5.0.tgz", - "integrity": "sha512-o9MaYVXr9ZNwOj+KO4jWWkC8qvTvsu6RfZLgF2h1UZjD2cenwEjoMMnCcILXZ0nu/RrSShc0OYgm1xl8iXEjJA==", - "requires": { - "debug": "^2.6.8", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/runscript": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/runscript/-/runscript-1.6.0.tgz", + "integrity": "sha512-lI0ybcwtdC5Wz3aiVtMAK6U5jcTDeLseEBSXcz6ABtQeMmQGpj35dmzpmpy2C9Bn0k2wTjTRLZoya0NFt8Mxsg==", + "license": "MIT", + "dependencies": { "is-type-of": "^1.1.0" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "engines": { + "node": ">=4.2.3" } }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "safe-regex": { + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dev": true, + "license": "MIT", + "dependencies": { "ret": "~0.1.10" } }, - "safe-timers": { + "node_modules/safe-regex-test": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-timers/-/safe-timers-1.1.0.tgz", - "integrity": "sha1-xYroMl2407BnMi8KTvOgytZ6rYM=" + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "safer-buffer": { + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safe-timers": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-timers/-/safe-timers-1.1.0.tgz", + "integrity": "sha512-9aqY+v5eMvmRaluUEtdRThV1EjlSElzO7HuCj0sTW9xvp++8iJ9t/RWGNWV6/WHcUJLHpyT2SNf/apoKTU2EpA==", + "license": "MIT" + }, + "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, - "scmp": { + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "license": "MIT", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/scmp": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", - "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" + "resolved": "https://mirrors.cloud.tencent.com/npm/scmp/-/scmp-2.1.0.tgz", + "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==", + "license": "BSD-3-Clause" }, - "sdk-base": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-3.6.0.tgz", - "integrity": "sha512-jxHUIrRLlAoRFRwiXKhOGjd6BeFWO/jz7tv+E7lbMSef6F9jzFN2Sv3hLW58oDDKscKaBGG6vQdkbXn7isE7fw==", - "requires": { + "node_modules/sdk-base": { + "version": "4.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sdk-base/-/sdk-base-4.2.1.tgz", + "integrity": "sha512-B33iy/AkIpLyxexn/5v+8jmYHCyUaJizEQcmhvMY+SoiXViY1FEULbQibQH/EcOfzPwJqJ5UDeXyUJGO47Sq3g==", + "license": "MIT", + "dependencies": { "await-event": "^2.1.0", "await-first": "^1.0.0", "co": "^4.6.0", - "is-type-of": "^1.2.1" + "p-timeout": "^4.1.0" } }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "sendmessage": { + "node_modules/sendmessage": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/sendmessage/-/sendmessage-1.1.0.tgz", - "integrity": "sha1-EKJFzuLVDHWfHgmiNHe5FJbQnjU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/sendmessage/-/sendmessage-1.1.0.tgz", + "integrity": "sha512-riI/U2etmtMKaVPe7zMnr++eG46F191F6Zycwrkm+/sEiHzucNXJETPJ5dQryNaDuHTpYdzmesEJQ2le1DxlMQ==", + "license": "MIT", + "engines": { + "node": ">= 0.10.0" + } }, - "sentence-case": { + "node_modules/sentence-case": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", - "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/sentence-case/-/sentence-case-2.1.1.tgz", + "integrity": "sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0", "upper-case-first": "^1.1.2" } }, - "sequin": { + "node_modules/sequin": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sequin/-/sequin-0.1.1.tgz", - "integrity": "sha1-XC04nWajg3NOqvvEXt6ywcsb5wE=" + "resolved": "https://mirrors.cloud.tencent.com/npm/sequin/-/sequin-0.1.1.tgz", + "integrity": "sha512-hJWMZRwP75ocoBM+1/YaCsvS0j5MTPeBHJkS2/wruehl9xwtX30HlDF1Gt6UZ8HHHY8SJa2/IL+jo+JJCd59rA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } }, - "serialize-json": { + "node_modules/serialize-json": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/serialize-json/-/serialize-json-1.0.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-json/-/serialize-json-1.0.3.tgz", "integrity": "sha512-TJvXOXSUEH4Lh2FNy1mYzNkUyBG7Ti5fRKGAbcpaDX3mLq23aT/5unC+cIFc5JTDi4/BHTaYLhynrboCCYrFaQ==", - "requires": { + "license": "MIT", + "dependencies": { "debug": "^3.2.6", "is-type-of": "^1.2.1", "utility": "^1.15.0" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">= 4.0.0" } }, - "set-blocking": { + "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "resolved": "https://mirrors.cloud.tencent.com/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" }, - "set-value": { + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-value": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "should-send-same-site-none": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/should-send-same-site-none/-/should-send-same-site-none-2.0.5.tgz", - "integrity": "sha512-7dig49H7sKnv1v/GPoFQChGgJdEX9s2oy9TQBSD5RbUx7M9CCRjHMaFP06v+DZQNM0K+o8dBhvBAd4eEKirqbQ==" - }, - "side-channel": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", - "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", - "dev": true, - "requires": { - "es-abstract": "^1.18.0-next.0", - "object-inspect": "^1.8.0" }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "engines": { + "node": ">=0.10.0" } }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, - "slash": { + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/should-send-same-site-none": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/should-send-same-site-none/-/should-send-same-site-none-2.0.5.tgz", + "integrity": "sha512-7dig49H7sKnv1v/GPoFQChGgJdEX9s2oy9TQBSD5RbUx7M9CCRjHMaFP06v+DZQNM0K+o8dBhvBAd4eEKirqbQ==", + "license": "MIT" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "slice-ansi": { + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "7.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sift/-/sift-7.0.1.tgz", + "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==", + "license": "MIT" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/slice-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/slice-ansi/-/slice-ansi-2.1.0.tgz", "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } }, - "snake-case": { + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/sliced": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==", + "license": "MIT" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snake-case": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/snake-case/-/snake-case-2.1.0.tgz", + "integrity": "sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0" } }, - "snapdragon": { + "node_modules/snapdragon": { "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", @@ -10341,137 +17248,184 @@ "source-map-resolve": "^0.5.0", "use": "^3.1.0" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-node": { + "node_modules/snapdragon-node": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">=0.10.0" } }, - "snapdragon-util": { + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "kind-of": "^3.2.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" + "is-buffer": "^1.1.5" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "^5.0.0" - } + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "sort-object-keys": { + "node_modules/sort-object-keys": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", - "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==" + "resolved": "https://mirrors.cloud.tencent.com/npm/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "license": "MIT" }, - "source-map": { + "node_modules/source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "source-map-resolve": { + "node_modules/source-map-resolve": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "license": "MIT", + "dependencies": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", @@ -10479,113 +17433,144 @@ "urix": "^0.1.0" } }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, + "node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "license": "MIT", "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } + "source-map": "^0.5.6" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, - "spdx-expression-parse": { + "node_modules/spdx-expression-parse": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://mirrors.cloud.tencent.com/npm/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" }, - "split": { + "node_modules/split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "license": "MIT", + "dependencies": { "through": "2" + }, + "engines": { + "node": "*" } }, - "split-string": { + "node_modules/split-string": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "extend-shallow": "^3.0.0" }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "engines": { + "node": ">=0.10.0" } }, - "split2": { + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/split2/-/split2-2.2.0.tgz", "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "requires": { + "license": "ISC", + "dependencies": { "through2": "^2.0.2" } }, - "sprintf-js": { + "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "license": "MIT", + "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -10595,170 +17580,382 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, - "static-extend": { + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dev": true, + "license": "MIT", + "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "engines": { + "node": ">=0.10.0" } }, - "statuses": { + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/statuses": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "stealthy-require": { + "node_modules/stealthy-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + "resolved": "https://mirrors.cloud.tencent.com/npm/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "license": "ISC", + "engines": { + "node": ">=0.10.0" + } }, - "stream-combiner": { + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-combiner": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "license": "MIT", + "dependencies": { "duplexer": "~0.1.1" } }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" }, - "stream-slice": { + "node_modules/stream-slice": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", - "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=" + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==", + "license": "MIT" }, - "stream-wormhole": { + "node_modules/stream-to-array": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-to-array/-/stream-to-array-2.3.0.tgz", + "integrity": "sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.1.0" + } + }, + "node_modules/stream-wormhole": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", - "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==" - }, - "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-wormhole/-/stream-wormhole-1.1.0.tgz", + "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" } }, - "streamsearch": { + "node_modules/streamsearch": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "resolved": "https://mirrors.cloud.tencent.com/npm/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "engines": { + "node": ">=0.8.0" } }, - "string.prototype.matchall": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", - "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2" - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string_decoder": { + "node_modules/string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" }, - "stringifier": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.4.0.tgz", - "integrity": "sha512-cNsMOqqrcbLcHTXEVmkw9y0fwDwkdgtZwlfyolzpQDoAE1xdNGhQhxBUfiDvvZIKl1hnUEgMv66nHwtMz3OjPw==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringifier": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/stringifier/-/stringifier-1.4.1.tgz", + "integrity": "sha512-7TGia2tzGIfw+Nki9r6kVxdP0vWeQ7oVZtyMnGxWsAJYe0XYV6VSGrfzUXm7r+icYfvpFlGNrwB+PYwFg+hfag==", + "dev": true, + "license": "MIT", + "dependencies": { "core-js": "^2.0.0", "traverse": "^0.6.6", "type-name": "^2.0.1" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "strip-bom": { + "node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, - "requires": { + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", + "dev": true, + "license": "MIT", + "dependencies": { "component-emitter": "^1.2.0", "cookiejar": "^2.1.0", "debug": "^3.1.0", @@ -10770,441 +17967,647 @@ "qs": "^6.5.1", "readable-stream": "^2.3.5" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } + "engines": { + "node": ">= 4.0" } }, - "supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", + "node_modules/superagent/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "requires": { + "license": "MIT" + }, + "node_modules/superagent/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/superagent/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/superagent/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/superagent/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/supertest": { + "version": "4.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/supertest/-/supertest-4.0.2.tgz", + "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", + "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net", + "dev": true, + "license": "MIT", + "dependencies": { "methods": "^1.1.2", "superagent": "^3.8.3" + }, + "engines": { + "node": ">=6.0.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" } }, - "swap-case": { + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swap-case": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", - "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/swap-case/-/swap-case-1.1.2.tgz", + "integrity": "sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==", + "license": "MIT", + "dependencies": { "lower-case": "^1.1.1", "upper-case": "^1.1.1" } }, - "synp": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/synp/-/synp-1.9.7.tgz", - "integrity": "sha512-/LVvZKAqaNQN8ZMrxhURx9i7EEVmErUnieGQZ+7oqhA+/sAZnCScyhu9mmaKud7tXBwqd8VeOrcGLPNBowc3+w==", - "requires": { + "node_modules/synp": { + "version": "1.9.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/synp/-/synp-1.9.14.tgz", + "integrity": "sha512-0e4u7KtrCrMqvuXvDN4nnHSEQbPlONtJuoolRWzut0PfuT2mEOvIFnYFHEpn5YPIOv7S5Ubher0b04jmYRQOzQ==", + "license": "MIT", + "dependencies": { "@yarnpkg/lockfile": "^1.1.0", - "bash-glob": "^2.0.0", - "colors": "^1.4.0", - "commander": "^7.1.0", - "eol": "^0.9.1", + "colors": "1.4.0", + "commander": "^7.2.0", + "eol": "^0.10.0", + "fast-glob": "^3.3.2", "lodash": "4.17.21", "nmtree": "^1.0.6", - "semver": "^7.3.4", + "semver": "^7.6.3", "sort-object-keys": "^1.1.3" }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } + "bin": { + "synp": "cli/synp.js" } }, - "table": { + "node_modules/synp/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/synp/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/synp/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/synp/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://mirrors.cloud.tencent.com/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/synp/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/table": { "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/table/-/table-5.4.6.tgz", "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, - "requires": { + "license": "BSD-3-Clause", + "dependencies": { "ajv": "^6.10.2", "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } + "engines": { + "node": ">=6.0.0" } }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "requires": { + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } + "engines": { + "node": ">=10" } }, - "tcp-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tcp-base/-/tcp-base-3.1.0.tgz", - "integrity": "sha512-5iTlUaVmeZBzyq9cSVjB4mzKtvBP2wpkbVZoMdRhFwq35DYUBAfeTgAD31NYJSba3HVxetjuqKlAkUUHlWoShw==", - "requires": { + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tcp-base": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tcp-base/-/tcp-base-3.2.0.tgz", + "integrity": "sha512-fFAqH8QTbheuEbXLdbxTSe31Gkw6Lg3nq4loyrxIXM6+ILGdbYXEblgyuu7UltOkOHbP/q2iqaC+gIXXu0C5bg==", + "license": "MIT", + "dependencies": { "is-type-of": "^1.0.0", "sdk-base": "^3.1.1" + }, + "engines": { + "node": ">= 6.0.0" } }, - "tcp-proxy.js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tcp-proxy.js/-/tcp-proxy.js-1.3.0.tgz", - "integrity": "sha512-bR33J6mcAhjueCH7emiXNxvIg/fitNma6zXs195uyteQizD+omAUZFTxRVNpW2EUSV3I+IbHoKJiHViq/ugR4A==", + "node_modules/tcp-base/node_modules/sdk-base": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/sdk-base/-/sdk-base-3.6.0.tgz", + "integrity": "sha512-jxHUIrRLlAoRFRwiXKhOGjd6BeFWO/jz7tv+E7lbMSef6F9jzFN2Sv3hLW58oDDKscKaBGG6vQdkbXn7isE7fw==", + "license": "MIT", + "dependencies": { + "await-event": "^2.1.0", + "await-first": "^1.0.0", + "co": "^4.6.0", + "is-type-of": "^1.2.1" + } + }, + "node_modules/tcp-proxy.js": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tcp-proxy.js/-/tcp-proxy.js-1.5.0.tgz", + "integrity": "sha512-+BTS7RUwSHhkJdlqgCZ1Ta7U3Ei/vyaHe6uizj4t5IoUrFM55SLsFHzlZzOZvvtVdpGhQ0Y10UKjA7HTlxU5eQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "debug": "^3.0.1", "through2": "^2.0.3" }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "engines": { + "node": ">=14.0.0" } }, - "test-exclude": { + "node_modules/test-exclude": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/test-exclude/-/test-exclude-5.2.3.tgz", "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "glob": "^7.1.3", "minimatch": "^3.0.4", "read-pkg-up": "^4.0.0", "require-main-filename": "^2.0.0" }, - "dependencies": { - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - } + "engines": { + "node": ">=6" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" }, - "thenify": { + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { + "license": "MIT", + "dependencies": { "any-promise": "^1.0.0" } }, - "thenify-all": { + "node_modules/thenify-all": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" } }, - "thinkingdata-node": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/thinkingdata-node/-/thinkingdata-node-1.2.2.tgz", - "integrity": "sha512-U5Nz2/OsFj3oFGboo/OmQcc1bcbibNJm2KVMPy7JpIVdYAH8U/VKzXCHfuVvbGSalLAdvMiBklL49r5uQnVqvw==", - "requires": { - "log4js": "^5.3.0" + "node_modules/thinkingdata-node": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/thinkingdata-node/-/thinkingdata-node-1.5.0.tgz", + "integrity": "sha512-Zio4PeOPAETswcwL8zSArLGLBAspk/kzO2bGfO+IGKm+umnfBE1XDv2YU9Mkd9WTZ6kIZVF3ykMZudF7AMNEOA==", + "license": "Apache-2.0", + "dependencies": { + "winston": "^3.8.2", + "winston-daily-rotate-file": "^4.7.1" + }, + "engines": { + "node": ">=6.9" } }, - "throat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true, + "license": "MIT" }, - "through": { + "node_modules/through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "resolved": "https://mirrors.cloud.tencent.com/npm/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" }, - "through2": { + "node_modules/through2": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { + "license": "MIT", + "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, - "title-case": { + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/title-case": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", - "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/title-case/-/title-case-2.1.1.tgz", + "integrity": "sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==", + "license": "MIT", + "dependencies": { "no-case": "^2.2.0", "upper-case": "^1.0.3" } }, - "tmp": { + "node_modules/tmp": { "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" } }, - "to-fast-properties": { + "node_modules/to-fast-properties": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "to-object-path": { + "node_modules/to-object-path": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dev": true, + "license": "MIT", + "dependencies": { "kind-of": "^3.0.2" }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "engines": { + "node": ">=0.10.0" } }, - "to-regex": { + "node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } }, - "tough-cookie": { + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { + "license": "BSD-3-Clause", + "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" } }, - "tr46": { + "node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true + "node_modules/traverse": { + "version": "0.6.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/traverse/-/traverse-0.6.11.tgz", + "integrity": "sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==", + "dev": true, + "license": "MIT", + "dependencies": { + "gopd": "^1.2.0", + "typedarray.prototype.slice": "^1.0.5", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "trim-right": { + "node_modules/trim-right": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "ts-node": { + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-node": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/ts-node/-/ts-node-7.0.1.tgz", "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "arrify": "^1.0.0", "buffer-from": "^1.1.0", "diff": "^3.1.0", @@ -11214,1149 +18617,2004 @@ "source-map-support": "^0.5.6", "yn": "^2.0.0" }, - "dependencies": { - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - } + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" } }, - "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "node_modules/ts-node/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ts-node/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/ts-node/node_modules/yn": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yn/-/yn-2.0.0.tgz", + "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", "strip-bom": "^3.0.0" }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } + "engines": { + "node": ">=6" } }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true, - "requires": { + "license": "0BSD" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "license": "MIT", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "tunnel-agent": { + "node_modules/tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "tweetnacl": { + "node_modules/tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "resolved": "https://mirrors.cloud.tencent.com/npm/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "dev": true, + "license": "ISC" }, - "type-check": { + "node_modules/type-check": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "dependencies": { "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "type-is": { + "node_modules/type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { + "license": "MIT", + "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "type-name": { + "node_modules/type-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/type-name/-/type-name-2.0.2.tgz", - "integrity": "sha1-7+fUEj2KxSr/9/QMfk3sUmYAj7Q=", - "dev": true + "resolved": "https://mirrors.cloud.tencent.com/npm/type-name/-/type-name-2.0.2.tgz", + "integrity": "sha512-kkgkuqR/jKdKO5oh/I2SMu2dGbLXoJq0zkdgbxaqYK+hr9S9edwVVGf+tMUFTx2gH9TN2+Zu9JZ/Njonb3cjhA==", + "dev": true, + "license": "MIT" }, - "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", - "dev": true + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } }, - "uid-safe": { + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray.prototype.slice": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz", + "integrity": "sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "math-intrinsics": "^1.1.0", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-offset": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uid-safe": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/uid-safe/-/uid-safe-2.1.5.tgz", "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { + "license": "MIT", + "dependencies": { "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "ultron": { + "node_modules/ultron": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + "resolved": "https://mirrors.cloud.tencent.com/npm/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow==", + "license": "MIT" }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" - }, - "unescape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", - "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", - "requires": { - "extend-shallow": "^2.0.1" + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "union-value": { + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "license": "MIT" + }, + "node_modules/unescape": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { + "dev": true, + "license": "MIT", + "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "universal-deep-strict-equal": { + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/universal-deep-strict-equal": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", - "integrity": "sha1-DaSsL3PP95JMgfpN4BjKViyisKc=", + "resolved": "https://mirrors.cloud.tencent.com/npm/universal-deep-strict-equal/-/universal-deep-strict-equal-1.2.2.tgz", + "integrity": "sha512-UpnFi3/IF3jZHIHTdQXTHLCqpBP3805OFFRPHgvCS7k0oob2YVXxMTjS0U0g9qJTzqFRMwEnFFSlFLqt6zwjTQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "array-filter": "^1.0.0", "indexof": "0.0.1", "object-keys": "^1.0.0" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { + "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved": "https://mirrors.cloud.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "unset-value": { + "node_modules/unset-value": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dev": true, + "license": "MIT", + "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - } + "engines": { + "node": ">=0.10.0" } }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "upper-case": { + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/upper-case": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + "resolved": "https://mirrors.cloud.tencent.com/npm/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "license": "MIT" }, - "upper-case-first": { + "node_modules/upper-case-first": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/upper-case-first/-/upper-case-first-1.1.2.tgz", + "integrity": "sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==", + "license": "MIT", + "dependencies": { "upper-case": "^1.1.1" } }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "requires": { + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { "punycode": "^2.1.0" } }, - "urijs": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz", - "integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==" + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "license": "MIT" }, - "urix": { + "node_modules/urix": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "resolved": "https://mirrors.cloud.tencent.com/npm/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true, + "license": "MIT" }, - "urllib": { - "version": "2.36.1", - "resolved": "https://registry.npmjs.org/urllib/-/urllib-2.36.1.tgz", - "integrity": "sha512-g0Gh7bH5AwfPUzFetxPtJwumGHE6D7KQn0K68MwcJXPgO2K0AliwEIxLAwGMF+TpY75DYAsvz1h9ekagYoq33w==", - "requires": { + "node_modules/urllib": { + "version": "2.44.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/urllib/-/urllib-2.44.0.tgz", + "integrity": "sha512-zRCJqdfYllRDA9bXUtx+vccyRqtJPKsw85f44zH7zPD28PIvjMqIgw9VwoTLV7xTBWZsbebUFVHU5ghQcWku2A==", + "license": "MIT", + "dependencies": { "any-promise": "^1.3.0", "content-type": "^1.0.2", - "debug": "^2.6.9", "default-user-agent": "^1.0.0", - "digest-header": "^0.0.1", + "digest-header": "^1.0.0", "ee-first": "~1.1.1", "formstream": "^1.1.0", "humanize-ms": "^1.2.0", - "iconv-lite": "^0.4.15", - "ip": "^1.1.5", - "proxy-agent": "^3.1.0", + "iconv-lite": "^0.6.3", "pump": "^3.0.0", "qs": "^6.4.0", "statuses": "^1.3.1", "utility": "^1.16.1" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "engines": { + "node": ">= 0.10.0" + }, + "peerDependencies": { + "proxy-agent": "^5.0.0" + }, + "peerDependenciesMeta": { + "proxy-agent": { + "optional": true } } }, - "use": { + "node_modules/urllib/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/use": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved": "https://mirrors.cloud.tencent.com/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, - "utility": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/utility/-/utility-1.16.3.tgz", - "integrity": "sha512-kYghm8fknkPkUd9ncODj/b2Zojc23gnRC29QmpmL3BBsSX6W++RNRTQ1tB7l0UA7d4SisIjUyvRfVET3lBwurw==", - "requires": { + "node_modules/utility": { + "version": "1.18.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/utility/-/utility-1.18.0.tgz", + "integrity": "sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==", + "license": "MIT", + "dependencies": { "copy-to": "^2.0.1", "escape-html": "^1.0.3", "mkdirp": "^0.5.1", "mz": "^2.7.0", "unescape": "^1.0.1" + }, + "engines": { + "node": ">= 0.12.0" } }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true, + "license": "MIT" }, - "validate-npm-package-license": { + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "vary": { + "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "resolved": "https://mirrors.cloud.tencent.com/npm/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "verror": { + "node_modules/verror": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "license": "MIT" }, - "whatwg-url": { + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "win-release": { + "node_modules/which-boxed-primitive": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/win-release": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==", + "license": "MIT", + "dependencies": { "semver": "^5.0.1" }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "engines": { + "node": ">=0.10.0" } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "node_modules/win-release/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "node_modules/winston": { + "version": "3.19.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } + "engines": { + "node": ">= 12.0.0" } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/winston-daily-rotate-file": { + "version": "4.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", + "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", + "license": "MIT", + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "winston": "^3" + } }, - "write": { + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/write/-/write-1.0.3.tgz", "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" } }, - "ws": { + "node_modules/ws": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-1.1.5.tgz", "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "requires": { + "license": "MIT", + "dependencies": { "options": ">=0.0.5", "ultron": "1.0.x" } }, - "wt": { + "node_modules/wt": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/wt/-/wt-1.2.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/wt/-/wt-1.2.0.tgz", "integrity": "sha512-nJttxFyxnIvWBWYcy7Px4XkXbRoEe77by66d0FDof266Mv00vVBNcUGa00rL1+0DdsXG75LG1rwBnBfUa2bNLA==", - "requires": { + "license": "MIT", + "dependencies": { "debug": "^2.2.0", "ndir": "^0.1.5", "sdk-base": "^2.0.1" }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "get-ready": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz", - "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "sdk-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz", - "integrity": "sha1-ukAonovfJy7RHdnql+r5jgNtJMY=", - "requires": { - "get-ready": "~1.0.0" - } - } + "engines": { + "node": ">= 0.12.9" } }, - "xprofiler": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/xprofiler/-/xprofiler-1.2.6.tgz", - "integrity": "sha512-z7o2L6x6UHpaI1G3Apc2ZDfbXw8VKcjVupmA2+V8Eb3deYyfGlFNWIwdTBiww/CwxXlv/OyHmbuim9M0UrQ+ow==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.4", + "node_modules/wt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/wt/node_modules/get-ready": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-ready/-/get-ready-1.0.0.tgz", + "integrity": "sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==", + "license": "MIT" + }, + "node_modules/wt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/wt/node_modules/sdk-base": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/sdk-base/-/sdk-base-2.0.1.tgz", + "integrity": "sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==", + "license": "MIT", + "dependencies": { + "get-ready": "~1.0.0" + } + }, + "node_modules/xprofiler": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/xprofiler/-/xprofiler-1.4.0.tgz", + "integrity": "sha512-ZXRrsC9S602oEH6lGe0ulLSK0iZaz9aO3apxNNFtsbhrHjvifnEfUvukngTZnCDJqfcdT0RNi4x0O3x3IRtlBg==", + "hasInstallScript": true, + "license": "BSD-2-Clause", + "dependencies": { + "@xprofiler/node-pre-gyp": "^1.0.9", "moment": "^2.29.1", - "nan": "^2.14.2", + "nan": "^2.15.0", "uuid": "^8.3.2", "yargs": "^15.4.1" }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + "bin": { + "xprofctl": "bin/xprofctl" } }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + "node_modules/xprofiler/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "xss": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz", - "integrity": "sha512-3MgPdaXV8rfQ/pNn16Eio6VXYPTkqwa0vc7GkiymmY/DqR1SE/7VPAAVZz1GJsJFrllMYO3RHfEaiUGjab6TNw==", - "requires": { + "node_modules/xprofiler/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/xprofiler/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/xprofiler/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/xprofiler/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/xprofiler/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xprofiler/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/xprofiler/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xprofiler/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/xss": { + "version": "1.0.15", + "resolved": "https://mirrors.cloud.tencent.com/npm/xss/-/xss-1.0.15.tgz", + "integrity": "sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==", + "license": "MIT", + "dependencies": { "commander": "^2.20.3", "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" } }, - "xtend": { + "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved": "https://mirrors.cloud.tencent.com/npm/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } }, - "xtransit": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/xtransit/-/xtransit-1.2.3.tgz", - "integrity": "sha512-RDWxbISJjfsMAg9bcDKrnfJf0KhsKPT1zrmgjEOljzwH51JIIIenkWZS1DcLMCwy2zYZci/xvdlKAXOOeUkrwQ==", - "requires": { + "node_modules/xtransit": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/xtransit/-/xtransit-1.5.0.tgz", + "integrity": "sha512-Wpq83ZkNzg+ZWdpwxY2Ej9yvwEN0j4xnT/ASgXkJlGM0Tcad1Bq0f3KZ1JKhvFHtFIS67bxBnbSVsxjEJpUTrQ==", + "license": "BSD-2-Clause", + "dependencies": { "address": "^1.1.2", - "formstream": "^1.1.0", + "form-data": "^4.0.0", "moment": "^2.28.0", "nounou": "^1.2.1", "p-map": "^4.0.0", "split2": "^3.2.2", - "synp": "^1.8.2", + "synp": "^1.9.9", "through2": "^4.0.2", "urllib": "^2.36.1", "uuid": "^8.3.0", "ws": "^7.3.1" }, + "bin": { + "xtransit": "bin/xtransit.js" + } + }, + "node_modules/xtransit/node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/xtransit/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/xtransit/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/xtransit/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/xtransit/node_modules/through2": { + "version": "4.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/xtransit/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "requires": { - "readable-stream": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "requires": { - "readable-stream": "3" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==" + "utf-8-validate": { + "optional": true } } }, - "y18n": { + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" } }, - "yargs-unparser": { + "node_modules/yargs-unparser": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-unparser/-/yargs-unparser-1.6.0.tgz", "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "flat": "^4.1.0", "lodash": "^4.17.15", "yargs": "^13.3.0" }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + "engines": { + "node": ">=6" } }, - "ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" + "node_modules/yargs-unparser/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "yn": { + "node_modules/yargs-unparser/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/yargs-unparser/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/yargs-unparser/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs-unparser/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs-unparser/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-unparser/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs-unparser/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-unparser/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/ylru": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ylru/-/ylru-1.4.0.tgz", + "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "ypkgfiles": { + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ypkgfiles": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ypkgfiles/-/ypkgfiles-1.6.0.tgz", + "resolved": "https://mirrors.cloud.tencent.com/npm/ypkgfiles/-/ypkgfiles-1.6.0.tgz", "integrity": "sha512-q8vgLzZy5CO1LUBFPWOkYpqCkAEaWdXTAAIfLREB72vxnXd+vUZvU3Qxb694TyPc56zA3t8fZIcBNj8fWtSR2A==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "debug": "^2.6.1", "glob": "^7.1.1", "is-type-of": "^1.0.0", "resolve-files": "^1.0.0", "yargs": "^7.0.1" }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - } + "bin": { + "pkgfiles": "bin/pkgfiles.js", + "ypkgfiles": "bin/ypkgfiles.js" + }, + "engines": { + "node": ">=4.0.0" } }, - "zlogger": { + "node_modules/ypkgfiles/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/ypkgfiles/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ypkgfiles/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true, + "license": "ISC" + }, + "node_modules/ypkgfiles/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zlogger/-/zlogger-1.1.0.tgz", - "integrity": "sha1-vA1KGlDYi04CdjYGDHojaCdUdE4=", - "requires": { + "resolved": "https://mirrors.cloud.tencent.com/npm/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ypkgfiles/node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true, + "license": "ISC" + }, + "node_modules/ypkgfiles/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ypkgfiles/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ypkgfiles/node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ypkgfiles/node_modules/yargs": { + "version": "7.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/ypkgfiles/node_modules/yargs-parser": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "node_modules/zlogger": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/zlogger/-/zlogger-1.1.0.tgz", + "integrity": "sha512-WjRPkjHe4rajXun45zZRAnViTSLkIr2PEFI303u+3NYIkhWqxhpTr0j67XPzhTJMmDH27pGoTSxGg/qP8FiaJA==", + "license": "MIT", + "dependencies": { "pumpify": "^1.3.5", "split2": "^2.1.0", "through2": "^2.0.1" + }, + "engines": { + "node": ">=4.3.1" } } } diff --git a/web-server/package.json b/web-server/package.json index f4971091a..29c7abb58 100644 --- a/web-server/package.json +++ b/web-server/package.json @@ -5,7 +5,7 @@ "private": true, "egg": { "typescript": true, - "declarations": true + "declarations": false }, "scripts": { "start": "egg-scripts start --daemon --title=egg-server-zyz --ignore-stderr", @@ -20,17 +20,17 @@ "autod": "autod", "lint": "eslint . --ext .ts", "clean": "ets clean", - "local": "cross-env EGG_SERVER_ENV=local npm run dev", - "isbn": "cross-env EGG_SERVER_ENV=isbn npm run dev", - "monitor": "cross-env EGG_SERVER_ENV=monitor npm run dev", - "distribute": "cross-env EGG_SERVER_ENV=distribute npm run dev", - "lylocal": "cross-env EGG_SERVER_ENV=lylocal npm run dev", - "alpha": "cross-env EGG_SERVER_ENV=alpha npm run dev", - "stable": "cross-env EGG_SERVER_ENV=stable npm run dev", - "deve": "cross-env EGG_SERVER_ENV=dev npm run dev", - "sq1": "cross-env EGG_SERVER_ENV=sq1 npm run dev", - "sq2": "cross-env EGG_SERVER_ENV=sq2 npm run dev", - "zy": "cross-env EGG_SERVER_ENV=zy npm run dev" + "local": "cross-env EGG_SERVER_ENV=local egg-bin dev", + "isbn": "cross-env EGG_SERVER_ENV=isbn egg-bin dev", + "monitor": "cross-env EGG_SERVER_ENV=monitor egg-bin dev", + "distribute": "cross-env EGG_SERVER_ENV=distribute egg-bin dev", + "lylocal": "cross-env EGG_SERVER_ENV=lylocal egg-bin dev", + "alpha": "cross-env EGG_SERVER_ENV=alpha egg-bin dev", + "stable": "cross-env EGG_SERVER_ENV=stable egg-bin dev", + "deve": "cross-env EGG_SERVER_ENV=dev egg-bin dev", + "sq1": "cross-env EGG_SERVER_ENV=sq1 egg-bin dev", + "sq2": "cross-env EGG_SERVER_ENV=sq2 egg-bin dev", + "zy": "cross-env EGG_SERVER_ENV=zy egg-bin dev" }, "dependencies": { "@types/underscore": "^1.11.3", @@ -44,7 +44,9 @@ "egg-scripts": "^2.6.0", "egg-view-nunjucks": "^2.2.0", "egg-xtransit": "^1.2.2", + "minimatch": "^3.0.4", "moment": "^2.29.1", + "mongoose": "5.10.18", "mongoose-transactions": "^1.1.4", "redis": "^3.1.2", "reflect-metadata": "^0.1.13", diff --git a/web-server/tsconfig.json b/web-server/tsconfig.json index ba55305c2..9e57d4f58 100644 --- a/web-server/tsconfig.json +++ b/web-server/tsconfig.json @@ -3,20 +3,19 @@ "compilerOptions": { "target": "es2017", "module": "commonjs", - "strict": true, + "strict": false, "noImplicitAny": false, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "charset": "utf8", "allowJs": false, "pretty": true, "noEmitOnError": false, - "noUnusedLocals": true, - "noUnusedParameters": true, - "allowUnreachableCode": false, - "allowUnusedLabels": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "allowUnreachableCode": true, + "allowUnusedLabels": true, "strictPropertyInitialization": false, - "noFallthroughCasesInSwitch": true, + "noFallthroughCasesInSwitch": false, "skipLibCheck": true, "skipDefaultLibCheck": true, "strictNullChecks": false, @@ -24,13 +23,21 @@ "importHelpers": true, "baseUrl": ".", "paths": { - "@db/*": ["app/db/*"], - "@consts": ["app/consts"] - }, + "@db/*": ["../shared/db/*"], + "@consts": ["../shared/consts"], + "@domain/*": ["../shared/domain/*"], + "@resource/*": ["../shared/resource/*"], + "@pubUtils/*": ["../shared/pubUtils/*"] + } }, + "include": [ + "app/**/*", // 只检查app目录下的所有文件(按需修改) + "typings/**/*" + ], "exclude": [ "app/public", "app/views", - "node_modules*" + "node_modules", + "**/node_modules/**" ] -} +} \ No newline at end of file diff --git a/web-server/typings/app/controller/index.d.ts b/web-server/typings/app/controller/index.d.ts index 914d7c619..442ade87f 100644 --- a/web-server/typings/app/controller/index.d.ts +++ b/web-server/typings/app/controller/index.d.ts @@ -1,5 +1,6 @@ -// This file is created by egg-ts-helper@1.25.8 +// This file is created by egg-ts-helper@1.35.2 // Do not modify this file!!!!!!!!! +/* eslint-disable */ import 'egg'; import ExportAccount from '../../../app/controller/account'; diff --git a/web-server/typings/app/index.d.ts b/web-server/typings/app/index.d.ts index 7b891bb48..41638859e 100644 --- a/web-server/typings/app/index.d.ts +++ b/web-server/typings/app/index.d.ts @@ -1,5 +1,6 @@ -// This file is created by egg-ts-helper@1.25.8 +// This file is created by egg-ts-helper@1.35.2 // Do not modify this file!!!!!!!!! +/* eslint-disable */ import 'egg'; export * from 'egg'; diff --git a/web-server/typings/app/middleware/index.d.ts b/web-server/typings/app/middleware/index.d.ts index 765e86b23..c433955ca 100644 --- a/web-server/typings/app/middleware/index.d.ts +++ b/web-server/typings/app/middleware/index.d.ts @@ -1,5 +1,6 @@ -// This file is created by egg-ts-helper@1.25.8 +// This file is created by egg-ts-helper@1.35.2 // Do not modify this file!!!!!!!!! +/* eslint-disable */ import 'egg'; import ExportCheckMainten from '../../../app/middleware/checkMainten'; diff --git a/web-server/typings/app/service/index.d.ts b/web-server/typings/app/service/index.d.ts index 291d94247..573786c7a 100644 --- a/web-server/typings/app/service/index.d.ts +++ b/web-server/typings/app/service/index.d.ts @@ -1,5 +1,6 @@ -// This file is created by egg-ts-helper@1.25.8 +// This file is created by egg-ts-helper@1.35.2 // Do not modify this file!!!!!!!!! +/* eslint-disable */ import 'egg'; type AnyClass = new (...args: any[]) => any; diff --git a/web-server/typings/config/index.d.ts b/web-server/typings/config/index.d.ts index 6f8bf3cca..dd87a48d0 100644 --- a/web-server/typings/config/index.d.ts +++ b/web-server/typings/config/index.d.ts @@ -1,5 +1,6 @@ -// This file is created by egg-ts-helper@1.25.8 +// This file is created by egg-ts-helper@1.35.2 // Do not modify this file!!!!!!!!! +/* eslint-disable */ import 'egg'; import { EggAppConfig } from 'egg'; diff --git a/web-server/typings/config/plugin.d.ts b/web-server/typings/config/plugin.d.ts deleted file mode 100644 index 4242eab8d..000000000 --- a/web-server/typings/config/plugin.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -// This file is created by egg-ts-helper@1.25.8 -// Do not modify this file!!!!!!!!! - -import 'egg'; -import 'egg-onerror'; -import 'egg-session'; -import 'egg-i18n'; -import 'egg-watcher'; -import 'egg-multipart'; -import 'egg-security'; -import 'egg-development'; -import 'egg-logrotator'; -import 'egg-schedule'; -import 'egg-static'; -import 'egg-jsonp'; -import 'egg-view'; -import 'egg-view-nunjucks'; -import 'egg-cors'; -import { EggPluginItem } from 'egg'; -declare module 'egg' { - interface EggPlugin { - onerror?: EggPluginItem; - session?: EggPluginItem; - i18n?: EggPluginItem; - watcher?: EggPluginItem; - multipart?: EggPluginItem; - security?: EggPluginItem; - development?: EggPluginItem; - logrotator?: EggPluginItem; - schedule?: EggPluginItem; - static?: EggPluginItem; - jsonp?: EggPluginItem; - view?: EggPluginItem; - nunjucks?: EggPluginItem; - cors?: EggPluginItem; - xtransit?: EggPluginItem; - } -} \ No newline at end of file diff --git a/web-server/typings/index.d.ts b/web-server/typings/index.d.ts deleted file mode 100644 index c81035ac9..000000000 --- a/web-server/typings/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import 'egg'; - -declare module 'egg' { - -} \ No newline at end of file diff --git a/web-server/typings/modules.d.ts b/web-server/typings/modules.d.ts new file mode 100644 index 000000000..0f820216f --- /dev/null +++ b/web-server/typings/modules.d.ts @@ -0,0 +1,2 @@ +declare module 'micromatch'; +declare module 'is-glob';