修改题目获取方式

This commit is contained in:
zhl 2021-05-11 11:09:43 +08:00
parent 96ec66d881
commit a0f5746af8
8 changed files with 228 additions and 16 deletions

View File

@ -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 // 题目难度
}]

View File

@ -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))

View File

@ -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;
};
};
};

View File

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

View 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 })

View File

@ -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[]
/**
*
* ,

View File

@ -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]
}

View File

@ -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)
}