diff --git a/game-server/app/servers/activity/handler/activityHandler.ts b/game-server/app/servers/activity/handler/activityHandler.ts index 17811e11c..b395af15f 100644 --- a/game-server/app/servers/activity/handler/activityHandler.ts +++ b/game-server/app/servers/activity/handler/activityHandler.ts @@ -21,6 +21,7 @@ import { sevenDaysActivity } from '../../../services/sevenDaysService'; import { checkActivityTask } from '../../../services/taskService'; import { treasureHuntActivity } from '../../../services/treasureHuntService'; import { getSelfServiceShopActivityData } from '../../../services/selfServiceShopActivityService'; +import { ActivitySelfServiceGoodsModel } from '../../../db/ActivitySelfServiceGoods'; // import { ActivityDailyChallengesModel } from '../../../db/ActivityDailyChallenges'; // import { isComplete } from '../../../pubUtils/taskUtil'; @@ -233,10 +234,11 @@ export class ActivityHandler { { let data = await getSelfServiceShopActivityData(serverId, roleId); if (data) { + let playerGoods = await ActivitySelfServiceGoodsModel.findData(data.activityId, roleId, data.roundIndex, true); playerActivityArray.push({ type: ACTIVITY_TYPE.SELF_SERVICE_SHOP, activityId: data.activityId, - data: data, + data: { playerData: data, playerGoods: playerGoods ? playerGoods : [] }, }); } } @@ -437,6 +439,19 @@ export class ActivityHandler { }); } } + + // //每日领取免费午饭、晚饭活动 + // { + // let data = await sevenDaysActivity(serverId, roleId, ACTIVITY_TYPE.DAILY_MEAL); + // if (data) { + // playerActivityArray.push({ + // type: ACTIVITY_TYPE.DAILY_MEAL, + // activityId: data.activityId, + // data, + // }); + // } + // } + return resResult(STATUS.SUCCESS, { playerActivityArray }); } diff --git a/game-server/app/servers/activity/handler/dailyMealHandler.ts b/game-server/app/servers/activity/handler/dailyMealHandler.ts new file mode 100644 index 000000000..410ee3f91 --- /dev/null +++ b/game-server/app/servers/activity/handler/dailyMealHandler.ts @@ -0,0 +1,87 @@ +import { Application, BackendSession } from 'pinus'; +import { resResult } from '../../../pubUtils/util'; +import { STATUS } from '../../../consts'; +import { handleCost } from '../../../services/rewardService'; +import { getPlayerDailyMealData } from '../../../services/dailyMealService'; +import { DailyMealItem } from '../../../domain/activityField/dailyMealField'; +import { ActivityDailyMealModel } from '../../../db/ActivityDailyMeal'; +import { addReward, stringToConsumeParam, stringToRewardParam } from '../../../services/giftPackageService'; +import { RewardParam } from '../../../domain/activityField/rewardField'; +import moment = require('moment'); + + +export default function (app: Application) { + return new DailyLunchHandler(app); +} + +export class DailyLunchHandler { + constructor(private app: Application) { + } + + + /************************每日午饭/晚饭****************************/ + + /** + * @description 获取每日午饭/晚饭活动数据 + * @param {{ activityId: number}} msg + * @param {BackendSession} session + * @memberof DailyLunchHandler + */ + async getDailyLunchActivity(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 DailyLunchHandler + */ + 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'); + const funcs = session.get('funcs'); + + 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); + if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH); + } + //免费期间 + let rewardParamArr: Array = stringToRewardParam(itemData.reward); + let result = await addReward(roleId, roleName, sid, serverId, funcs, rewardParamArr) + await ActivityDailyMealModel.addReceiveRecord(serverId, activityId, roleId, type, curDate); + itemData.isReceive = true; + return resResult(STATUS.SUCCESS, Object.assign(result, { + param: { activityId, type }, + item: itemData, + })); + } + +} diff --git a/game-server/app/servers/activity/handler/selfServiceShopHandler.ts b/game-server/app/servers/activity/handler/selfServiceShopHandler.ts index cb9a3788c..3d874f897 100644 --- a/game-server/app/servers/activity/handler/selfServiceShopHandler.ts +++ b/game-server/app/servers/activity/handler/selfServiceShopHandler.ts @@ -36,7 +36,7 @@ export class SelfServiceShopHandler { 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 }); + return resResult(STATUS.SUCCESS, { playerData, playerGoods: playerGoods ? playerGoods : [] }); } /** @@ -95,7 +95,7 @@ export class SelfServiceShopHandler { await ActivitySelfServiceGoodsModel.addGoods(obj.activityId, roleId, obj.roundIndex, obj.index, obj.cellIndex, obj.gift, obj.rewardIndex); } - return resResult(STATUS.SUCCESS, {}); + return resResult(STATUS.SUCCESS, { data }); } /** diff --git a/game-server/app/services/dailyMealService.ts b/game-server/app/services/dailyMealService.ts new file mode 100644 index 000000000..156a64274 --- /dev/null +++ b/game-server/app/services/dailyMealService.ts @@ -0,0 +1,50 @@ +import { ACTIVITY_TYPE, DAILY_MEAL_TYPE } from '../consts'; +import { ActivityModel, ActivityModelType } from '../db/Activity'; +import { ActivityDailyMealModel, ActivityDailyMealModelType } from '../db/ActivityDailyMeal'; +import { ServerlistModel } from '../db/Serverlist'; +import { DailyMealData } from '../domain/activityField/dailyMealField'; + + +/** + * 获取活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function dailyMealActivity(serverId: number, roleId: string) { + let { activityGroupId } = await ServerlistModel.findByServerId(serverId); + let activityDataArray: ActivityModelType[] = await ActivityModel.findOpenActivityByType(activityGroupId, ACTIVITY_TYPE.DAILY_MEAL, new Date()); + if (activityDataArray.length === 0) { + return null; + } + let activityData: ActivityModelType = activityDataArray[0]; + let playerData = new DailyMealData(activityData); + + let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.beginTime, playerData.endTime); + let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.beginTime, playerData.endTime); + 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: ActivityModelType = await ActivityModel.findActivity(activityId); + let playerData = new DailyMealData(activityData); + + let playerLunchRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.LUNCH, playerData.beginTime, playerData.endTime); + let playerDinnerRecords: ActivityDailyMealModelType[] = await ActivityDailyMealModel.findData(serverId, activityData.activityId, roleId, DAILY_MEAL_TYPE.DINNER, playerData.beginTime, playerData.endTime); + playerData.setPlayerRecords(playerLunchRecords.concat(playerDinnerRecords)); + return playerData; +} + + diff --git a/shared/consts/constModules/activityConst.ts b/shared/consts/constModules/activityConst.ts index 860b37fa0..67124e453 100644 --- a/shared/consts/constModules/activityConst.ts +++ b/shared/consts/constModules/activityConst.ts @@ -34,6 +34,7 @@ export enum ACTIVITY_TYPE { SEVEN_DAY = 27, // 七天乐活动(每日特惠礼包,成长任务活动,今日挑战活动) FOURTEEN_DAY = 28, // 十四天乐活动 COMMON_SEVEN_DAY = 29, // 通用七天乐活动 + DAILY_MEAL = 30, // 每日领取免费午饭、晚饭活动 } /** @@ -101,6 +102,15 @@ export enum ORDER_STATE { RESULT_FAIL = 3, // 订单失败 } +/** + * 每日免费领取午饭、晚饭类型 + */ +export enum DAILY_MEAL_TYPE { + LUNCH = 1, // 午饭 + DINNER = 2, // 晚饭 +} + + //服务器开服时间 export const SERVER_OPEN_TIME = '2021-06-06T20:03:16.637+08:00'; //玩家等级大于等于15级才能开启vip签到 diff --git a/shared/db/ActivityDailyMeal.ts b/shared/db/ActivityDailyMeal.ts new file mode 100644 index 000000000..9198f63ae --- /dev/null +++ b/shared/db/ActivityDailyMeal.ts @@ -0,0 +1,53 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; + +/** + * 活动系统 - 每日免费午餐、晚餐 +*/ +@index({ roleId: 1 }) + +export default class Activity_Daily_Meal extends BaseModel { + @prop({ required: true }) + serverId: number; // 服id + @prop({ required: true }) + activityId: number; // 活动Id + @prop({ required: true }) + roleId: string; // 用户Id + @prop({ required: true }) + receiveTime: number; // 领取时间 + @prop({ required: true }) + type: number; // 1午餐、2晚餐类型 + + + //领取记录 + public static async addReceiveRecord(serverId: number, activityId: number, roleId: string, type: number, receiveTime: number) { + await ActivityDailyMealModel.insertMany([ + { + serverId, + activityId, + roleId, + receiveTime, + type + } + ]) + } + + //根据活动时间查询活动数据 + public static async findData(serverId: number, activityId: number, roleId: string, type: number, beginTime: number, endTime: number) { + let result: ActivityDailyMealModelType[] = await ActivityDailyMealModel.find({ + serverId, roleId, activityId, type, + receiveTime: { $gt: beginTime, $lt: endTime } + }).lean(true); + return result; + } + + //删除活动领取记录 + public static async deleteActivity(serverId: number, activityId: number, roleId: string, type: number, beginTime: number, endTime: number) { + await ActivityDailyMealModel.deleteMany({ serverId, roleId, activityId, type, receiveTime: { $gt: beginTime, $lt: endTime } }); + } +} + +export const ActivityDailyMealModel = getModelForClass(Activity_Daily_Meal); + +export interface ActivityDailyMealModelType extends Pick, keyof Activity_Daily_Meal> { } +export type ActivityDailyMealModelTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/domain/activityField/dailyMealField.ts b/shared/domain/activityField/dailyMealField.ts new file mode 100644 index 000000000..db7489a75 --- /dev/null +++ b/shared/domain/activityField/dailyMealField.ts @@ -0,0 +1,73 @@ +import moment = require('moment'); +import { REFRESH_TIME, TASK_TYPE } from '../../consts'; +import { ActivityModelType } from '../../db/Activity'; +import { ActivityDailyMealModelType } from '../../db/ActivityDailyMeal'; +import { ActivityBase } from './activityField'; + + +// 每日配置数据 +export class DailyMealItem { + name: string; // 名称 + beginTime: number; // 开始时间 + endTime: number; // 结束时间 + type: number; // 午饭晚饭类型,DAILY_MEAL_TYPE 1.午饭 2晚饭 + reward: string; // 任务奖励,格式:1&3&1(类型&id&数量) 类型定义:1.英雄,2.物品 + consume: string; //补签消耗资源 + + isReceive: boolean = false; //是否领取过 + + constructor(data: any) { + this.beginTime = moment(new Date()).startOf('d').add(data.beginHour, 'h').valueOf(); + this.endTime = moment(new Date()).startOf('d').add(data.endHour, 'h').valueOf(); + this.type = data.type; + this.reward = data.reward; + this.consume = data.consume; + this.name = data.name; + + this.isReceive = false; + } +} + + +// 每日免费午餐、晚餐活动数据 +export class DailyMealData extends ActivityBase { + list: Array = []; + name: string = ''//名字 + + public findItem(type: number) { + let index = this.list.findIndex(obj => { return obj.type === type }) + return (index != -1) ? this.list[index] : null + } + + //解析玩家领取记录 + public setPlayerRecords(data: ActivityDailyMealModelType[]) { + for (let obj of this.list) { + let index = data.findIndex(record => { return obj.type == record.type }) + if (index != -1) { + obj.isReceive = true; + } + } + } + + public initData(data: string) { + let dataObj = JSON.parse(data); + this.name = dataObj.name; + let arr = dataObj.data; + for (let obj of arr) { + this.list.push(new DailyMealItem(obj)) + } + let curDate = moment(new Date()); + if (curDate.hour() < REFRESH_TIME) { + this.beginTime = curDate.startOf('d').add(-1, 'd').add(REFRESH_TIME, 'h').valueOf(); + this.endTime = moment(this.beginTime).add(1, 'd').valueOf(); + } else { + this.beginTime = curDate.startOf('d').add(REFRESH_TIME, 'h').valueOf(); + this.endTime = moment(this.beginTime).add(1, 'd').valueOf() + } + } + + constructor(activityData: ActivityModelType) { + super(activityData) + this.initData(activityData.data) + } +} \ No newline at end of file diff --git a/shared/domain/activityField/treasureHuntField.ts b/shared/domain/activityField/treasureHuntField.ts index 2e85ed35a..c39fde004 100644 --- a/shared/domain/activityField/treasureHuntField.ts +++ b/shared/domain/activityField/treasureHuntField.ts @@ -172,9 +172,9 @@ export class TreasureHuntTaskData { public setPlayerTaskRecords(record: ActivityTreasureHuntTaskModelType[]) { for (let item of this.list) { - let index = record.findIndex(obj => { return obj.cellIndex === item.cellIndex && obj.type === item.taskType }); + let index = record.findIndex(obj => { return obj.cellIndex === item.cellIndex }); if (index != -1) { - item.totalCount = record[index].totalCount; + item.totalCount = record[index].totalCount ? record[index].totalCount : 0; item.isReceive = record[index].receiveRewardCount ? true : false; } }