corgi/src/models/match/PuzzleSession.ts

261 lines
5.4 KiB
TypeScript

import { dbconn } from '../../decorators/dbconn'
import { getModelForClass, modelOptions, prop } from '@typegoose/typegoose'
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 },
})
export class PuzzleStatusClass {
@prop({ type: Number, default: new Map() })
answer: Map<string, number>
@prop({ default: 0 })
total: number
/**
* 打对数量
* @type {number}
*/
@prop({ default: 0 })
rightCount: number
/**
* 答错数量
* @type {number}
*/
@prop({ default: 0 })
errorCount: number
/**
* 当前连击数
* @type {number}
*/
@prop({ default: 0 })
comboCount: number
/**
* 最大连击数
* @type {number}
*/
@prop({ default: 0 })
maxCombo: number
/**
* 多人模式中, 该玩家在房间中的sessionId, 用于重连
* @type {string}
*/
@prop()
sessionId: string
/**
* 游戏胜利后的得分
* @type {number}
*/
@prop({ default: 0 })
score: number
@prop({ default: 0 })
star: number
@prop()
timeLeft: number
/**
* 最后一次答题时间
* @type {number}
*/
@prop()
timeLast: number
/**
* 游戏结果
* @type {number}
*/
@prop({ default: 0 })
public gameResult: number
}
// @ts-ignore
export interface PuzzleSessionClass extends Base, TimeStamps {}
@dbconn()
@modelOptions({ schemaOptions: { collection: 'puzzle_session', timestamps: true } })
export class PuzzleSessionClass extends BaseModule {
@prop({ _id: false, type: PuzzleStatusClass, default: new Map() })
public members: Map<string, PuzzleStatusClass>
@prop({ _id: false, type: CompactPuzzleClass, default: new Map() })
public questions: Map<string, CompactPuzzleClass>
@prop()
public shop: string
@prop()
public level: number
/**
* 活动或者挑战, 可将相关的id存入该字段
* @type {string}
*/
@prop()
public activityId: string
@prop()
public room: string
/**
* 类型
* 0: 单人
* 1: 多人
* 2: 测验
* @type {number}
*/
@prop({ default: 0 })
public type: number
/**
* 模式
* 0: 普通
* 1: 减低难度
* @type {number}
*/
@prop({ default: 0 })
public difficultyMode: number
/**
* 当前的问题
* @type {number}
*/
@prop({ default: 0 })
public current: number
/**
* 一共多少问题
* @type {number}
*/
@prop()
public total: number
/**
* 每一题回答时间
* @type {number}
*/
@prop()
public timeone: number
/**
* 比赛状态
* 0: 未开始答题
* 1: 答题进行中
* 9: 结束
* @type {number}
*/
@prop({ default: 0 })
public status: number
/**
* 已选择的题库分类
* @type {string[]}
*/
@prop({ type: () => [String] })
public qtypes: string[]
/**
* 开始时间
* 对于多人比赛来说, 需要一个自动开始时间
* @type {number}
*/
@prop()
public begin: number
@prop()
public expire: number
/**
* 获取正确答案次数, 只针对单人模式
* @type {number}
*/
@prop({ default: 0 })
public helpCount: number
public hasExpired(): boolean {
return this.expire < Date.now()
}
public get scheduleKey() {
// @ts-ignore
return this.room + this._id
}
public static parseQueryParam(params) {
let { exam, timeBegin, timeEnd, shop } = params
let opt: any = { type: 2 }
if (shop) {
opt.shop = shop
}
if (exam) {
opt.activityId = exam
}
if (timeBegin && !timeEnd) {
opt.createdAt = { $gte: new Date(timeBegin) }
} else if (timeBegin && timeEnd) {
opt['$and'] = [{ createdAt: { $gte: new Date(timeBegin) } }, { createdAt: { $lte: new Date(timeEnd) } }]
} else if (!timeBegin && timeEnd) {
opt.createdAt = { $lte: new Date(timeEnd) }
}
let sort = { _id: 1 }
return { opt, sort }
}
public toPartnerJson() {
const exportKeys = ['_id', 'status', 'createdAt', 'type', 'activityId']
let result: any = {}
for (let key of exportKeys) {
result[key] = this[key]
}
result.qcount = this.questions.size
let questions: any = []
const accountId = this.members.keys().next().value
const udata = this.members.get(accountId)
result.accountId = accountId
for (let [key, data] of this.questions) {
let obj = {
title: data.title,
answers: data.answers,
answer: udata.answer.has(key) ? udata.answer.get(key) : -1,
}
questions.push(obj)
}
result.questions = questions
return result
}
}
export const PuzzleSession = getModelForClass(PuzzleSessionClass, { existingConnection: PuzzleSessionClass.db })