修改题目获取方式
This commit is contained in:
parent
96ec66d881
commit
a0f5746af8
10
doc/api.md
10
doc/api.md
@ -29,8 +29,9 @@
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| shop | 店铺id |
|
||||
| shop | 店铺id, 比如 607ff59d4a4e16687a3b7079 |
|
||||
| level | 关卡id |
|
||||
| type | 是否降低难度 0: 普通, 1: 降低难度 |
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
@ -47,7 +48,8 @@
|
||||
"刘永福"
|
||||
],
|
||||
"category": "体育-体育", // 类型
|
||||
"type": 1 // 题目类型 1: 普通的文字选择题, 2: 图形
|
||||
"type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形
|
||||
"quality": 1 // 题目难度
|
||||
}]
|
||||
}
|
||||
|
||||
@ -137,6 +139,7 @@
|
||||
| -------- | -------------------------------------- |
|
||||
| count | 需要获取的数量 |
|
||||
| session | 当局的id, 从关卡题目列表中获取 |
|
||||
| quality | 难度 |
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
@ -151,7 +154,8 @@
|
||||
"刘永福"
|
||||
],
|
||||
"category": "体育-体育", // 类型
|
||||
"type": 1 // 题目类型 1: 普通的文字选择题, 2: 图形
|
||||
"type": 1, // 题目类型 1: 普通的文字选择题, 2: 图形
|
||||
"quality": 1 // 题目难度
|
||||
}]
|
||||
|
||||
|
||||
|
@ -18,25 +18,44 @@ import { RoomState } from '../../services/RoomState'
|
||||
import { retry } from '../../utils/promise.util'
|
||||
import { RoomLockErr } from '../../common/RoomLockErr'
|
||||
import { Schedule } from '../../clock/Schedule'
|
||||
import { calcScore, startGame, transformRecord } from '../../services/GameLogic'
|
||||
import {
|
||||
calcScore, calcSingleScore,
|
||||
checkSingleFinish, fetchLevelCfg, fetchSinglePuzzleType,
|
||||
startGame,
|
||||
transformRecord, updateSingleRank
|
||||
} from '../../services/GameLogic'
|
||||
import { ObjectId } from 'bson'
|
||||
import { Shop } from '../../models/shop/Shop'
|
||||
import { isObjectId } from '../../utils/string.util'
|
||||
|
||||
|
||||
class PuzzleController extends BaseController {
|
||||
//TODO:: 增加字段, 表明该次是普通开局还是降低难度开局
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/puzzle/list')
|
||||
async list(req, res) {
|
||||
let { shop, level, accountid } = req.params
|
||||
let { shop, level, accountid, type } = 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)
|
||||
if (!shop || isObjectId(shop)) {
|
||||
throw new ZError(10, '没有店铺id或者店铺id格式不正确, 测试使用: 607ff59d4a4e16687a3b7079')
|
||||
}
|
||||
const cfg = fetchLevelCfg(level)
|
||||
let params = {}
|
||||
let typeArr = await fetchSinglePuzzleType({shopId: shop, levelCfg: cfg})
|
||||
if (typeArr?.length > 0) {
|
||||
params = {$or: [{tag: {$in: typeArr}}, {sub_tag: {$in: typeArr}}]}
|
||||
}
|
||||
let record1 = await Puzzle.randomQuestions(Object.assign(params, {quality: 1}), 5)
|
||||
let record2 = await Puzzle.randomQuestions(Object.assign(params, {quality: 2}), 5)
|
||||
let record3 = await Puzzle.randomQuestions(Object.assign(params, {quality: 3}), 5)
|
||||
const records = (record1.concat(record2)).concat(record3)
|
||||
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
|
||||
history.difficultyMode = type || 0
|
||||
history.qtypes = typeArr
|
||||
await history.save()
|
||||
const results = transformRecord(records)
|
||||
return {
|
||||
@ -100,6 +119,23 @@ class PuzzleController extends BaseController {
|
||||
// if (checkSubFinish(history, id)) {
|
||||
// await sendOneQuestion(history)
|
||||
// }
|
||||
} else if (mode == 0) {
|
||||
let result = checkSingleFinish(history)
|
||||
if (result) {
|
||||
history.status = 9
|
||||
//TODO:: 计算积分, 并更新排行榜
|
||||
let score = calcSingleScore()
|
||||
let rankObj = {
|
||||
shop: history.shop,
|
||||
level: history.level,
|
||||
accountId: accountid,
|
||||
score,
|
||||
mode: 0,
|
||||
session: history.id
|
||||
}
|
||||
await updateSingleRank(rankObj)
|
||||
await history.save()
|
||||
}
|
||||
}
|
||||
return { result, answer: record.a1, stats: history.members }
|
||||
}
|
||||
@ -107,7 +143,7 @@ class PuzzleController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/puzzle/more')
|
||||
async moreLevelQuestions(req, res) {
|
||||
let {session,accountid, count} = req.params
|
||||
let {session,accountid, count, quality} = req.params
|
||||
count = count ? +count : 10
|
||||
if (!session) {
|
||||
throw new ZError(11, 'param mismatch')
|
||||
@ -125,7 +161,13 @@ class PuzzleController extends BaseController {
|
||||
throw new ZError(14, 'not in current match')
|
||||
}
|
||||
let ids = history.questions.map(o => new ObjectId(o))
|
||||
let options = {'_id': {$nin: ids}}
|
||||
let options: any = {'_id': {$nin: ids}}
|
||||
if (quality) {
|
||||
options.quality = quality
|
||||
}
|
||||
if (history.qtypes.length > 0) {
|
||||
Object.assign(options, {$or: [{tag: {$in: history.qtypes}}, {sub_tag: {$in: history.qtypes}}]})
|
||||
}
|
||||
let records = await Puzzle.randomQuestions(options, count)
|
||||
const results = transformRecord(records)
|
||||
history.questions = history.questions.concat(records.map(o => o._id))
|
||||
|
@ -7,7 +7,7 @@ export class mission_vo implements Cfg{
|
||||
public number: number;
|
||||
public commonlyadd: number;
|
||||
public hardadd: number;
|
||||
public hp: number;
|
||||
public lastdif: number;
|
||||
public hp: number;
|
||||
public hpstar: number;
|
||||
public time: number;
|
||||
@ -22,7 +22,7 @@ export class mission_vo implements Cfg{
|
||||
this.number = data.number;
|
||||
this.commonlyadd = data.commonlyadd;
|
||||
this.hardadd = data.hardadd;
|
||||
this.hp = data.hp;
|
||||
this.lastdif = data.lastdif;
|
||||
this.hp = data.hp;
|
||||
this.hpstar = data.hpstar;
|
||||
this.time = data.time;
|
||||
@ -32,7 +32,7 @@ export class mission_vo implements Cfg{
|
||||
this.beforehand_enemy = data.beforehand_enemy;
|
||||
this.keyID = data.keyID;
|
||||
};
|
||||
|
||||
|
||||
public isOK (uniqueID: number, param1: any, param2: any): boolean {
|
||||
if((param1 == undefined || param1 == null) && (param2 == undefined || param2 == null)){
|
||||
return this.id == uniqueID;
|
||||
@ -42,4 +42,4 @@ export class mission_vo implements Cfg{
|
||||
}
|
||||
return this.id == uniqueID && this.id == param1 && this.id == param2;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -99,7 +99,7 @@ class PuzzleClass extends BaseModule {
|
||||
}
|
||||
public static async randomQuestions(this: ReturnModelType<typeof PuzzleClass>, options: any, count: number) {
|
||||
let filters = {status: 1, is_hide: 0, deleted: 0, dp: 1}
|
||||
Object.assign(options)
|
||||
Object.assign(filters, options)
|
||||
return Puzzle.aggregate([
|
||||
{ $match: filters },
|
||||
{ $sample: { size: count } }
|
||||
|
39
src/models/match/PuzzleRank.ts
Normal file
39
src/models/match/PuzzleRank.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { BaseModule } from '../Base'
|
||||
import { dbconn } from '../../decorators/dbconn'
|
||||
import {
|
||||
getModelForClass,
|
||||
index,
|
||||
modelOptions,
|
||||
prop
|
||||
} from '@typegoose/typegoose'
|
||||
|
||||
/**
|
||||
* 排名数据
|
||||
*/
|
||||
@dbconn()
|
||||
@index({ shop: 1, level: 1, accountId: 1, mode: 1}, { unique: true })
|
||||
@modelOptions({ schemaOptions: { collection: 'puzzle_rank', timestamps: true } })
|
||||
export class PuzzleRankClass extends BaseModule {
|
||||
@prop()
|
||||
public shop: string
|
||||
|
||||
@prop()
|
||||
public level: number
|
||||
|
||||
@prop()
|
||||
public accountId: string
|
||||
|
||||
@prop()
|
||||
public score: number
|
||||
|
||||
@prop()
|
||||
public session: string
|
||||
|
||||
@prop()
|
||||
public mode: number
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export const PuzzleRank = getModelForClass(PuzzleRankClass, { existingConnection: PuzzleRankClass.db })
|
@ -73,6 +73,15 @@ export class PuzzleSessionClass extends BaseModule {
|
||||
@prop({default: 0})
|
||||
public type: number
|
||||
|
||||
/**
|
||||
* 模式
|
||||
* 0: 普通
|
||||
* 1: 减低难度
|
||||
* @type {number}
|
||||
*/
|
||||
@prop({default: 0})
|
||||
public difficultyMode: number
|
||||
|
||||
/**
|
||||
* 当前的问题
|
||||
* @type {number}
|
||||
@ -95,6 +104,13 @@ export class PuzzleSessionClass extends BaseModule {
|
||||
*/
|
||||
@prop({default: 0})
|
||||
public status: number
|
||||
|
||||
/**
|
||||
* 已选择的题库分类
|
||||
* @type {string[]}
|
||||
*/
|
||||
@prop()
|
||||
public qtypes: string[]
|
||||
/**
|
||||
* 开始时间
|
||||
* 对于多人比赛来说, 需要一个自动开始时间
|
||||
|
@ -11,6 +11,10 @@ import { BaseConst } from '../constants/BaseConst'
|
||||
import { QCategoryCache } from './QCategoryCache'
|
||||
import { PuzzleSession } from '../models/match/PuzzleSession'
|
||||
import { GameEnv } from '../config/GameEnv'
|
||||
import { PuzzleRank } from '../models/match/PuzzleRank'
|
||||
import { Shop } from '../models/shop/Shop'
|
||||
import { mission_vo } from '../config/parsers/mission_vo'
|
||||
import { ShopActivity } from '../models/shop/ShopActivity'
|
||||
|
||||
|
||||
export function transformRecord(records: any[]) {
|
||||
@ -112,3 +116,100 @@ export function calcScore(timeKey: string, combo: number) {
|
||||
const cfg = new GameEnv()
|
||||
return cfg.pvpBaseScore + time / 100 * cfg.pvpTimeRate + combo * cfg.pvpComboRate
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新排行榜
|
||||
* @param {string} shop 店铺id
|
||||
* @param {number} level 关卡id
|
||||
* @param {string} accountId 帐号id
|
||||
* @param {number} score 分数
|
||||
* @param {string} session
|
||||
* @param {number} mode 模式: 0: 单人 1: pvp
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export async function updateSingleRank({shop, level, accountId, score, session, mode }
|
||||
: {shop: string,
|
||||
level: number,
|
||||
accountId: string,
|
||||
score: number,
|
||||
mode: number
|
||||
session: string}) {
|
||||
|
||||
let record = (await PuzzleRank.findOrCreate({shop, level, accountId, mode})).doc
|
||||
if (record.score < score) {
|
||||
record.score = score
|
||||
record.session = session
|
||||
await record.save()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO::
|
||||
* 单人模式检查游戏是否结束
|
||||
*/
|
||||
export function checkSingleFinish(history: any) {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO::
|
||||
* 计算单人模式的得分
|
||||
* @return {number}
|
||||
*/
|
||||
export function calcSingleScore() {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定pvp模式题目类型
|
||||
* @param {string} shopId
|
||||
* @param {string} aid 活动配置
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export async function fetchPvpPuzzleType({shopId, aid} : {shopId: string, aid?: string}) {
|
||||
|
||||
//{$or:[{tag: {$in: ['a', 'SS']}}, {sub_tag: {$in: ['a', 'SS']}}]}
|
||||
let typeArr: string[] = []
|
||||
if (aid) {
|
||||
let actData = await ShopActivity.findById(aid)
|
||||
if (actData?.qtypes?.length > 0) {
|
||||
typeArr = actData.qtypes
|
||||
}
|
||||
}
|
||||
if (typeArr.length === 0 ) {
|
||||
let shop = await Shop.findById(shopId)
|
||||
if (shop?.qtypes?.length > 0) {
|
||||
typeArr = shop.qtypes
|
||||
}
|
||||
}
|
||||
// let params = {$or: [{tag: {$in: typeArr}}, {sub_tag: {$in: typeArr}}]}
|
||||
return typeArr
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单人模式题目类型
|
||||
* @param {string} shopId
|
||||
* @param {mission_vo} levelCfg
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export async function fetchSinglePuzzleType({shopId, levelCfg} : {shopId: string, levelCfg?: mission_vo}) {
|
||||
let typeArr: string[] = []
|
||||
let shop = await Shop.findById(shopId)
|
||||
if (shop?.qtypes?.length > 0) {
|
||||
typeArr = shop.qtypes
|
||||
}
|
||||
if (typeArr.length === 0 && levelCfg?.keyID) {
|
||||
typeArr = levelCfg.keyID.split(':')
|
||||
}
|
||||
return typeArr
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关卡配置信息
|
||||
* @param {number} level
|
||||
*/
|
||||
export function fetchLevelCfg(level: number) {
|
||||
const cfgs: mission_vo[] = Array.from(global.$cfg.get(BaseConst.MISSION).values())
|
||||
return cfgs.find(o => o.number == level) || cfgs[cfgs.length - 1]
|
||||
}
|
||||
|
@ -48,3 +48,13 @@ export function isTrue(obj) {
|
||||
return obj === 'true' || obj === 'TRUE' || obj === 'True' || obj === 'on' || obj ==='ON' || obj === true || obj === 1
|
||||
|| obj === '1' || obj === 'YES' || obj === 'yes';
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证ObjectId格式是否正确
|
||||
* @param {string} id
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isObjectId(id: string): boolean {
|
||||
//mongoose.Types.ObjectId.isValid(id)
|
||||
return /^[a-fA-F0-9]{24}$/.test(id)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user