From 7cc642e2aec4c9ed34dec8ae490ce79b1733ecb2 Mon Sep 17 00:00:00 2001 From: zhl Date: Thu, 10 Jun 2021 15:09:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=AD=94=E6=A1=88=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/api.md | 28 ++++++++ src/api/controllers/puzzle.controller.ts | 84 +++++++++++++++++------- src/constants/BaseConst.ts | 2 + src/models/Base.ts | 5 +- src/models/match/PuzzleSession.ts | 7 ++ 5 files changed, 99 insertions(+), 27 deletions(-) diff --git a/doc/api.md b/doc/api.md index 43015fe..78cf405 100644 --- a/doc/api.md +++ b/doc/api.md @@ -736,3 +736,31 @@ | 字段 | 说明 | | -------- | -------------------------------------- | | ids | 邮件id数组 | + + +### 21. 显示正确答案 + +1. Method: POST +2. URI: /api/:accountId/puzzle/help + +| 字段 | 说明 | +| -------- | -------------------------------------- | +| accountid | 帐号id | + +> POST参数 + + +| 字段 | 说明 | +| -------- | -------------------------------------- | +| id | 题目id | +| session | 当局的id, 从关卡题目列表中获取 | + +3. Response: JSON + +```js +{ + answer: '1123123' + } +``` + +> 说明, 这里获取的answer是使用 当前比赛session_当前题目的id_答案_jcfw中的sessionid, 计算md5 \ No newline at end of file diff --git a/src/api/controllers/puzzle.controller.ts b/src/api/controllers/puzzle.controller.ts index 7b55780..f06c52c 100644 --- a/src/api/controllers/puzzle.controller.ts +++ b/src/api/controllers/puzzle.controller.ts @@ -25,6 +25,8 @@ import { Shop, validShopId } from '../../models/shop/Shop' import { ShopActivity } from '../../models/shop/ShopActivity' import { GameUser } from '../../models/user/GameUser' import { isObjectId } from '../../utils/string.util' +import { SINGLE_HELP_COUNT } from '../../constants/BaseConst' +import { md5 } from '../../utils/security.util' class PuzzleController extends BaseController { @role('anon') @@ -44,9 +46,9 @@ class PuzzleController extends BaseController { } @role('anon') - @router('post /api/:accountid/puzzle/list') + @router('post /api/:accountId/puzzle/list') async list(req, res) { - let { shop, level, accountid, type } = req.params + let { shop, level, accountId, type } = req.params level = +level || 1 if (!shop || !validShopId(shop)) { throw new ZError(10, `type: ${type} level:${level} 没有店铺id或者店铺id格式不正确, ${shop}`) @@ -62,7 +64,7 @@ class PuzzleController extends BaseController { let record3 = await Puzzle.randomQuestions(Object.assign(params, { quality: 3 }), 5) const records = record1.concat(record2).concat(record3) let history = new PuzzleSession({ shop: shopId, level }) - history.members.set(accountid, new PuzzleStatusClass()) + history.members.set(accountId, new PuzzleStatusClass()) for (let record of records) { history.questions.set(record.id, record.compactRecord(true)) } @@ -79,9 +81,9 @@ class PuzzleController extends BaseController { } @role('anon') - @router('post /api/:accountid/puzzle/answer') + @router('post /api/:accountId/puzzle/answer') async report(req, res) { - let { id, answer, type, session, accountid, mode, debug } = req.params + let { id, answer, type, session, accountId, mode, debug } = req.params mode = mode || 0 if (!id || !session) { throw new ZError(11, 'param mismatch') @@ -90,7 +92,7 @@ class PuzzleController extends BaseController { if (!history) { throw new ZError(13, 'not found match info') } - if (!history.members.has(accountid)) { + if (!history.members.has(accountId)) { throw new ZError(14, 'not in current match') } if (!history.questions.has(id)) { @@ -105,7 +107,7 @@ class PuzzleController extends BaseController { if (history.status == 9 || history.hasExpired()) { result = -1 } - let statMap = history.members.get(accountid) + let statMap = history.members.get(accountId) if (statMap.answer.has(id)) { throw new ZError(15, 'current question already answered') } @@ -136,8 +138,8 @@ class PuzzleController extends BaseController { if (record.type === 3) { score = 0 } - await broadcast(history.room, 'answer', { accountid, result, score }) - await updateScore(history.room, [{ accountid, score }]) + await broadcast(history.room, 'answer', { accountid: accountId, result, score }) + await updateScore(history.room, [{ accountid: accountId, score }]) if (checkSubFinish(history, id)) { if (new Schedule().getLeftTime(history.scheduleKey) > 1000) { @@ -154,15 +156,15 @@ class PuzzleController extends BaseController { await sendOneQuestion(history) } } else if (mode == 0) { - gameResult = checkSingleFinish(history, accountid) + gameResult = checkSingleFinish(history, accountId) if (gameResult) { history.status = 9 if (gameResult === 1) { - let { score } = calcSingleScore(history, accountid) + let { score } = calcSingleScore(history, accountId) let rankObj = { shop: history.shop, level: history.level, - accountId: accountid, + accountId: accountId, score, mode: 0, session: history.id, @@ -174,7 +176,7 @@ class PuzzleController extends BaseController { let { rankList, userRank } = await getRank({ shop: history.shop, level: history.level, - accountId: accountid, + accountId: accountId, mode: 0, skip: 0, limit: 20, @@ -188,9 +190,9 @@ class PuzzleController extends BaseController { } @role('anon') - @router('post /api/:accountid/puzzle/more') + @router('post /api/:accountId/puzzle/more') async moreLevelQuestions(req, res) { - let { session, accountid, count, quality } = req.params + let { session, accountId, count, quality } = req.params count = count ? +count : 10 if (!session) { throw new ZError(11, 'param mismatch') @@ -204,7 +206,7 @@ class PuzzleController extends BaseController { await history.save() throw new ZError(17, 'match end') } - if (!history.members.has(accountid)) { + if (!history.members.has(accountId)) { throw new ZError(14, 'not in current match') } let ids = Array.from(history.questions.keys()) @@ -226,10 +228,10 @@ class PuzzleController extends BaseController { } @role('anon') - @router('post /api/:accountid/puzzle/match') + @router('post /api/:accountId/puzzle/match') async joinMultipleGame(req, res) { - let { shop, aid, accountid, debug_begin_sec, debug_qcount } = req.params - let data: any = { shop, maxTime: 3600, accountid } + let { shop, aid, accountId, debug_begin_sec, debug_qcount } = req.params + let data: any = { shop, maxTime: 3600, accountid: accountId } let beginSecond = debug_begin_sec ? +debug_begin_sec : 10 beginSecond = Math.max(2, beginSecond) * 1000 /** @@ -247,7 +249,7 @@ class PuzzleController extends BaseController { } let activity = await ShopActivity.findById(aid) let shopData = await Shop.fetchByID(shop) - let gameUser = await GameUser.getByAccountID(accountid) + let gameUser = await GameUser.getByAccountID(accountId) if (gameUser) { data.nickname = gameUser.nickname data.avatar = gameUser.avatar @@ -277,7 +279,7 @@ class PuzzleController extends BaseController { if (history && !history.hasExpired()) { beginTime = history.begin sessionMatch = history.id - if (!history.members.has(accountid)) { + if (!history.members.has(accountId)) { let rsp = await joinRoom(Object.assign(data, { roomId: history.room })) if (rsp.status != 200) { new RoomState().unlock(shop) @@ -286,13 +288,13 @@ class PuzzleController extends BaseController { let memberData = new PuzzleStatusClass() sessionId = rsp.data?.sessionId memberData.sessionId = sessionId - history.members.set(accountid, memberData) + history.members.set(accountId, memberData) history.markModified('members') await history.save() new RoomState().unlock(shop) return (roomId = history.room) } else { - let memberData = history.members.get(accountid) + let memberData = history.members.get(accountId) sessionId = memberData.sessionId roomId = history.room new RoomState().unlock(shop) @@ -310,7 +312,7 @@ class PuzzleController extends BaseController { history.activityId = aid let memberData = new PuzzleStatusClass() memberData.sessionId = sessionId - history.members.set(accountid, memberData) + history.members.set(accountId, memberData) history.room = roomId //TODO: 根据配置赋值 history.total = debug_qcount || activity.qcount @@ -363,4 +365,38 @@ class PuzzleController extends BaseController { let { rankList, userRank, rankTotal } = await getRank({ shop, level, accountId, mode, skip, limit }) return { rankList, userRank, rankTotal } } + + @role('anon') + @router('post /api/:accountId/puzzle/help') + async help(req) { + let { id, session, accountId, sessionid } = req.params + 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.hasExpired()) { + throw new ZError(18, 'match has expired') + } + if (history.type !== 0) { + throw new ZError(18, 'only available in single mode') + } + if (history.helpCount >= SINGLE_HELP_COUNT) { + throw new ZError(17, 'reach max count') + } + if (!history.members.has(accountId)) { + throw new ZError(14, 'not in current match') + } + if (!history.questions.has(id)) { + throw new ZError(16, 'current question not in current match') + } + let record = history.questions.get(id) + history.helpCount += 1 + await history.save() + let hashStr = `${session}_${id}_${record.answers[0]}_${sessionid}` + let hash = md5(hashStr) + return { answer: hash } + } } diff --git a/src/constants/BaseConst.ts b/src/constants/BaseConst.ts index 7608cce..b8ebe83 100644 --- a/src/constants/BaseConst.ts +++ b/src/constants/BaseConst.ts @@ -13,3 +13,5 @@ export class BaseConst { // 抽奖券的物品id export const LOTTERY_TICKET = 'lottery_ticket' export const EMPTY = 'empty' +// 单人模式使用显示答案次数 +export const SINGLE_HELP_COUNT = 999 diff --git a/src/models/Base.ts b/src/models/Base.ts index bb2ac6c..726b6d6 100644 --- a/src/models/Base.ts +++ b/src/models/Base.ts @@ -1,6 +1,6 @@ import { FindOrCreate } from '@typegoose/typegoose/lib/defaultClasses' -import { checkJson, noJson } from '../decorators/nojson' -import { plugin, prop, ReturnModelType } from '@typegoose/typegoose' +import { checkJson } from '../decorators/nojson' +import { plugin, ReturnModelType } from '@typegoose/typegoose' // @ts-ignore import findOrCreate from 'mongoose-findorcreate' @@ -8,7 +8,6 @@ import { Connection } from 'mongoose' import { ObjectId } from 'bson' import { isTrue } from '../utils/string.util' import { AnyParamConstructor } from '@typegoose/typegoose/lib/types' -import { SysMail } from './content/SysMail' const jsonExcludeKeys = ['updatedAt', '__v'] const saveExcludeKeys = ['createdAt', 'updatedAt', '__v', '_id'] diff --git a/src/models/match/PuzzleSession.ts b/src/models/match/PuzzleSession.ts index 9d8693e..b61e79a 100644 --- a/src/models/match/PuzzleSession.ts +++ b/src/models/match/PuzzleSession.ts @@ -197,6 +197,13 @@ export class PuzzleSessionClass extends BaseModule { @prop() public expire: number + /** + * 获取正确答案次数, 只针对单人模式 + * @type {number} + */ + @prop({ default: 0 }) + public helpCount: number + public hasExpired(): boolean { return this.expire < Date.now() }