diff --git a/packages/cli/cli.js b/packages/cli/cli.js index b170f09..91b5d66 100644 --- a/packages/cli/cli.js +++ b/packages/cli/cli.js @@ -95,4 +95,4 @@ async function main() { } } -main() +main().then(exit) diff --git a/server/quests/helloworld/game.yml b/server/quests/helloworld/game.yml index 8db3f1e..d7f6f47 100644 --- a/server/quests/helloworld/game.yml +++ b/server/quests/helloworld/game.yml @@ -5,7 +5,7 @@ introduction: | 「輸入 echo Hello World!」 stages: - - name: helloworld + - id: helloworld condition: command: - echo Hello World! @@ -19,3 +19,11 @@ stages: - 例如,你可以輸入 `ls` 來查看目前的目錄下有哪些檔案。 hint: - 使用 `ls` 指令來查看目前的目錄下有哪些檔案。 + next: ls + - id: ls + condition: + command: + - ls + responses: + - NOTHING + next: END diff --git a/server/src/api/controllers/commandController.js b/server/src/api/controllers/commandController.js index 7cfbb0c..d4deabe 100644 --- a/server/src/api/controllers/commandController.js +++ b/server/src/api/controllers/commandController.js @@ -2,6 +2,7 @@ import Command from '../../models/command.js' import Session from '../../models/session.js' import { verifySessionJWT } from '../../utils/auth.js' +import commandHandler from '../../game/commandHandler.js' export async function newCommand(req, res) { console.log('new command:', req.body) @@ -38,7 +39,8 @@ export async function newCommand(req, res) { await c.save() - res.status(201).json({ - responses: ['Hello, world!', 'How are you?'], - }) + const response = await commandHandler(session, c) + console.log(response) + + res.status(201).json(response) } diff --git a/server/src/api/controllers/sessionController.js b/server/src/api/controllers/sessionController.js index 81e163f..79b0940 100644 --- a/server/src/api/controllers/sessionController.js +++ b/server/src/api/controllers/sessionController.js @@ -23,9 +23,11 @@ export async function createSession(req, res) { } try { + const progress = quest.stages[0].id const newSession = new Session({ user: req.user, quest, + progress, containerId: `quest-${quest.id}-${req.user.username}-${Date.now()}`, }) diff --git a/server/src/game/commandHandler.js b/server/src/game/commandHandler.js new file mode 100644 index 0000000..c5d2c5b --- /dev/null +++ b/server/src/game/commandHandler.js @@ -0,0 +1,42 @@ +import Quest from '../models/quest.js' + +// 檢查 pattern 是否符合 input +const checkMatch = (pattern, input) => { + if (pattern.length === 0) return true + return pattern.some((p) => { + const regex = new RegExp(p) + return regex.test(input) + }) +} + +const commandHandler = async (session, commandInput) => { + const quest = await Quest.findById(session.quest) + const stage = quest.stages.find((s) => s.id === session.progress) + if (!stage) { + console.error('stage not found', session.progress) + return {} + } + + console.log(stage.condition) + + const commandMatch = checkMatch(stage.condition.command, commandInput.command) + const outputMatch = checkMatch(stage.condition.output, commandInput.output) + const errorMatch = checkMatch(stage.condition.error, commandInput.output) + + console.log(commandMatch, outputMatch, errorMatch) + + if (!commandMatch || !outputMatch || !errorMatch) return {} + + session.completion.push(session.progress) + + const nextStage = quest.stages.find((s) => s.id === stage.next) + session.progress = nextStage.id + await session.save() + + return { + responses: stage.responses, + hint: stage.hint, + } +} + +export default commandHandler diff --git a/server/src/models/quest.js b/server/src/models/quest.js index d16804d..7c68866 100644 --- a/server/src/models/quest.js +++ b/server/src/models/quest.js @@ -1,7 +1,7 @@ import { model, Schema } from 'mongoose' const stageSchema = new Schema({ - name: { + id: { type: String, required: true, }, @@ -27,6 +27,10 @@ const stageSchema = new Schema({ type: [String], required: true, }, + next: { + type: String, + required: true, + }, }) const Quest = model( diff --git a/server/src/models/session.js b/server/src/models/session.js index 62ccdf6..c1b813e 100644 --- a/server/src/models/session.js +++ b/server/src/models/session.js @@ -14,6 +14,8 @@ const Session = model( }, containerId: String, finishedAt: Date, + progress: String, + completion: [String], }, { timestamps: true } )