diff --git a/doc/api.md b/doc/api.md index dde63e4..1454797 100644 --- a/doc/api.md +++ b/doc/api.md @@ -48,7 +48,7 @@ "刘永福" ], "category": "体育-体育", // 类型 - "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形 + "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形, 3: 问卷式题目 "quality": 1 // 题目难度 }] } @@ -85,10 +85,10 @@ gameResult: 0, // 当前局游戏结果 0: 未完成, -1: 失败, 1: 胜利 "stats": { // 当局的状态 "1111": { - "answer": [ // 每一题的结果 - 1, - 0 - ], + "answer": {// 每一题的结果, key为题目的id, 值为answer在答案中的index值, 0为正确值, -1为超时, 其他都为错误 + "608a3d15e678843dd443fa53": 0, + }, + "total": 2, // 总答题数量 "rightCount": 1, // 答对的数量 "errorCount": 1, // 答错的数量 "comboCount": 0, // 当前连续答对的数量 @@ -162,7 +162,7 @@ "刘永福" ], "category": "体育-体育", // 类型 - "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形 + "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形, 3: 问卷式题目 "quality": 1 // 题目难度 }] ``` @@ -238,7 +238,7 @@ "刘永福" ], "category": "体育-体育", // 类型 - "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形 + "type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形, 3: 问卷式题目 "quality": 1 // 题目难度 }] } @@ -273,10 +273,10 @@ overtime: 0, // 当前回答是否超时 0: 未超时, 1: 超时 "stats": { // 当局的状态 "1111": { - "answer": [ // 每一题的结果 - 1, - 0 - ], + "answer": {// 每一题的结果, key为题目的id, 值为answer在答案中的index值, 0为正确值, -1为超时, 其他都为错误 + "608a3d15e678843dd443fa53": 0, + }, + "total": 2, // 总答题数量 "rightCount": 1, // 答对的数量 "errorCount": 1, // 答错的数量 "comboCount": 0, // 当前连续答对的数量 diff --git a/src/api/controllers/exam.controller.ts b/src/api/controllers/exam.controller.ts index 111ca6e..85e43e4 100644 --- a/src/api/controllers/exam.controller.ts +++ b/src/api/controllers/exam.controller.ts @@ -53,7 +53,7 @@ class ExamController extends BaseController { } else { results = record.transQuestion() for (let _r of record.questions) { - history.questions.set(_r._id + '', _r.a1) + history.questions.set(_r._id + '', _r.compactRecord(true)) } } let stat = new PuzzleStatusClass() @@ -101,18 +101,19 @@ class ExamController extends BaseController { } let time = (history.timeone* 1000 - (Date.now() - statMap.timeLast)) / 1000 let record = history.questions.get(id) - let result = record === answer ? 1 : 0 + let result = record.answers.indexOf(answer) let overtime = 0 if (type == 1) { // type = 1 为客户端上报的超时消息, 直接判负 - result = 0 + result = -1 overtime = 1 } else if (time < 0){ - result = 0 + result = -1 overtime = 1 } statMap.timeLast = Date.now() statMap.answer.set(id, result) - if (result == 1) { + statMap.total ++ + if (result == 0) { statMap.rightCount++ statMap.comboCount++ statMap.maxCombo = Math.max(statMap.maxCombo, statMap.comboCount) @@ -128,7 +129,7 @@ class ExamController extends BaseController { history.markModified('members') await history.save() let gameResult = 0 - let rspData: any = { result, answer: record, stats: history.members, overtime } + let rspData: any = { result: result === 0, answer: record.answers[0], stats: history.members, overtime } if (statMap.answer.size >= history.questions.size) { gameResult = 1 } diff --git a/src/api/controllers/puzzle.controller.ts b/src/api/controllers/puzzle.controller.ts index 732a450..6594674 100644 --- a/src/api/controllers/puzzle.controller.ts +++ b/src/api/controllers/puzzle.controller.ts @@ -30,7 +30,6 @@ import { import { Shop, validShopId } from '../../models/shop/Shop' import { ShopActivity } from '../../models/shop/ShopActivity' import { GameUser } from '../../models/GameUser' -import { BaseConst } from '../../constants/BaseConst' class PuzzleController extends BaseController { @@ -71,7 +70,7 @@ class PuzzleController extends BaseController { let history = new PuzzleSession({ shop: shopId, level }) history.members.set(accountid, new PuzzleStatusClass()) for (let record of records) { - history.questions.set(record.id, record.a1) + history.questions.set(record.id, record.compactRecord(true)) } history.expire = Date.now() + (cfg.time || 90) * 1000 history.type = 0 @@ -104,12 +103,12 @@ class PuzzleController extends BaseController { throw new ZError(16, 'current question not in current match') } let record = history.questions.get(id) - let result = record === answer ? 1 : 0 + let result = record.answers.indexOf(answer) if (type == 1) { // type = 1 为客户端上报的超时消息, 直接判负 - result = 0 + result = -1 } if (history.status == 9 || history.hasExpired()) { - result = 0 + result = -1 } let statMap = history.members.get(accountid) if (statMap.answer.has(id)) { @@ -117,7 +116,8 @@ class PuzzleController extends BaseController { } statMap.timeLast = Date.now() statMap.answer.set(id, result) - if (result == 1) { + statMap.total ++ + if (result == 0) { statMap.rightCount++ statMap.comboCount++ statMap.maxCombo = Math.max(statMap.maxCombo, statMap.comboCount) @@ -129,7 +129,7 @@ class PuzzleController extends BaseController { history.markModified('members') let gameResult = 0 await history.save() - let rspData: any = { result, answer: record, stats: history.members } + let rspData: any = { result: result === 0, answer: record.answers[0], stats: history.members } if (mode == 1) { let score = result ? calcPvpScore(history.scheduleKey, statMap.comboCount) : 0 await broadcast(history.room, 'answer', {accountid, result, score}) @@ -204,7 +204,7 @@ class PuzzleController extends BaseController { let records = await Puzzle.randomQuestions(options, count) const results = transformRecord(records) for (let record of records) { - history.questions.set(record.id, record.a1) + history.questions.set(record.id, record.compactRecord(true)) } history.markModified('questions') await history.save() diff --git a/src/models/content/Puzzle.ts b/src/models/content/Puzzle.ts index 03b1d15..7d6f7d7 100644 --- a/src/models/content/Puzzle.ts +++ b/src/models/content/Puzzle.ts @@ -7,10 +7,17 @@ import { } from '@typegoose/typegoose' import { BaseModule } from '../Base' import { noJson } from '../../decorators/nojson' +import { QCategoryCache } from '../../services/QCategoryCache' +import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses' +import { CompactPuzzleClass } from '../match/PuzzleSession' + +// @ts-ignore +export interface PuzzleClass extends Base, TimeStamps { +} @dbconn('second') @modelOptions({ schemaOptions: { collection: 'question' } }) -class PuzzleClass extends BaseModule { +export class PuzzleClass extends BaseModule { @prop() public question: string @prop() @@ -110,9 +117,31 @@ class PuzzleClass extends BaseModule { { $match: filters }, { $sample: { size: count } } ]).exec() - } + public compactRecord(withAnswer: boolean) { + let answers = [] + for (let i = 1; i <= 4; i++) { + if (this[`a${ i }`]) { + answers.push(this[`a${ i }`]) + } + } + let type = new QCategoryCache().getType(this.tag) + let subType = new QCategoryCache().getType(this.sub_tag) + let result = new CompactPuzzleClass() + result.id = this._id+'' + result.title = this.question + + result.type = 1 + result.category = type + '-' + subType + result.quality = this.quality + if (!withAnswer) { + answers.randomSort() + } + result.source = 0 + result.answers = answers + return result + } } export const Puzzle = getModelForClass(PuzzleClass, { existingConnection: PuzzleClass.db }) diff --git a/src/models/match/PuzzleSession.ts b/src/models/match/PuzzleSession.ts index 70606cd..73b8368 100644 --- a/src/models/match/PuzzleSession.ts +++ b/src/models/match/PuzzleSession.ts @@ -4,6 +4,42 @@ import { BaseModule } from '../Base' import { Severity } from '@typegoose/typegoose/lib/internal/constants' import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses' +export class CompactPuzzleClass { + @prop() + id: string + @prop() + title: string + @prop({ type: () => [String] }) + public answers: string[] + //1: 普通的文字选择题, 2: 图形, 3: 问卷式题目 + @prop() + public type: number + @prop() + public category: string + @prop() + public quality: number + /** + * 题目来源 + * 0: 系统题库 + * 1: 自定义 + * @type {number} + */ + @prop() + public source: number + + public toJson() { + let answers = this.answers.slice(0) + answers.randomSort() + return { + id: this.id, + title: this.title, + answers: answers, + type: this.type, + category: this.category, + quality: this.quality + } + } +} @modelOptions({ options: {allowMixed: Severity.ALLOW} @@ -13,6 +49,8 @@ export class PuzzleStatusClass { @prop({ type: Number, default: new Map() }) answer: Map + @prop({default: 0}) + total: number /** * 打对数量 * @type {number} @@ -81,8 +119,8 @@ export class PuzzleSessionClass extends BaseModule { @prop({ _id: false, type: PuzzleStatusClass, default: new Map() }) public members: Map - @prop({ _id: false, type: String, default: new Map() }) - public questions: Map + @prop({ _id: false, type: CompactPuzzleClass, default: new Map() }) + public questions: Map @prop() public shop: string diff --git a/src/models/shop/ShopExam.ts b/src/models/shop/ShopExam.ts index d56660f..51473e4 100644 --- a/src/models/shop/ShopExam.ts +++ b/src/models/shop/ShopExam.ts @@ -8,6 +8,7 @@ import { BaseModule } from '../Base' import { noJson } from '../../decorators/nojson' import { Severity } from '@typegoose/typegoose/lib/internal/constants' import { Base } from '@typegoose/typegoose/lib/defaultClasses' +import { CompactPuzzleClass } from '../match/PuzzleSession' export class ShopPuzzleClass extends Base{ @prop() @@ -20,6 +21,33 @@ export class ShopPuzzleClass extends Base{ public a3: string @prop() public a4: string + /** + * 题目类型: 1: 正常单选题, 2: 图片, 3: 问卷式题目 + * @type {number} + */ + @prop() + public type: number + + public compactRecord(withAnswer: boolean) { + let answers = [] + for (let i = 1; i <= 4; i++) { + if (this[`a${ i }`]) { + answers.push(this[`a${ i }`]) + } + } + let result = new CompactPuzzleClass() + result.id = this._id+'' + result.title = this.question + result.type = 1 + result.category = '自定义' + result.quality = 1 + if (!withAnswer) { + answers.randomSort() + } + result.source = 1 + result.answers = answers + return result + } } export class ExamRewardClass extends Base{ @@ -168,21 +196,7 @@ export class ShopExamClass extends BaseModule { public transQuestion() { return this.questions.map(o => { - let answers = [] - for (let i = 1; i <= 4; i++) { - if (o[`a${ i }`]) { - answers.push(o[`a${ i }`]) - } - } - answers.randomSort() - return { - id: o._id, - title: o.question, - answers, - type: 1, - category: '自定义', - quality: 1 - } + return o.compactRecord(false) }) } public getReward(score: number) { diff --git a/src/models/shop/ShopGameExt.ts b/src/models/shop/ShopGameExt.ts index 184fe0d..b30b98c 100644 --- a/src/models/shop/ShopGameExt.ts +++ b/src/models/shop/ShopGameExt.ts @@ -26,35 +26,15 @@ export class ShopGameExtClass extends BaseModule { @prop() public version: string - + /** + * bg_item_icon: 背景图案 + * game_main_pic: 主页正中间图片 + * game_single_btn: 主页上单人赛按钮文字 + * game_multi_btn: 主页上多人赛按钮名字 + */ @prop({type: mongoose.Schema.Types.Mixed}) public cfg: {} - // /** - // * 背景图案 - // * @type {string} - // */ - // @prop() - // public bg_item_icon: string - // /** - // * 主页正中间图片 - // * @type {string} - // */ - // @prop() - // public game_main_pic: string - // /** - // * 主页上单人赛按钮文字 - // * @type {string} - // */ - // @prop() - // public game_single_btn: string - // - // /** - // * 主页上多人赛按钮名字 - // * @type {string} - // */ - // @prop() - // public game_multi_btn: string } export const ShopGameExt = getModelForClass(ShopGameExtClass, { existingConnection: ShopGameExtClass.db }) diff --git a/src/services/GameLogic.ts b/src/services/GameLogic.ts index be841f8..a9241f8 100644 --- a/src/services/GameLogic.ts +++ b/src/services/GameLogic.ts @@ -1,6 +1,7 @@ import { beginGame, - endGame, sendMsg, + endGame, + sendMsg, sendQuestion, updateRound, updateScore @@ -8,7 +9,6 @@ import { import { Puzzle } from '../models/content/Puzzle' import { Schedule } from '../clock/Schedule' import { BaseConst } from '../constants/BaseConst' -import { QCategoryCache } from './QCategoryCache' import { PuzzleSession } from '../models/match/PuzzleSession' import { GameEnv } from '../config/GameEnv' import { Shop } from '../models/shop/Shop' @@ -22,23 +22,7 @@ import { GameUser } from '../models/GameUser' export function transformRecord(records: any[]) { return records.map(o => { - let answers = [] - for (let i = 1; i <= 4; i++) { - if (o[`a${ i }`]) { - answers.push(o[`a${ i }`]) - } - } - answers.randomSort() - let type = new QCategoryCache().getType(o.tag) - let subType = new QCategoryCache().getType(o.sub_tag) - return { - id: o._id, - title: o.question, - answers, - type: 1, - category: type + '-' + subType, - quality: o.quality - } + return o.compactRecord(false) }) } @@ -98,8 +82,7 @@ export async function sendOneQuestion(history: any) { } const questions:string[] = Array.from(history.questions.keys()) let qid: string = questions[history.current] - let record = await Puzzle.findById(qid) - let qdata: any = transformRecord([record])[0] + let qdata = history.questions.get(qid).toJson() qdata.no = history.current await updateRound(roomId, history.current) await sendQuestion(roomId, qdata) @@ -110,7 +93,7 @@ export async function sendOneQuestion(history: any) { let datas = [] for (let [accountid, data] of subHistory.members) { if (!data.answer.has(qid)) { - data.answer.set(qid, 0) + data.answer.set(qid, -1) data.errorCount++ data.comboCount = 0 datas.push({ accountid, score: 0 })