172 lines
5.5 KiB
TypeScript
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 }
|
|
}
|
|
}
|