增加挑战结算的定时任务

This commit is contained in:
zhl 2021-07-08 20:54:46 +08:00
parent 5a90fb3e1c
commit cf07e39ffe
6 changed files with 185 additions and 2 deletions

View File

@ -44,6 +44,7 @@
"mongoose-findorcreate": "^3.0.0",
"nanoid": "^3.1.23",
"node-html-to-image": "^3.1.0",
"node-schedule": "^2.0.0",
"qrcode": "^1.4.4",
"querystring": "^0.2.1",
"queue": "^6.0.2",
@ -62,6 +63,7 @@
"@types/dotenv": "^8.2.0",
"@types/mongoose": "5.10.3",
"@types/node": "^14.14.20",
"@types/node-schedule": "^1.3.2",
"@types/redis": "^2.8.28",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",

View File

@ -9,6 +9,7 @@ import { AdminRole } from 'models/admin/AdminRole'
import { Shop } from './models/shop/Shop'
import { MongoTool } from './services/MongoTool'
import { GameItem } from './models/content/GameItem'
import ExamSchedule from './schedule/exam.schedule'
const rbacPlugin = require('plugins/zrbac')
const zAuthPlugin = require('plugins/zauth')
@ -148,6 +149,11 @@ export class AdminServer {
new MongoTool().init('gameitem', id)
}
private initSchedules() {
new ExamSchedule().scheduleAll()
// new ExamSchedule().parseAllRecord()
}
public async start() {
let self = this
return new Promise(async (resolve, reject) => {
@ -158,6 +164,7 @@ export class AdminServer {
self.registerRouter()
self.setErrHandler()
self.setFormatSend()
self.initSchedules()
this.server.listen({ port: config.admin.port }, (err: any, address: any) => {
if (err) {
logger.log(err)

View File

@ -1,10 +1,11 @@
import { dbconn } from '../../decorators/dbconn'
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { getModelForClass, index, modelOptions, prop, ReturnModelType } from '@typegoose/typegoose'
import { BaseModule } from '../Base'
import { noJson } from '../../decorators/nojson'
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
import { Base } from '@typegoose/typegoose/lib/defaultClasses'
import { CompactPuzzleClass } from '../match/PuzzleSession'
import { AdminClass } from '../admin/Admin'
export class ShopPuzzleClass extends Base {
@prop()
@ -70,7 +71,7 @@ export class ExamRewardClass extends Base {
/**
*
* @type {number} 0: 单局, 1: 累积
* @type {number} 0: 单局, 1: 累积 2: 累计排名
*/
@prop({ default: 0 })
public type: number
@ -192,6 +193,19 @@ export class ShopExamClass extends BaseModule {
@prop({ type: [ShopPuzzleClass] })
public questions: ShopPuzzleClass[]
/**
*
* @type {number} 0: 默认状态, 9: 奖励已发放
*/
@prop({ default: 0 })
public status: number
/**
*
*/
public static allUnSettleRecords(this: ReturnModelType<typeof ShopExamClass>) {
return this.find({ endTime: { $gte: Date.now() }, status: { $ne: 9 } })
}
public static parseQueryParam(params) {
let { key, timeBegin, timeEnd, active, shop, source } = params
let opt: any = { deleted: false }
@ -239,6 +253,25 @@ export class ShopExamClass extends BaseModule {
return results
}
/**
*
* @param {number} rank
*/
public getRewardByRank(rank: number) {
if (!this.rewardInfo || this.rewardInfo.length === 0) {
return []
}
let results = []
for (let reward of this.rewardInfo) {
if (rank <= reward.rank && reward.type === 2) {
results.push({ id: reward._id + '', coupon: reward.coupon, count: reward.count })
break
}
}
return results
}
public toPartnerJson() {
const exportKeys = [
'_id',

View File

@ -73,6 +73,18 @@ export class UserMailClass extends BaseModule {
return record
}
public static async addOneMail({ accountId, shop, items, title, content, senderShop }) {
let record = new UserMail({})
record.title = title
record.content = content
record.sender = shop
record.accountId = accountId
record.items = items
record.senderShop = senderShop
record.expire = Date.now() + 3600 * 24 * 15 * 1000
await record.save()
}
public static async updateExpire(accountId: string) {
await UserMail.updateMany(
{ accountId, deleted: false, expire: { $lt: Date.now() } },

View File

@ -0,0 +1,70 @@
import * as schedule from 'node-schedule'
import { singleton } from '../decorators/singleton'
import { ShopExam } from '../models/shop/ShopExam'
import { getRankCount, getRankList } from '../services/Rank'
import { rankKey } from '../services/GameLogic'
import { UserMail } from '../models/user/UserMail'
import { Coupon } from '../models/shop/Coupon'
import { Shop } from '../models/shop/Shop'
@singleton
export default class ExamSchedule {
async parseOneExam(data: any) {
const shop = data.shop
let shopName = ''
const shopData = await Shop.fetchByID(shop)
if (shopData) {
shopName = shopData.showName
}
const level = data.id + '_total'
const mode = 2
const skip = 0
const key = rankKey(shop, level, mode)
const limit = (await getRankCount(key)) as number
let datas: any = await getRankList(skip, limit, key)
const accountIDS = []
for (let i = 0, l = datas.length; i < l; i += 2) {
accountIDS.push(datas[i])
}
data.rewardInfo.sort((a, b) => a.rank - b.rank)
for (let i = 0, l = accountIDS.length; i < l; i++) {
let rewards = data.getRewardByRank(i + 1)
let items = []
for (let r of rewards) {
let name = '抽奖券'
if (r.type === 0) {
let cdata = await Coupon.findById(r.coupon)
if (cdata) {
name = cdata.name
}
}
items.push({
itemId: r.coupon,
name,
count: r.count,
})
}
const title = `${data.name}${i + 1}名奖励`
const content = `您在 ${shopName}${data.name}活动中获得第${i + 1}名, 获得如下奖励`
await UserMail.addOneMail({
accountId: accountIDS[i],
shop,
items,
title,
content,
senderShop: shopName,
})
}
}
async parseAllRecord() {
let records = await ShopExam.allUnSettleRecords()
for (let record of records) {
await this.parseOneExam(record)
}
}
scheduleAll() {
const job = schedule.scheduleJob('1 0 0 * * *', async () => {
await this.parseAllRecord()
})
}
}

View File

@ -194,6 +194,13 @@
"@types/mongodb" "*"
"@types/node" "*"
"@types/node-schedule@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@types/node-schedule/-/node-schedule-1.3.2.tgz#cc7e32c6795cbadc8de03d0e1f86311727375423"
integrity sha512-Y0CqdAr+lCpArT8CJJjJq4U2v8Bb5e7ru2nV/NhDdaptCMCRdOL3Y7tAhen39HluQMaIKWvPbDuiFBUQpg7Srw==
dependencies:
"@types/node" "*"
"@types/node@*", "@types/node@^14.14.20":
version "14.14.41"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615"
@ -773,6 +780,14 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cron-parser@^3.1.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-3.5.0.tgz#b1a9da9514c0310aa7ef99c2f3f1d0f8c235257c"
integrity sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==
dependencies:
is-nan "^1.3.2"
luxon "^1.26.0"
cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@ -870,6 +885,13 @@ default-user-agent@^1.0.0:
dependencies:
os-name "~1.0.3"
define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
object-keys "^1.0.12"
degenerator@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-2.2.0.tgz#49e98c11fa0293c5b26edfbb52f15729afcdb254"
@ -1845,6 +1867,14 @@ is-json@^2.0.1:
resolved "https://registry.yarnpkg.com/is-json/-/is-json-2.0.1.tgz#6be166d144828a131d686891b983df62c39491ff"
integrity sha1-a+Fm0USCihMdaGiRuYPfYsOUkf8=
is-nan@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
dependencies:
call-bind "^1.0.0"
define-properties "^1.1.3"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@ -2092,6 +2122,11 @@ loglevel@^1.6.7, loglevel@^1.7.0:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
long-timeout@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514"
integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@ -2106,6 +2141,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
luxon@^1.26.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.27.0.tgz#ae10c69113d85dab8f15f5e8390d0cbeddf4f00f"
integrity sha512-VKsFsPggTA0DvnxtJdiExAucKdAnwbCCNlMM5ENvHlxubqWd0xhZcdb4XgZ7QFNhaRhilXCFxHuoObP5BNA4PA==
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
@ -2308,6 +2348,15 @@ node-html-to-image@^3.1.0:
puppeteer "3.0.0"
puppeteer-cluster "^0.21.0"
node-schedule@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-2.0.0.tgz#73ab4957d056c63708409cc1fab676e0e149c191"
integrity sha512-cHc9KEcfiuXxYDU+HjsBVo2FkWL1jRAUoczFoMIzRBpOA4p/NRHuuLs85AWOLgKsHtSPjN8csvwIxc2SqMv+CQ==
dependencies:
cron-parser "^3.1.0"
long-timeout "0.1.1"
sorted-array-functions "^1.3.0"
nth-check@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
@ -2330,6 +2379,11 @@ object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.2.tgz#b6385a3e2b7cae0b5eafcf90cddf85d128767f30"
integrity sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==
object-keys@^1.0.12:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@ -3011,6 +3065,11 @@ sonic-boom@^1.0.2:
atomic-sleep "^1.0.0"
flatstr "^1.0.12"
sorted-array-functions@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5"
integrity sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==
source-map-support@^0.5.17:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"