增加题目发送,和积分更新机制
This commit is contained in:
parent
9f795bf415
commit
6d0f821f04
@ -8,30 +8,23 @@ import {
|
||||
import { ZError } from '../../common/ZError'
|
||||
import { BaseConst } from '../../constants/BaseConst'
|
||||
import { mission_vo } from '../../config/parsers/mission_vo'
|
||||
import { beginGame, createRoom } from '../../services/WsSvr'
|
||||
import {
|
||||
beginGame,
|
||||
broadcast,
|
||||
createRoom,
|
||||
sendQuestion, updateScore
|
||||
} from '../../services/WsSvr'
|
||||
import { RoomState } from '../../services/RoomState'
|
||||
import { retry } from '../../utils/promise.util'
|
||||
import { RoomLockErr } from '../../common/RoomLockErr'
|
||||
import { Schedule } from '../../clock/Schedule'
|
||||
import { createDeflateRaw } from 'zlib'
|
||||
import {
|
||||
checkSubFinish, sendOneQuestion,
|
||||
startGame,
|
||||
transformRecord
|
||||
} from '../../services/GameLogic'
|
||||
|
||||
|
||||
const transformRecord = function (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()
|
||||
return {
|
||||
id: o._id,
|
||||
title: o.question,
|
||||
answers,
|
||||
type: 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class PuzzleController extends BaseController {
|
||||
@role('anon')
|
||||
@ -59,7 +52,8 @@ class PuzzleController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/puzzle/answer')
|
||||
async report(req, res) {
|
||||
let { id, answer, type, session, accountid } = req.params
|
||||
let { id, answer, type, session, accountid, mode } = req.params
|
||||
mode = mode || 0
|
||||
if (!id || !session) {
|
||||
throw new ZError(11, 'param mismatch')
|
||||
}
|
||||
@ -79,7 +73,7 @@ class PuzzleController extends BaseController {
|
||||
throw new ZError(16, 'current question not in current match')
|
||||
}
|
||||
let statMap = history.members.get(accountid)
|
||||
if (statMap.questions.find(o => o == id)) {
|
||||
if (statMap.answer.has(id)) {
|
||||
throw new ZError(15, 'current question already answered')
|
||||
}
|
||||
let record = await Puzzle.findById(id)
|
||||
@ -90,8 +84,7 @@ class PuzzleController extends BaseController {
|
||||
if (type == 1) {
|
||||
result = 0
|
||||
}
|
||||
statMap.answer.push(result)
|
||||
statMap.questions.push(id)
|
||||
statMap.answer.set(id, result)
|
||||
if (result == 1) {
|
||||
statMap.rightCount++
|
||||
statMap.comboCount++
|
||||
@ -103,6 +96,13 @@ class PuzzleController extends BaseController {
|
||||
history.status = 1
|
||||
history.markModified('members')
|
||||
await history.save()
|
||||
if (mode == 1) {
|
||||
let score = result ? 3 : -1
|
||||
await updateScore(history.room, [{accountid, score }])
|
||||
if (checkSubFinish(history, id)) {
|
||||
await sendOneQuestion(history)
|
||||
}
|
||||
}
|
||||
return { result, answer: record.a1, stats: history.members }
|
||||
}
|
||||
|
||||
@ -132,6 +132,8 @@ class PuzzleController extends BaseController {
|
||||
if (history && !history.hasExpired()) {
|
||||
new RoomState().unlock(shop)
|
||||
beginTime = history.begin
|
||||
history.members.set(accountid, new PuzzleStatusClass())
|
||||
await history.save()
|
||||
return roomId = history.room
|
||||
} else {
|
||||
let rsp = await createRoom(data)
|
||||
@ -145,15 +147,14 @@ class PuzzleController extends BaseController {
|
||||
history.room = roomId
|
||||
//TODO: 根据配置赋值
|
||||
const beginSecond = 20 * 1000
|
||||
history.total = 10
|
||||
history.begin = Date.now() + beginSecond
|
||||
beginTime = history.begin
|
||||
history.expire = history.begin + (100 || 90) * 1000
|
||||
history.type = 1
|
||||
await history.save()
|
||||
new Schedule().beginSchedule(beginSecond, async function () {
|
||||
await beginGame(roomId, {})
|
||||
history.status = 1
|
||||
await history.save()
|
||||
await startGame(roomId, history)
|
||||
}, shop)
|
||||
new RoomState().unlock(shop)
|
||||
return roomId
|
||||
|
@ -1,4 +1,5 @@
|
||||
import BaseController from '../../common/base.controller'
|
||||
import { role, router } from '../../decorators/router'
|
||||
|
||||
class ServerController extends BaseController {
|
||||
|
||||
|
@ -2,4 +2,6 @@ export class BaseConst{
|
||||
public static readonly COMPOUND = 'compound'
|
||||
public static readonly MISSION = 'mission'
|
||||
public static readonly RANK_SCORE = 'rank_score'
|
||||
// 多人答题时间
|
||||
public static readonly MATCH_ANSWER_TIME = 10000
|
||||
}
|
||||
|
@ -10,11 +10,9 @@ import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
|
||||
})
|
||||
export class PuzzleStatusClass {
|
||||
|
||||
@prop({default: []})
|
||||
answer: number[]
|
||||
@prop({ type: Number, default: new Map() })
|
||||
answer: Map<string, number>
|
||||
|
||||
@prop({ type: () => [String], default: [] })
|
||||
questions: string[]
|
||||
/**
|
||||
* 打对数量
|
||||
* @type {number}
|
||||
@ -71,6 +69,19 @@ export class PuzzleSessionClass extends BaseModule {
|
||||
@prop({default: 0})
|
||||
public type: number
|
||||
|
||||
/**
|
||||
* 当前的问题
|
||||
* @type {number}
|
||||
*/
|
||||
@prop({default: 0})
|
||||
public current: number
|
||||
/**
|
||||
* 一共多少问题
|
||||
* @type {number}
|
||||
*/
|
||||
@prop()
|
||||
public total: number
|
||||
|
||||
/**
|
||||
* 比赛状态
|
||||
* 0: 未开始答题
|
||||
@ -93,6 +104,10 @@ export class PuzzleSessionClass extends BaseModule {
|
||||
public hasExpired(): boolean {
|
||||
return this.expire < Date.now()
|
||||
}
|
||||
|
||||
public get scheduleKey() {
|
||||
return this.room + this._id
|
||||
}
|
||||
}
|
||||
|
||||
export const PuzzleSession = getModelForClass(PuzzleSessionClass, { existingConnection: PuzzleSessionClass.db })
|
||||
|
74
src/services/GameLogic.ts
Normal file
74
src/services/GameLogic.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { beginGame, endGame, sendQuestion, updateScore } from './WsSvr'
|
||||
import { Puzzle } from '../models/content/Puzzle'
|
||||
import { Schedule } from '../clock/Schedule'
|
||||
import { BaseConst } from '../constants/BaseConst'
|
||||
|
||||
|
||||
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()
|
||||
return {
|
||||
id: o._id,
|
||||
title: o.question,
|
||||
answers,
|
||||
type: 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function checkSubFinish(history: any, qid: string) {
|
||||
let count = 0
|
||||
for (let [key, val] of history.members) {
|
||||
if (val.has(qid)) {
|
||||
count ++
|
||||
}
|
||||
}
|
||||
return count >= history.questions.length;
|
||||
}
|
||||
/**
|
||||
* 开始游戏
|
||||
* @param {string} roomId
|
||||
* @param history
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export async function startGame(roomId: string, history: any) {
|
||||
await beginGame(roomId, {})
|
||||
let records = await Puzzle.randomQuestions({}, history.total)
|
||||
history.questions = records.map(o => o._id)
|
||||
await history.save()
|
||||
await sendOneQuestion(history)
|
||||
}
|
||||
|
||||
export async function sendOneQuestion(history: any) {
|
||||
const roomId = history.room
|
||||
new Schedule().stopSchedule(history.scheduleKey)
|
||||
if (history.current >= history.questions.length) {
|
||||
console.log('match over')
|
||||
await endGame(roomId, {})
|
||||
return
|
||||
}
|
||||
|
||||
let qid = history.questions[history.current]
|
||||
let record = await Puzzle.findById(qid)
|
||||
let qdata: any = transformRecord([record])[0]
|
||||
qdata.no = history.current
|
||||
await sendQuestion(roomId, qdata)
|
||||
history.current ++
|
||||
await history.save()
|
||||
new Schedule().beginSchedule(BaseConst.MATCH_ANSWER_TIME, async function (){
|
||||
let datas = []
|
||||
for (let [accountid, data] of history.members) {
|
||||
if (!data.answer.has(qid)) {
|
||||
datas.push({accountid, score: -1})
|
||||
}
|
||||
}
|
||||
await updateScore(history.room, datas)
|
||||
await sendOneQuestion(history)
|
||||
}, history.scheduleKey)
|
||||
}
|
@ -85,8 +85,53 @@ export async function beginGame(roomId, params) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function endGame(roomId, params) {
|
||||
console.log(`end game: ${roomId}, ${params}`)
|
||||
const url = `${apiBase}/room/call`
|
||||
const args = [params]
|
||||
const data = {
|
||||
roomId,
|
||||
method: 'endGame',
|
||||
args: JSON.stringify(args)
|
||||
}
|
||||
return axios.post(url, data)
|
||||
.then(res => {
|
||||
return res.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建房间
|
||||
* @param data
|
||||
* @return {Promise<AxiosResponse<any>>}
|
||||
*/
|
||||
export async function createRoom(data) {
|
||||
const url = `${apiBase}/matchmake/joinOrCreate/puzzle_room`
|
||||
return axios.post(url, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一条问题
|
||||
* @param {string} roomId
|
||||
* @param data
|
||||
* @return {Promise<AxiosResponse<any>>}
|
||||
*/
|
||||
export async function sendQuestion(roomId: string, data: any) {
|
||||
console.log(`sendOneQuestion to ${roomId}, ${JSON.stringify(data)}`)
|
||||
return broadcast(roomId, 'question', data)
|
||||
}
|
||||
|
||||
export async function updateScore(roomId: string, data: any) {
|
||||
console.log(`updateScore: ${roomId}, ${JSON.stringify(data)}`)
|
||||
const url = `${apiBase}/room/call`
|
||||
const args = [data]
|
||||
const params = {
|
||||
roomId,
|
||||
method: 'updateScore',
|
||||
args: JSON.stringify(args)
|
||||
}
|
||||
return axios.post(url, params)
|
||||
.then(res => {
|
||||
return res.data
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user