diff --git a/game-server/app/servers/activity/handler/signInHandler.ts b/game-server/app/servers/activity/handler/signInHandler.ts new file mode 100644 index 000000000..57d5ec10f --- /dev/null +++ b/game-server/app/servers/activity/handler/signInHandler.ts @@ -0,0 +1,105 @@ +import { Application, BackendSession } from 'pinus'; +import { resResult } from '../../../pubUtils/util'; +import { STATUS, ACTIVITY_RESOURCES_TYPE, ACTIVITY_TYPE } from '../../../consts'; +import { getPlayerSignInData, signInActivity } from '../../../services/signInService'; +import { addItems, createHeroes, handleCost } from '../../../services/rewardService'; +import { SignInItem } from '../../../domain/activityField/signInField'; +import { ActivitySignInModel } from '../../../db/ActivitySignIn'; +import moment = require('moment'); + + +export default function (app: Application) { + return new SignInHandler(app); +} + +export class SignInHandler { + constructor(private app: Application) { + } + + /************************签到活动****************************/ + + /** + * @description 获取普通签到活动数据 + * @param {BackendSession} session + * @memberof SignInHandler + */ + async getSignInActivity(msg: {}, session: BackendSession) { + const { } = msg; + const roleId = session.get('roleId'); + const serverId = session.get('serverId'); + + let todayIndex = moment(Date.now()).day(); + console.log('todayIndex', todayIndex) + // if (todayIndex < 5 || todayIndex > 24) {//未开启 + // return resResult(STATUS.ACTIVITY_CLOSED); + // } + + let activityData = await signInActivity(ACTIVITY_TYPE.SIGN_IN, serverId, roleId); + if (!activityData) {//未配置活动数据 + return resResult(STATUS.ACTIVITY_MISSING); + } + + let acvitityId = activityData.acvitityId;//活动ID + let playerData = await getPlayerSignInData(acvitityId, 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 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'); + const funcs: number[] = session.get('funcs'); + + let todayIndex = moment(Date.now()).day(); + // if (todayIndex < 5 || todayIndex > 24) {//未开启 + // return resResult(STATUS.ACTIVITY_CLOSED); + // } + // if (todayIndex < dayIndex) { + // return resResult(STATUS.ACTIVITY_DAY_INDEX_OVER); + // } + + let activityData = await signInActivity(ACTIVITY_TYPE.SIGN_IN, serverId, roleId); + if (!activityData) {//未配置活动数据 + return resResult(STATUS.ACTIVITY_MISSING); + } + if (activityData.acvitityId != activityId) { + return resResult(STATUS.ACTIVITY_EXPIRE); + } + + let playerData = await getPlayerSignInData(activityId, serverId, roleId) + if (!playerData) return resResult(STATUS.ACTIVITY_MISSING); + + let signinItemData: SignInItem = playerData.findDayItem(dayIndex); + if (!signinItemData) { + return resResult(STATUS.ACTIVITY_DATA_ERROR); + } + if (!signinItemData.canReceive()) {//已经领取过 + return resResult(STATUS.ACTIVITY_REWARDED); + } + + await ActivitySignInModel.addSignInRecord(activityId, roleId, dayIndex); + let reward = signinItemData.goodReward(); + let goods = await addItems(roleId, roleName, sid, reward); + let heroReward = signinItemData.heroReward(); + let addHeros = []; + if (heroReward.length > 0) { + let heroResult = await createHeroes(roleId, roleName, sid, serverId, funcs, heroReward); + goods = goods.concat(heroResult.goods) + addHeros = addHeros.concat(heroResult.heroes); + } + + return resResult(STATUS.SUCCESS, { goods, addHeros }); + } + +} diff --git a/game-server/app/services/signInService.ts b/game-server/app/services/signInService.ts new file mode 100644 index 000000000..82547af8b --- /dev/null +++ b/game-server/app/services/signInService.ts @@ -0,0 +1,40 @@ +import { ActivityModel, ActivityModelType } from '../db/Activity'; +import { ActivitySignInModel, ActivitySignInModelType } from '../db/ActivitySignIn'; +import { SignInData, SignInItem } from '../domain/activityField/SignInField'; + +/** + * 获取活动数据 + * + * @param {number} type 普通、高级 ACTIVITY_TYPE + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function signInActivity(type: number, serverId: number, roleId: string) { + let activityArray: ActivityModelType[] = await ActivityModel.findOpenActivityByType(type, new Date()); + if (activityArray.length > 0) { + return activityArray[0]; + } + return null +} + +/** + * 玩家活动数据 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * + */ +export async function getPlayerSignInData(activityId: number, serverId: number, roleId: string) { + let activityData: ActivityModelType = await ActivityModel.findActivity(activityId, true); + let playerRecords: ActivitySignInModelType[] = await ActivitySignInModel.findData(activityId, roleId); + + let playerData = new SignInData(activityData); + playerData.setPlayerRecords(playerRecords); + + return playerData; +} + + diff --git a/shared/consts/constModules/activityConst.ts b/shared/consts/constModules/activityConst.ts index fc66ad6a6..69d0658fc 100644 --- a/shared/consts/constModules/activityConst.ts +++ b/shared/consts/constModules/activityConst.ts @@ -8,6 +8,8 @@ export enum ACTIVITY_TYPE { SEVEN_DAYS = 1, // 七天乐活动 TASK_GROWTH = 2, // 成长任务活动 TASK_DAILY_CHALLENGES = 3, // 今日挑战活动 + SIGN_IN = 4, // 签到活动 + SIGN_IN_VIP = 5, // 签到活动(高级) } /** diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 54cd3b816..847d245ca 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -343,6 +343,9 @@ export const STATUS = { ACTIVITY_MAX_COUNT: { code: 50006, simStr: '已经到最大次数' }, ACTIVITY_UNOPENED: { code: 50007, simStr: '还未开启,不能购买' }, ACTIVITY_RES_NOT_ENOUGH: { code: 50008, simStr: '资源不足' }, + ACTIVITY_CLOSED: { code: 50009, simStr: '关闭中' }, + ACTIVITY_DAY_INDEX_OVER: { code: 50010, simStr: '心急吃不了热豆腐' }, + ACTIVITY_EXPIRE: { code: 50011, simStr: '活动到期,刷新' }, // GM后台相关状态 60000 - 69999 GM_ERR_PASSWORD: { code: 60001, simStr: '账号或密码错误' }, GM_MISS_API: { code: 60002, simStr: '未找到该接口' }, diff --git a/shared/db/ActivitySignIn.ts b/shared/db/ActivitySignIn.ts new file mode 100644 index 000000000..315dc8c8a --- /dev/null +++ b/shared/db/ActivitySignIn.ts @@ -0,0 +1,47 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; + +/** + * 签到 +*/ +@index({ roleId: 1 }) + +export default class ActivitySignIn extends BaseModel { + @prop({ required: true }) + acvitityId: number; // 活动Id + @prop({ required: true }) + roleId: string; // 用户Id + @prop({ required: true }) + dayIndex: number; // 第几天 从1开始 + @prop({ required: true }) + isReceive: boolean; // 是否领取 + + //签到记录 + public static async addSignInRecord(acvitityId: number, roleId: string, dayIndex: number, lean = true) { + let result: ActivitySignInModelType = await ActivitySignInModel.findOneAndUpdate({ roleId, acvitityId, dayIndex }, + { $set: { isReceive: true } }, { upsert: true, new: true }).lean(lean); + return result; + } + + //根据活动id查询活动数据 + public static async findData(acvitityId: number, roleId: string, lean = true) { + let result: ActivitySignInModelType[] = await ActivitySignInModel.find({ roleId, acvitityId }).lean(lean); + return result; + } + + //查询第几天的活动数据 + public static async findDataByDayIndex(acvitityId: number, roleId: string, dayIndex: number, lean = true) { + let result: ActivitySignInModelType[] = await ActivitySignInModel.find({ roleId, acvitityId, dayIndex }).lean(lean); + return result; + } + + //删除签到记录 + public static async deleteActivity(acvitityId: number, roleId: string, dayIndex: number) { + await ActivitySignInModel.deleteMany({ roleId, acvitityId, dayIndex }); + } +} + +export const ActivitySignInModel = getModelForClass(ActivitySignIn); + +export interface ActivitySignInModelType extends Pick, keyof ActivitySignIn> { } +export type ActivitySignInModelTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/domain/activityField/activityField.ts b/shared/domain/activityField/activityField.ts index bddd8440a..c2b6fa5cc 100644 --- a/shared/domain/activityField/activityField.ts +++ b/shared/domain/activityField/activityField.ts @@ -22,7 +22,6 @@ export abstract class ActivityBase { this.endTime = activityData.endTime; this.type = activityData.type; // this.data = activityData.data; - this.initData(activityData.data); this.todayIndex = deltaDays(activityData.beginTime, new Date) + 1; console.log('今天是活动第几天', activityData.beginTime, new Date, this.todayIndex) } diff --git a/shared/domain/activityField/dailyChallengesField.ts b/shared/domain/activityField/dailyChallengesField.ts index a5c93895e..66672f8b2 100644 --- a/shared/domain/activityField/dailyChallengesField.ts +++ b/shared/domain/activityField/dailyChallengesField.ts @@ -38,7 +38,7 @@ export class DailyItem { let reward = parseHeroStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) } public goodReward(): RewardInter[] { @@ -48,7 +48,7 @@ export class DailyItem { let reward = parseGoodStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) } public canReceive(): boolean { @@ -138,5 +138,6 @@ export class DailyChallengesData extends ActivityBase { constructor(activityData: ActivityModelType) { super(activityData) + this.initData(activityData.data) } } \ No newline at end of file diff --git a/shared/domain/activityField/dailyGiftsField.ts b/shared/domain/activityField/dailyGiftsField.ts index 55e54df04..2d7e2f49e 100644 --- a/shared/domain/activityField/dailyGiftsField.ts +++ b/shared/domain/activityField/dailyGiftsField.ts @@ -41,7 +41,7 @@ export class DailyGiftItem { let reward = parseHeroStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) } public goodReward(): RewardInter[] { @@ -51,7 +51,7 @@ export class DailyGiftItem { let reward = parseGoodStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) } public canBuy(): boolean { @@ -89,5 +89,6 @@ export class DailyGiftsData extends ActivityBase { constructor(activityData: ActivityModelType) { super(activityData) + this.initData(activityData.data) } } \ No newline at end of file diff --git a/shared/domain/activityField/growthField.ts b/shared/domain/activityField/growthField.ts index e49774bb5..3abe9fc9e 100644 --- a/shared/domain/activityField/growthField.ts +++ b/shared/domain/activityField/growthField.ts @@ -46,7 +46,7 @@ export class GrowthItem { let reward = parseHeroStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) } public goodReward(): RewardInter[] { @@ -56,7 +56,7 @@ export class GrowthItem { let reward = parseGoodStrWithType(objStr); rewardArray.push(reward); } - return rewardArray.find(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) } public canReceive(): boolean { @@ -162,5 +162,6 @@ export class GrowthData extends ActivityBase { constructor(activityData: ActivityModelType) { super(activityData) + this.initData(activityData.data) } } \ No newline at end of file diff --git a/shared/domain/activityField/signInField.ts b/shared/domain/activityField/signInField.ts new file mode 100644 index 000000000..4a0cc1c25 --- /dev/null +++ b/shared/domain/activityField/signInField.ts @@ -0,0 +1,81 @@ +import { ACTIVITY_RESOURCES_TYPE } from '../../consts'; +import { ActivityModelType } from '../../db/Activity'; +import { ActivitySignInModelType } from '../../db/ActivitySignIn'; +import { RewardInter } from '../../pubUtils/interface'; +import { parseGoodStrWithType, parseHeroStrWithType } from '../../pubUtils/util'; +import { CreateHeroParam } from '../roleField/hero'; +import { ActivityBase } from './activityField'; + + +// 每天签到配置数据 +export class SignInItem { + dayIndex: number; // 第几天,从1开始 + reward: string; // 签到奖励,格式:1&3&1(类型&id&数量) 类型定义:1.英雄,2.物品 + + isReceive: boolean = false; //是否领取 + + constructor(data: any) { + console.log('dddddddddd', data) + this.dayIndex = data.dayIndex; + this.reward = data.reward; + } + + public heroReward(): CreateHeroParam[] { + let rewardArray = []; + let rewardData = this.reward.split('|').filter(obj => { return obj && obj != '' }); + for (let objStr of rewardData) { + let reward = parseHeroStrWithType(objStr); + rewardArray.push(reward); + } + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.HERO }) + } + + public goodReward(): RewardInter[] { + let rewardArray = []; + let rewardData = this.reward.split('|').filter(obj => { return obj && obj != '' }); + for (let objStr of rewardData) { + let reward = parseGoodStrWithType(objStr); + rewardArray.push(reward); + } + return rewardArray.filter(obj => { return obj && obj.type == ACTIVITY_RESOURCES_TYPE.GOODS }) + } + + public canReceive(): boolean { + return !this.isReceive; + } +} + + +// 成长活动数据 +export class SignInData extends ActivityBase { + list: Array = []; + + //第几天的签到奖励 + public findDayItem(dayIndex: number) { + let index = this.list.findIndex(obj => { return obj && obj.dayIndex == dayIndex }) + return (index != -1) ? this.list[index] : null; + } + + //解析玩家签到记录 + public setPlayerRecords(data: ActivitySignInModelType[]) { + for (let obj of this.list) { + let index = data.findIndex(record => { return obj.dayIndex == record.dayIndex }) + if (index != -1) { + obj.isReceive = data[index].isReceive; + } + } + } + + public initData(data: string) { + let arr = JSON.parse(data); + for (let obj of arr) { + console.log('obj', obj) + this.list.push(new SignInItem(obj)) + } + } + + constructor(activityData: ActivityModelType) { + super(activityData) + this.initData(activityData.data) + } +} \ No newline at end of file