diff --git a/package.json b/package.json index c5e8c49..48e9a1c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "taskid": "ts-node -r tsconfig-paths/register src/generateTaskId.ts", "token": "ts-node -r tsconfig-paths/register src/generateToken.ts", "ingame": "ts-node -r tsconfig-paths/register src/fixIngame.ts", + "reward": "ts-node -r tsconfig-paths/register src/rewardSchedule.ts", "testdraw": "ts-node -r tsconfig-paths/register src/testdraw.ts", "test:watch": "jest --watch", "test": "jest" diff --git a/src/controllers/ingame.controller.ts b/src/controllers/ingame.controller.ts index 78bf0ed..9fad3af 100644 --- a/src/controllers/ingame.controller.ts +++ b/src/controllers/ingame.controller.ts @@ -3,7 +3,6 @@ import { SyncLocker } from 'common/SyncLocker' import { formatNumShow } from 'common/Utils' import logger from 'logger/logger' import { join } from 'path' -import { ActivityInfo } from 'models/ActivityInfo' import { ActivityUser } from 'models/ActivityUser' import { DrawRecord } from 'models/DrawRecord' import { InGameScoreRecord } from 'models/InGameScoreRecord' @@ -186,7 +185,7 @@ class InGameController extends BaseController { let position: number[] = [] const dateTag = formatDate(new Date()) for (let i = 0; i < step; i++) { - let reward = await drawOnce(user.inWhiteList) + let reward = await drawOnce(user.id, user.inWhiteList) let record = new DrawRecord({ user: user.id, score: 0, diff --git a/src/models/RewardRecrd.ts b/src/models/RewardRecrd.ts new file mode 100644 index 0000000..1e65350 --- /dev/null +++ b/src/models/RewardRecrd.ts @@ -0,0 +1,20 @@ +import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose' +import { dbconn } from 'decorators/dbconn' +import { BaseModule } from './Base' + +@dbconn() +@index({ type: 1 }, { unique: false }) +@modelOptions({ + schemaOptions: { collection: 'reward_add_record', timestamps: true }, +}) +class RewardRecordClass extends BaseModule { + @prop({ required: true }) + public type: number + + @prop() + public user: string + @prop() + public drawTime: number +} + +export const RewardRecord = getModelForClass(RewardRecordClass, { existingConnection: RewardRecordClass['db'] }) diff --git a/src/rewardSchedule.ts b/src/rewardSchedule.ts new file mode 100644 index 0000000..61f5dc7 --- /dev/null +++ b/src/rewardSchedule.ts @@ -0,0 +1,32 @@ +import * as dotenv from 'dotenv' +const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development' +dotenv.config({ path: envFile }) +import logger from 'logger/logger' +import { ZRedisClient } from 'zutils' +import * as schedule from 'node-schedule' + +const REDIS_KEY = `draw_1` +import { RewardRecord } from 'models/RewardRecrd' + +const addRewards = async (type: number) => { + logger.info('schedule add rewards for type: ', type) + try { + for (let i = 0; i < 10; i++) { + let record = new RewardRecord({ type }) + await record.save() + new ZRedisClient().pub.sadd(REDIS_KEY, record.id) + } + } catch (e) { + console.log(e) + } +} + +;(async () => { + let opts = { url: process.env.REDIS } + new ZRedisClient(opts) + logger.info('REDIS Connected') + schedule.scheduleJob('0 0 0 * * *', async () => { + await addRewards(1) + }) + addRewards(1) +})() diff --git a/src/services/game.svr.ts b/src/services/game.svr.ts index af063d8..5b36788 100644 --- a/src/services/game.svr.ts +++ b/src/services/game.svr.ts @@ -3,6 +3,8 @@ import { ActivityChest, ActivityChestClass, ChestStatusEnum } from 'models/Activ import { ZError, ZRedisClient } from 'zutils' import { DocumentType } from '@typegoose/typegoose' import { timeoutFetch } from 'zutils/utils/net.util' +import { RewardRecord } from 'models/RewardRecrd' +import logger from 'logger/logger' export const drawCfgs = require('../../configs/draw_cfg.json') // 处理draw_cfg.json中的probability, 计算出每个奖励的概率区间 @@ -160,7 +162,7 @@ export const queryInGameInfo = async (openId: string, channel: string) => { * 根据drawCfgs中设定的probability, 抽取指定的奖励 * 如果抽到的type为1或2, 则从redis中spop一个值, 如果该值为空, 则再次调用本方法, 直到抽到奖励位置 * */ -export const drawOnce = async (hasWhite: boolean) => { +export const drawOnce = async (userId: string, hasWhite: boolean) => { let random = Math.random() * probability let reward for (let i = 0; i < drawCfgs.length; i++) { @@ -172,14 +174,22 @@ export const drawOnce = async (hasWhite: boolean) => { } } if (!reward) { - return drawOnce(hasWhite) + return drawOnce(userId, hasWhite) } if (reward.type === 1 || reward.type === 2) { const redisKey = `draw_${reward.type}` const itemId = await new ZRedisClient().spop(redisKey) if (!itemId) { - return drawOnce(hasWhite) + return drawOnce(userId, hasWhite) } + // double check if the record is exist + let record = await RewardRecord.findById(itemId) + if (!record) { + logger.info('record not found: ', itemId) + return drawOnce(userId, hasWhite) + } + record.user = userId + await record.save() reward.id = itemId } return reward diff --git a/src/testdraw.ts b/src/testdraw.ts index 995c0f0..1ece200 100644 --- a/src/testdraw.ts +++ b/src/testdraw.ts @@ -9,19 +9,19 @@ import { drawOnce } from 'services/game.svr' import { ZRedisClient } from 'zutils' ;(async () => { try { - let opts = { url: process.env.REDIS } - new ZRedisClient(opts) - let resultMap = new Map() - const total = 10000 - for (let i = 0; i < total; i++) { - let reward = await drawOnce(false) - // console.log(reward) - resultMap.set(reward.amount, (resultMap.get(reward.amount) || 0) + 1) - } - for (let [key, value] of resultMap) { - console.log(key, value, parseFloat(value) / parseFloat(total + '')) - } - process.exit(0) + // let opts = { url: process.env.REDIS } + // new ZRedisClient(opts) + // let resultMap = new Map() + // const total = 10000 + // for (let i = 0; i < total; i++) { + // let reward = await drawOnce(false) + // // console.log(reward) + // resultMap.set(reward.amount, (resultMap.get(reward.amount) || 0) + 1) + // } + // for (let [key, value] of resultMap) { + // console.log(key, value, parseFloat(value) / parseFloat(total + '')) + // } + // process.exit(0) } catch (e) { console.error(e) }