task-svr/src/controllers/tasks.controller.ts
2024-01-17 16:30:02 +08:00

201 lines
6.5 KiB
TypeScript

import { ZError, SyncLocker, BaseController, router } from 'zutils'
import { TaskCfg, TaskTypeEnum } from 'models/ActivityInfo'
import { TaskStatus, TaskStatusEnum } from 'models/ActivityUser'
import { join } from 'path'
import { formatDate } from 'zutils/utils/date.util'
const fs = require('fs')
const prod = process.env.NODE_ENV === 'production'
const initTasks = () => {
const tasks = join(__dirname, '../tasks')
const list = new Map()
fs.readdirSync(tasks)
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
.forEach((file: any) => {
const Task = require('../tasks/' + file)
list.set(Task.default.name, {
name: Task.default.name,
desc: Task.default.desc,
show: Task.default.show,
})
})
return list
}
const allTasks = initTasks()
export default class TasksController extends BaseController {
@router('post /api/tasks/progress')
async taskProgress(req) {
let user = req.user
let activity = req.activity
const dateTag = formatDate(new Date())
let taskAddedSet = new Set()
for (let task of user.taskProgress) {
if (task.dateTag) {
taskAddedSet.add(task.id + ':' + task.dateTag)
} else {
taskAddedSet.add(task.id)
}
}
let modified = false
let visibleTasks = new Set()
for (let task of activity.tasks) {
if (!allTasks.has(task.task)) {
continue
}
if (!task.isVaild()) {
continue
}
if (task.type === TaskTypeEnum.DAILY) {
let id = `${task.id}:${dateTag}`
if (!taskAddedSet.has(id)) {
modified = true
user.taskProgress.push({ id, task: task.task, dateTag: dateTag, status: TaskStatusEnum.NOT_START })
}
if (task.show) visibleTasks.add(id)
} else if (task.type === TaskTypeEnum.ONCE) {
if (!taskAddedSet.has(task.id)) {
modified = true
user.taskProgress.push({ id: task.id, task: task.task, status: TaskStatusEnum.NOT_START })
}
if (task.show) visibleTasks.add(task.id)
}
}
if (modified) {
await user.save()
}
return user.taskProgress.filter((t: TaskStatus) => visibleTasks.has(t.id))
}
@router('post /api/tasks/begin_task')
async beginTask(req) {
new SyncLocker().checkLock(req)
let user = req.user
let activity = req.activity
let { task } = req.params
const [taskId, dateTag] = task.split(':')
const currentDateTag = formatDate(new Date())
if (dateTag && currentDateTag !== dateTag) {
throw new ZError(11, 'task date not match')
}
if (!activity.isVaild()) {
throw new ZError(15, 'activity not start or end')
}
let cfg = activity.tasks.find((t: TaskCfg) => t.id === taskId)
if (!cfg) {
throw new ZError(12, 'task not found')
}
if (!cfg.isVaild()) {
throw new ZError(16, 'task not start or end')
}
if (dateTag && cfg.type !== TaskTypeEnum.DAILY) {
throw new ZError(13, 'task is not daily task')
}
if (cfg.pretasks && cfg.pretasks.length > 0) {
for (let preTask of cfg.pretasks) {
let preTaskData = user.taskProgress.find((t: TaskStatus) => {
if (preTask.type === TaskTypeEnum.DAILY) {
//这种情况下只要完成一次就算完成了
return t.id.indexOf(preTask) > -1
}
return t.id === preTask
})
if (
!preTaskData ||
preTaskData.status === TaskStatusEnum.NOT_START ||
preTaskData.status === TaskStatusEnum.RUNNING
) {
throw new ZError(14, 'task previous not finish')
}
}
}
let currentTask = user.taskProgress.find((t: TaskStatus) => t.id === task)
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) {
currentTask.timeStart = Date.now()
currentTask.status = TaskStatusEnum.RUNNING
}
await user.save()
return currentTask
}
@router('post /api/tasks/check_task')
async checkTask(req) {
const user = req.user
const activity = req.activity
const { task } = req.params
const [taskId, dateTag] = task.split(':')
const currentDateTag = formatDate(new Date())
if (dateTag && currentDateTag !== dateTag) {
throw new ZError(11, 'task date not match')
}
if (!activity.isVaild()) {
throw new ZError(15, 'activity not start or end')
}
let cfg = activity.tasks.find((t: TaskCfg) => t.id === taskId)
if (!cfg) {
throw new ZError(12, 'task not found')
}
if (!cfg.isVaild()) {
throw new ZError(16, 'task not start or end')
}
let currentTask = user.taskProgress.find((t: TaskStatus) => t.id === task)
if (!currentTask) {
throw new ZError(11, 'task not found')
}
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 || currentTask.status === TaskStatusEnum.PART_SUCCESS) {
let Task = require('../tasks/' + currentTask.task)
let taskInstance = new Task.default({ user, activity })
await taskInstance.execute({ task: currentTask })
}
return currentTask
}
@router('post /api/tasks/claim')
async claimTask(req) {
new SyncLocker().checkLock(req)
const user = req.user
const activity = req.activity
const { task } = req.params
const [taskId, dateTag] = task.split(':')
if (!activity.isVaild()) {
throw new ZError(15, 'activity not start or end')
}
let cfg = activity.tasks.find((t: TaskCfg) => t.id === taskId)
if (!cfg) {
throw new ZError(14, 'task not found')
}
if (!cfg.isVaild()) {
throw new ZError(16, 'task not start or end')
}
let currentTask = user.taskProgress.find((t: TaskStatus) => t.id === task)
if (!currentTask) {
throw new ZError(11, 'task not found')
}
if (currentTask.status === TaskStatusEnum.CLAIMED) {
throw new ZError(12, 'task already claimed')
}
if (currentTask.status !== TaskStatusEnum.SUCCESS && currentTask.status !== TaskStatusEnum.PART_SUCCESS) {
throw new ZError(13, 'task not end')
}
const Task = require('../tasks/' + currentTask.task)
const taskInstance = new Task.default({ user, activity })
await taskInstance.claimReward(currentTask)
return currentTask
}
}