feat: add exceptions to stage

This commit is contained in:
Lin, Hung-Shin committed 2023-11-21 14:27:43 +08:00
1 parent 56d96cf7a0
commit 66ce015f0e
6 files changed
+86 -1

No files matched your search

+1
View File
@@ -28,5 +28,6 @@ module.exports = {
'no-plusplus': 'off',
'prettier/prettier': ['error', { endOfLine: 'auto', semi: false }],
'import/prefer-default-export': 'off',
'no-restricted-syntax': ['off', 'ForOfStatement'],
},
}
+24
View File
@@ -35,6 +35,26 @@ conditionSchema.add({
not: conditionSchema,
})
const exceptionSchema = new Schema({
condition: {
type: conditionSchema,
required: false,
},
catchAll: {
type: Boolean,
required: true,
default: false,
},
responses: {
type: [responseSchema],
required: true,
},
hints: {
type: [String],
required: true,
},
})
const stageSchema = new Schema({
id: {
type: String,
@@ -66,6 +86,10 @@ const stageSchema = new Schema({
type: [String],
required: true,
},
exceptions: {
type: [exceptionSchema],
required: true,
},
})
const Quest = model(
+3
View File
@@ -0,0 +1,3 @@
FROM linuxodyssey/quest-base
COPY home ${HOME}
+22 -1
View File
@@ -1,6 +1,27 @@
title: 複製檔案
instruction: |
複製檔案
在這個關卡中,你將學習如何複製檔案。
requirements:
- create
stages:
- id: start
task: 輸入 `echo start` 來開始
condition:
output:
- start
exceptions:
- condition:
command:
- ^echo$
responses:
- type: narrative
content:
- 你忘記輸入 `start` 了嗎?
- 請輸入 `echo start` 來開始
- catchAll: true
responses:
- type: narrative
content:
- 請輸入 `echo start` 來開始
+21
View File
@@ -97,6 +97,19 @@ export default class CommandHandler extends SessionHandler {
return matches.some((m) => m === true)
}
async checkException(stage) {
const exceptions = stage.exceptions || []
for (const exception of exceptions) {
console.log(exception)
// eslint-disable-next-line no-await-in-loop
if (exception.condition && (await this.isMatch(exception.condition))) {
return exception
}
if (exception.catchAll) return exception
}
return null
}
async run() {
this.quest = await Quest.findById(this.session.quest)
const stages = this.getStages()
@@ -114,6 +127,14 @@ export default class CommandHandler extends SessionHandler {
const stage = stages.find((_, i) => matches[i])
if (!stage) {
for (const s of stages) {
// eslint-disable-next-line no-await-in-loop
const exception = await this.checkException(s)
if (exception) {
console.log('Got exception', exception)
return this.executeException(exception)
}
}
return {}
}
const response = this.execute(stage)
+15
View File
@@ -63,4 +63,19 @@ export default class SessionHandler {
},
}
}
executeException(exception) {
const { hints, responses } = exception
if (hints && hints.length > 0) this.session.hints.push(hints)
return {
responses,
hints,
callback: () => {
if (hints && hints.length > 0)
pushToSession(this.session.id, 'hints', hints)
pushToSession(this.session.id, 'status', this.session.status)
},
}
}
}