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>(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 } } }