diff --git a/docker-compose.yml b/docker-compose.yml index 8a03ed9..40925c6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,15 @@ services: volumes: - ./data:/data/db + swagger: + image: swaggerapi/swagger-editor:latest + ports: + - 8080:8080 + volumes: + - ./server/swagger.yaml:/tmp/swagger.yaml + environment: + - SWAGGER_FILE=/tmp/swagger.yaml + networks: internal: players: diff --git a/server/quests/helloworld/game.yml b/server/quests/helloworld/game.yml index d7f6f47..e7dd507 100644 --- a/server/quests/helloworld/game.yml +++ b/server/quests/helloworld/game.yml @@ -1,6 +1,6 @@ title: Hello, Linux World! order: 1 -introduction: | +instruction: | 你身在一個漆黑的房間裡,沒有任何的光線或聲音。你想不起來為什麼自己會來到這裡。但你的腦中隱約感到某個聲音跟你說: 「輸入 echo Hello World!」 @@ -17,7 +17,7 @@ stages: - 首先,你必須要學會如何使用指令。 - 一個指令是由一個指令名稱和一些參數所組成的,而指令名稱和參數之間是以空白字元分隔。 - 例如,你可以輸入 `ls` 來查看目前的目錄下有哪些檔案。 - hint: + hints: - 使用 `ls` 指令來查看目前的目錄下有哪些檔案。 next: ls - id: ls diff --git a/server/src/api/controllers/commandController.js b/server/src/api/controllers/commandController.js index d4deabe..add1214 100644 --- a/server/src/api/controllers/commandController.js +++ b/server/src/api/controllers/commandController.js @@ -6,7 +6,7 @@ import commandHandler from '../../game/commandHandler.js' export async function newCommand(req, res) { console.log('new command:', req.body) - const { token, command, pwd, exit_code, output } = req.body + const { token, command, pwd, output, error } = req.body if (!command) { res.status(400).json({ message: 'command is required' }) @@ -33,8 +33,8 @@ export async function newCommand(req, res) { session, command, pwd, - exit_code, output, + error, }) await c.save() diff --git a/server/src/api/controllers/questController.js b/server/src/api/controllers/questController.js index a9ca070..059490e 100644 --- a/server/src/api/controllers/questController.js +++ b/server/src/api/controllers/questController.js @@ -3,9 +3,8 @@ import Quest from '../../models/quest.js' export async function getQuests(req, res) { const quests = await Quest.find({}).sort({ order: 1 }) res.json( - quests.map(({ name, title, order, _id }) => ({ + quests.map(({ title, order, _id }) => ({ _id, - name, title, order, })) @@ -19,5 +18,6 @@ export async function getQuestDetail(req, res) { res.status(404).json({ message: 'Quest not found.' }) return } - res.json(quest) + const { _id, title, order, instruction } = quest + res.json({ _id, title, order, instruction }) } diff --git a/server/src/game/commandHandler.js b/server/src/game/commandHandler.js index c5d2c5b..ca99dff 100644 --- a/server/src/game/commandHandler.js +++ b/server/src/game/commandHandler.js @@ -28,6 +28,7 @@ const commandHandler = async (session, commandInput) => { if (!commandMatch || !outputMatch || !errorMatch) return {} session.completion.push(session.progress) + session.hints.push(...stage.hints) const nextStage = quest.stages.find((s) => s.id === stage.next) session.progress = nextStage.id @@ -35,7 +36,6 @@ const commandHandler = async (session, commandInput) => { return { responses: stage.responses, - hint: stage.hint, } } diff --git a/server/src/models/quest.js b/server/src/models/quest.js index 7c68866..2b46935 100644 --- a/server/src/models/quest.js +++ b/server/src/models/quest.js @@ -23,7 +23,7 @@ const stageSchema = new Schema({ type: [String], required: true, }, - hint: { + hints: { type: [String], required: true, }, @@ -39,7 +39,7 @@ const Quest = model( _id: String, title: String, order: Number, - introduction: String, + instruction: String, stages: [stageSchema], }) ) diff --git a/server/src/models/session.js b/server/src/models/session.js index c1b813e..5ae0865 100644 --- a/server/src/models/session.js +++ b/server/src/models/session.js @@ -16,6 +16,7 @@ const Session = model( finishedAt: Date, progress: String, completion: [String], + hints: [String], }, { timestamps: true } ) diff --git a/server/swagger.yaml b/server/swagger.yaml index 2527225..5532b60 100644 --- a/server/swagger.yaml +++ b/server/swagger.yaml @@ -1,6 +1,8 @@ openapi: 3.0.0 servers: - url: /api/v1 + - url: https://odyssey.wancat.cc/api/v1 + - url: http://localhost:3000/api/v1 info: description: Linux Odyssey API version: '1.0.0' @@ -304,6 +306,10 @@ paths: responses: '201': description: Command recorded successfully + content: + application/json: + schema: + $ref: '#/components/schemas/CommandResponse' '400': description: Invalid request body '401': @@ -333,10 +339,9 @@ components: title: type: string example: Hello World - content: + instruction: type: string - format: html - example: '

Hello World

' + example: 'In this quest, you need to learn how to use `ls` to list the file.' order: type: number @@ -372,20 +377,21 @@ components: finished_at: type: string format: date-time - terminals: - type: array - items: - type: string - graphs: - $ref: '#/components/schemas/TreeNode' - progress: - type: array - items: - $ref: '#/components/schemas/Progress' hints: type: array items: - $ref: '#/components/schemas/Hint' + type: string + example: '`ls -al` to list detail information of all files.' + progress: + type: string + description: current stage id + example: helloworld + completion: + type: array + description: list of completed stage ids + items: + type: string + example: helloworld SessionSummary: type: object @@ -418,28 +424,6 @@ components: items: $ref: '#/components/schemas/TreeNode' - Progress: - type: object - properties: - name: - type: string - finished_at: - type: string - format: date-time - skipped_at: - type: string - format: date-time - - Hint: - type: object - properties: - name: - type: string - content: - type: string - source: - type: string - Command: type: object required: @@ -461,6 +445,18 @@ components: output: type: string description: The output of the command + error: + type: string + description: The error message of the command + + CommandResponse: + type: object + properties: + responses: + type: array + items: + type: string + example: 'You have completed the quest!' securitySchemes: BearerAuth: