增加任务repeat的支持
This commit is contained in:
parent
a41fb9aa3a
commit
145a5cb06c
@ -105,6 +105,7 @@ SiweMessage的nonce说明(具体参考例子):
|
||||
"title": "任务名",
|
||||
"desc": "任务描述",
|
||||
"type": 1, //任务类型, 1: 一次性任务, 2: 日常任务
|
||||
"repeat": 1, // 任务可重复次数
|
||||
"pretasks": ["task id 1"], //前置任务
|
||||
"score": 0, // 完成任务可获得的积分
|
||||
"category": "", // 任务分类
|
||||
|
@ -199,6 +199,7 @@
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"repeat": 2,
|
||||
"title": "Hero NFT",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
@ -212,6 +213,7 @@
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"repeat": 2,
|
||||
"title": "Candy Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
@ -224,6 +226,7 @@
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"repeat": 2,
|
||||
"title": "Explorer Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
@ -237,6 +240,7 @@
|
||||
"task": "BurnNft",
|
||||
"type": 1,
|
||||
"show": true,
|
||||
"repeat": 2,
|
||||
"title": "Gacha Badge",
|
||||
"desc": "Click to burn and redeem Flame",
|
||||
"category": "CF Pal",
|
||||
|
@ -96,12 +96,12 @@ export default class TasksController extends BaseController {
|
||||
return t.id === preTask
|
||||
});
|
||||
if (!preTaskData || (preTaskData.status === TaskStatusEnum.NOT_START || preTaskData.status === TaskStatusEnum.RUNNING)) {
|
||||
throw new ZError(14, 'task previous not end')
|
||||
throw new ZError(14, 'task previous not finish')
|
||||
}
|
||||
}
|
||||
}
|
||||
let currentTask = user.taskProgress.find((t: TaskStatus) => t.id === task);
|
||||
if (currentTask.status === TaskStatusEnum.SUCCESS || currentTask.status === TaskStatusEnum.CLAIMED) {
|
||||
if (currentTask.status === TaskStatusEnum.PART_SUCCESS || currentTask.status === TaskStatusEnum.SUCCESS || currentTask.status === TaskStatusEnum.CLAIMED) {
|
||||
throw new ZError(15, 'task already end')
|
||||
}
|
||||
if (currentTask.status === TaskStatusEnum.NOT_START) {
|
||||
@ -126,13 +126,13 @@ export default class TasksController extends BaseController {
|
||||
if (!currentTask) {
|
||||
throw new ZError(11, 'task not found')
|
||||
}
|
||||
if (currentTask.status === TaskStatusEnum.SUCCESS || currentTask.status === TaskStatusEnum.CLAIMED) {
|
||||
if (currentTask.status === TaskStatusEnum.CLAIMED) {
|
||||
return currentTask;
|
||||
}
|
||||
if (currentTask.status === TaskStatusEnum.NOT_START) {
|
||||
throw new ZError(11, 'task not begin');
|
||||
}
|
||||
if (currentTask.status === TaskStatusEnum.RUNNING) {
|
||||
if (currentTask.status === TaskStatusEnum.RUNNING || currentTask.status === TaskStatusEnum.PART_SUCCESS) {
|
||||
let Task = require('../tasks/' + currentTask.task);
|
||||
let taskInstance = new Task.default({user, activity});
|
||||
await taskInstance.execute({task: currentTask});
|
||||
@ -152,7 +152,7 @@ export default class TasksController extends BaseController {
|
||||
if (currentTask.status === TaskStatusEnum.CLAIMED) {
|
||||
throw new ZError(12, 'task already claimed')
|
||||
}
|
||||
if (currentTask.status !== TaskStatusEnum.SUCCESS) {
|
||||
if (currentTask.status !== TaskStatusEnum.SUCCESS && currentTask.status !== TaskStatusEnum.PART_SUCCESS) {
|
||||
throw new ZError(13, 'task not end')
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { dbconn } from 'decorators/dbconn'
|
||||
import findOrCreate from 'mongoose-findorcreate'
|
||||
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
|
||||
import { BaseModule } from './Base'
|
||||
import exp from 'constants'
|
||||
|
||||
|
||||
export enum TaskTypeEnum {
|
||||
ONCE = 1,
|
||||
@ -20,6 +20,8 @@ export class TaskCfg {
|
||||
title: string
|
||||
@prop({ enum: TaskTypeEnum, default: TaskTypeEnum.ONCE })
|
||||
type: TaskTypeEnum
|
||||
@prop({default: 1})
|
||||
repeat: number
|
||||
@prop()
|
||||
desc: string
|
||||
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||
@ -76,6 +78,7 @@ class ActivityInfoClass extends BaseModule {
|
||||
title: task.title,
|
||||
desc: task.desc,
|
||||
type: task.type,
|
||||
repeat: task.repeat,
|
||||
pretasks: task.pretasks,
|
||||
score: task.score,
|
||||
category: task.category,
|
||||
|
@ -13,6 +13,7 @@ export enum TaskStatusEnum {
|
||||
RUNNING = 1,
|
||||
SUCCESS = 2,
|
||||
CLAIMED = 3,
|
||||
PART_SUCCESS = 4,
|
||||
}
|
||||
|
||||
@modelOptions({ schemaOptions: { _id: false }, options: { allowMixed: Severity.ALLOW }})
|
||||
|
@ -10,16 +10,12 @@ import { BaseModule } from './Base'
|
||||
class NftBurnRecordClass extends BaseModule {
|
||||
@prop({ required: true})
|
||||
public user: string
|
||||
|
||||
@prop()
|
||||
public chain: number
|
||||
|
||||
@prop({ required: true})
|
||||
public address: string
|
||||
|
||||
@prop()
|
||||
public tokenId: number
|
||||
|
||||
public tokenId: string
|
||||
@prop()
|
||||
public activity: string
|
||||
@prop()
|
||||
|
@ -21,31 +21,50 @@ export default class BurnNft extends ITask {
|
||||
const localNft = await NftBurnRecord.find({
|
||||
user: this.params.user.id,
|
||||
chain,
|
||||
address
|
||||
address,
|
||||
})
|
||||
const localNftSet = new Set();
|
||||
let finishAmount = 0;
|
||||
let tmpNftSet = new Set();
|
||||
for (let nft of localNft) {
|
||||
localNftSet.add(nft.tokenId)
|
||||
}
|
||||
let finishNft
|
||||
for (let nft of nftList) {
|
||||
if (!localNftSet.has(nft.tokenId)) {
|
||||
finishNft = nft.tokenId
|
||||
break;
|
||||
if (nft.activity === this.params.activity.id && nft.task === task.id) {
|
||||
finishAmount += 1
|
||||
tmpNftSet.add(nft.tokenId)
|
||||
}
|
||||
}
|
||||
const record = new NftBurnRecord({
|
||||
user: this.params.user.id,
|
||||
chain,
|
||||
address,
|
||||
tokenId: finishNft,
|
||||
activity: this.params.activity.id,
|
||||
task: task.id
|
||||
})
|
||||
await record.save()
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
task.data = {tokenId: finishNft}
|
||||
let finishNfts = new Set();
|
||||
for (let nft of nftList) {
|
||||
if (!localNftSet.has(nft.tokenId)) {
|
||||
finishNfts.add(nft.tokenId)
|
||||
finishAmount += 1
|
||||
if (finishAmount >= cfg.repeat) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let finishNft of finishNfts) {
|
||||
const record = new NftBurnRecord({
|
||||
user: this.params.user.id,
|
||||
chain,
|
||||
address,
|
||||
tokenId: finishNft,
|
||||
activity: this.params.activity.id,
|
||||
task: task.id
|
||||
})
|
||||
await record.save()
|
||||
}
|
||||
let dataToSave = task.data || {}
|
||||
dataToSave.tokenId = [...tmpNftSet, ...finishNfts]
|
||||
dataToSave.finishAmount = finishAmount
|
||||
task.data = dataToSave
|
||||
task.markModified('data')
|
||||
if (finishAmount >= cfg.repeat) {
|
||||
task.status = TaskStatusEnum.SUCCESS
|
||||
task.timeFinish = Date.now()
|
||||
} else if (finishAmount > 0) {
|
||||
task.status = TaskStatusEnum.PART_SUCCESS
|
||||
}
|
||||
try {
|
||||
await this.params.user.save()
|
||||
} catch(err) {
|
||||
@ -60,5 +79,4 @@ export default class BurnNft extends ITask {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
@ -14,30 +14,40 @@ export abstract class ITask {
|
||||
}
|
||||
abstract execute(data: any): Promise<boolean>
|
||||
|
||||
public async claimReward(task: TaskStatus) {
|
||||
public async claimReward(task: any) {
|
||||
const user = this.params.user
|
||||
const [taskId, dateTag] = task.id.split(':');
|
||||
const cfg = this.params.activity.tasks.find((t: TaskCfg) => t.id === taskId)
|
||||
if (!cfg.score) {
|
||||
return;
|
||||
}
|
||||
let claimAmount = task.data.claimAmount || 0
|
||||
let score = cfg.score
|
||||
if (user.boost > 1 && Date.now() < user.boostExpire) {
|
||||
score = Math.floor(score * user.boost)
|
||||
}
|
||||
await updateRankScore({
|
||||
user: user.id,
|
||||
score: score,
|
||||
activity: user.activity,
|
||||
scoreType: cfg.task,
|
||||
scoreParams: {
|
||||
date: dateTag,
|
||||
taskId: task.id,
|
||||
boost: user.boost
|
||||
}
|
||||
})
|
||||
task.status = TaskStatusEnum.CLAIMED
|
||||
task.timeClaim = Date.now()
|
||||
let finishAmount = cfg.repeat > 1 ? task.data.finishAmount || 0 : 1
|
||||
for (let i = claimAmount; i < Math.min(cfg.repeat, finishAmount); i++) {
|
||||
await updateRankScore({
|
||||
user: user.id,
|
||||
score: score,
|
||||
activity: user.activity,
|
||||
scoreType: cfg.task,
|
||||
scoreParams: {
|
||||
date: dateTag,
|
||||
taskId: task.id,
|
||||
boost: user.boost
|
||||
}
|
||||
})
|
||||
claimAmount += 1
|
||||
}
|
||||
task.data.claimAmount = claimAmount
|
||||
task.markModified('data')
|
||||
if ((cfg.repeat > 1 && claimAmount >= cfg.repeat)
|
||||
|| (cfg.repeat === 1 && claimAmount >= 1)) {
|
||||
task.status = TaskStatusEnum.CLAIMED
|
||||
task.timeClaim = Date.now()
|
||||
}
|
||||
await user.save()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user