corgi/src/api/controllers/puzzle.controller.ts
2021-04-30 10:10:18 +08:00

172 lines
5.5 KiB
TypeScript

import BaseController from '../../common/base.controller'
import { role, router } from '../../decorators/router'
import { Puzzle } from '../../models/content/Puzzle'
import {
PuzzleSession,
PuzzleStatusClass
} from '../../models/match/PuzzleSession'
import { ZError } from '../../common/ZError'
import { BaseConst } from '../../constants/BaseConst'
import { mission_vo } from '../../config/parsers/mission_vo'
import {
createRoom,
updateScore
} from '../../services/WsSvr'
import { RoomState } from '../../services/RoomState'
import { retry } from '../../utils/promise.util'
import { RoomLockErr } from '../../common/RoomLockErr'
import { Schedule } from '../../clock/Schedule'
import {
checkSubFinish, sendOneQuestion,
startGame,
transformRecord
} from '../../services/GameLogic'
class PuzzleController extends BaseController {
@role('anon')
@router('post /api/:accountid/puzzle/list')
async list(req, res) {
let { shop, level, accountid } = req.params
level = +level || 1
const cfgs: mission_vo[] = Array.from(global.$cfg.get(BaseConst.MISSION).values())
const cfg = cfgs.find(o => o.number == level) || cfgs[cfgs.length - 1]
let count = cfg.beforehand_enemy || 10
let records = await Puzzle.randomQuestions({}, count)
let history = new PuzzleSession({ shop, level })
history.members.set(accountid, new PuzzleStatusClass())
history.questions = records.map(o => o._id)
history.expire = Date.now() + (cfg.time || 90) * 1000
history.type = 0
await history.save()
const results = transformRecord(records)
return {
session: history.id,
records: results
}
}
@role('anon')
@router('post /api/:accountid/puzzle/answer')
async report(req, res) {
let { id, answer, type, session, accountid, mode } = req.params
mode = mode || 0
if (!id || !session) {
throw new ZError(11, 'param mismatch')
}
let history = await PuzzleSession.findById(session)
if (!history) {
throw new ZError(13, 'not found match info')
}
if (history.status == 9 || history.hasExpired()) {
history.status = 9
await history.save()
throw new ZError(17, 'match end')
}
if (!history.members.has(accountid)) {
throw new ZError(14, 'not in current match')
}
if (!history.questions.find(o => o == id)) {
throw new ZError(16, 'current question not in current match')
}
let statMap = history.members.get(accountid)
if (statMap.answer.has(id)) {
throw new ZError(15, 'current question already answered')
}
let record = await Puzzle.findById(id)
if (!record) {
throw new ZError(12, 'question not found')
}
let result = record.a1 == answer ? 1 : 0
if (type == 1) {
result = 0
}
statMap.answer.set(id, result)
if (result == 1) {
statMap.rightCount++
statMap.comboCount++
statMap.maxCombo = Math.max(statMap.maxCombo, statMap.comboCount)
} else {
statMap.errorCount++
statMap.comboCount = 0
}
history.status = 1
history.markModified('members')
await history.save()
if (mode == 1) {
let score = result ? 3 : -1
await updateScore(history.room, [{accountid, score }])
if (checkSubFinish(history, id)) {
await sendOneQuestion(history)
}
}
return { result, answer: record.a1, stats: history.members }
}
@role('anon')
@router('post /api/:accountid/puzzle/match')
async joinMultipleGame(req, res) {
const { shop, accountid } = req.params
let data = { shop }
/**
* 查找店铺设置, 查看一定时间内是否有要开始的活动
* 如果有, 则读取配置, 加入开始游戏的定时
* 如果没有人请求, 说明没人参加, 也没必要开启定时了
* TODO:: 读取店铺活动配置
*/
let activityId = '1111111'
let roomId = ''
let sessionId = ''
let beginTime = 0
let result = new RoomState().isLock(shop)
try {
await retry<Promise<string>>(async () => {
if (result) {
throw new RoomLockErr('')
}
new RoomState().lock(shop)
let history = await PuzzleSession.findOne({ shop, status: 0, type: 1 })
if (history && !history.hasExpired()) {
new RoomState().unlock(shop)
beginTime = history.begin
history.members.set(accountid, new PuzzleStatusClass())
await history.save()
return roomId = history.room
} else {
let rsp = await createRoom(data)
if (rsp.status != 200) {
new RoomState().unlock(shop)
throw new ZError(11, 'error create room')
}
roomId = rsp.data?.room?.roomId
sessionId = rsp.data?.sessionId
history = new PuzzleSession({shop, status: 0, type: 1})
history.members.set(accountid, new PuzzleStatusClass())
history.room = roomId
//TODO: 根据配置赋值
const beginSecond = 20 * 1000
history.total = 10
history.begin = Date.now() + beginSecond
beginTime = history.begin
history.expire = history.begin + (100 || 90) * 1000
history.type = 1
await history.save()
new Schedule().beginSchedule(beginSecond, async function () {
await startGame(roomId, history)
}, shop)
new RoomState().unlock(shop)
return roomId
}
}, 0, [RoomLockErr])
} catch (err) {
new RoomState().unlock(shop)
throw new ZError(12, 'error create room')
}
return { roomId, beginTime,sessionId }
}
}