Compare commits

..
16 Commits
Author SHA1 Message Date
Lin, Hung-Shin b41e67ee0b fix: error in quest read (#81) 2023-11-24 12:59:46 +08:00
Chen, Tai-Lin 50a0bbbab1 add warning 2023-11-24 12:59:09 +08:00
Chen, Tai-Lin d712925d0f modify path 2023-11-24 12:56:57 +08:00
Lin, Hung-Shin b78398680d fix: add error handling (#82) 2023-11-24 12:53:00 +08:00
Lin, Hung-Shin c7f52b1003 fix: add error handling 2023-11-24 12:52:01 +08:00
Chen, Tai-Lin f008fb9f60 modify quest map 2023-11-24 12:49:17 +08:00
Chen, Tai-Lin 76a39add29 fix: error in quest read 2023-11-24 11:54:30 +08:00
Lin, Hung-Shin eb9118d5b1 Quest update (#80) 2023-11-24 09:58:09 +08:00
Chen, Tai-Lin cfdf8730e8 fix error 2023-11-24 09:55:17 +08:00
Chen, Tai-Lin 6651071580 fix: error in quest read 2023-11-24 09:54:18 +08:00
Lin, Hung-Shin f30f6472f5 fix: error in quests (#79) 2023-11-24 09:51:33 +08:00
Chen, Tai-Lin 5ac3b3088d fix: error in create quest 2023-11-24 09:50:15 +08:00
Chen, Tai-Lin acc4d5acba fix: error in create quest 2023-11-24 09:48:41 +08:00
Chen, Tai-Lin 1fb43b78e3 fix: erro in quest explore 2023-11-24 09:46:06 +08:00
Lin, Hung-Shin b27adc1f69 Add survey and leaderboard button (#78)
Add survey and leaderboard button
2023-11-24 00:59:34 +08:00
Annie Huang 6f68107405 Add survey and 2023-11-24 00:58:03 +08:00
11 changed files with 126 additions and 65 deletions

No files matched your search

+1 -1
View File
@@ -90,7 +90,7 @@ const handleChange = () => {
class="bg-bg border-8 border-bg-primary flex flex-1 flex-col items-center justify-center rounded-3xl p-10"
>
<h1 class="text-text-primary text-3xl font-black mb-2">{{ title }}</h1>
<div class="text-error inline-flex justify-center items-center xl:hidden">
<div class="text-error inline-flex justify-center items-center md:hidden">
<font-awesome-icon
:icon="['fas', 'circle-exclamation']"
class="px-1 text-sm"
+14 -1
View File
@@ -1,5 +1,17 @@
<template>
<section class="h-[10%] p-3 grid grid-cols-3 gap-4 place-content-between">
<section class="h-[10%] p-3 grid grid-cols-4 gap-4 place-content-between">
<button id="survey" class="bg-bg-secondary rounded-lg p-2">
<a title="Survey" :href="surveyUrl" target="_blank" class="h-5 w-5">
<font-awesome-icon
:icon="['fas', 'file-invoice']"
class="text-text-primary"
/>
<p class="text-text-primary inline ml-1">
<!-- Survey -->
問卷
</p>
</a>
</button>
<button disabled id="solution" class="bg-bg-disabled rounded-lg p-2">
<font-awesome-icon
:icon="['far', 'circle-question']"
@@ -41,6 +53,7 @@
import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification'
import { createSession } from '../store/session'
import { surveyUrl } from '../config'
const router = useRouter()
const reset = async () => {
+22 -1
View File
@@ -3,7 +3,7 @@ import { defineProps, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification'
import { logout } from '../utils/auth'
import { bugReportUrl } from '../config'
import { bugReportUrl, surveyUrl } from '../config'
import { reset } from '../store/session'
import userProfileStore, {
loadUserProfile,
@@ -35,6 +35,15 @@ const handleMap = async () => {
console.error(err)
}
}
const handleLeaderBoard = async () => {
try {
router.push({ name: 'leaderboard' })
} catch (err) {
// toast.error('Failed to load map')
toast.error('無法讀取排行榜')
console.error(err)
}
}
defineProps({
title: {
@@ -110,6 +119,18 @@ onMounted(async () => {
>
{{ userProfileStore.username }}
</p>
<a title="Survey" :href="surveyUrl" target="_blank" class="h-5 w-5">
<font-awesome-icon
:icon="['fas', 'file-invoice']"
class="text-text-primary h-full w-full"
/>
</a>
<button title="LeaderBoard" @click="handleLeaderBoard" class="h-5 w-5">
<font-awesome-icon
:icon="['fas', 'trophy']"
class="text-text-primary h-full w-full"
/>
</button>
<button title="Map" @click="handleMap" class="h-5 w-5">
<font-awesome-icon
:icon="['fas', 'map']"
+6 -5
View File
@@ -15,8 +15,8 @@ import { DAG } from '@linux-odyssey/utils'
import api from '../utils/api'
import { NodeImage } from '../img/svg.js'
const marginX = 200
const marginY = 65
const marginX = 500
const marginY = 300
const chartContainer = ref(null)
let chartInstance = null
const fullwidth = window.screen.width
@@ -71,9 +71,10 @@ const genOption = (nodes, edges) => ({
symbol: () => {
return NodeImage
},
symbolSize: [fullwidth / 10, fullwidth / 25],
symbolSize: [fullwidth / 13, fullwidth / 30],
roam: 'move',
zoom: 1,
zoom: 1.5,
center: ['150%', '50%'],
label: {
show: true,
fontSize: fullwidth / 90,
@@ -103,7 +104,7 @@ const genOption = (nodes, edges) => ({
if (unlocked) {
return '#ADADB5'
}
return '454552'
return '#505050'
},
},
},
+5 -1
View File
@@ -16,6 +16,8 @@ import {
faBug,
faCircleExclamation,
faMap,
faTrophy,
faFileInvoice,
} from '@fortawesome/free-solid-svg-icons'
import {
faLightbulb,
@@ -38,10 +40,12 @@ library.add(
faArrowRight,
faBug,
faMap,
faTrophy,
faCircleExclamation,
faLightbulb,
faCircleQuestion,
faCircleRight,
faGithub,
faGoogle
faGoogle,
faFileInvoice
)
+1 -1
View File
@@ -159,7 +159,7 @@ stages:
- ls-mkdir
condition:
pwd:
- notes
- ^/home/commander/notes$
responses:
- type: narrative
content:
+9 -9
View File
@@ -44,7 +44,7 @@ stages:
- condition:
not:
pwd:
- /home/commander
- ^/home/commander$
responses:
- type: narrative
content:
@@ -78,11 +78,11 @@ stages:
- ls
condition:
pwd:
- /home/commander/folder1
- ^/home/commander/folder1$
exceptions:
- condition:
pwd:
- /home/commander
- ^/home/commander$
responses:
- type: narrative
content:
@@ -90,7 +90,7 @@ stages:
- condition:
not:
pwd:
- /home/commander
- ^/home/commander$
responses:
- type: narrative
content:
@@ -113,7 +113,7 @@ stages:
- cd-folder1
condition:
pwd:
- /home/commander/folder1
- ^/home/commander/folder1$
command:
- ls
responses:
@@ -131,7 +131,7 @@ stages:
- ls-folder1
condition:
pwd:
- /home/commander
- ^/home/commander$
responses:
- content:
- 你成功的回到上一層資料夾了。
@@ -146,7 +146,7 @@ stages:
- cd-..
condition:
pwd:
- /home/commander/folder2
- ^/home/commander/folder2$
responses:
- content:
- 你成功的進入 `folder2` 資料夾了。
@@ -160,7 +160,7 @@ stages:
- cd-folder2
condition:
pwd:
- /home/commander/folder2
- ^/home/commander/folder2$
command:
- ls
responses:
@@ -176,7 +176,7 @@ stages:
- ls-folder2
condition:
pwd:
- /home/commander
- ^/home/commander$
responses:
- content:
- 你成功的回到原本的資料夾了。
+8
View File
@@ -17,6 +17,14 @@ stages:
hints:
- '!! 請勿使用全形空格 !!'
- id: warning-02
repeatable: true
condition:
command:
- '`'
hints:
- '!! 不需要輸入上下引號 !!'
- id: start
task: 輸入 `echo start` 來開始教程
condition:
+4 -8
View File
@@ -64,14 +64,12 @@ stages:
- ➤ 請輸入 `cd ../folder2` 來進入 `folder2` 資料夾。
- id: cd-folder2
task: 用指定方式進入 `folder2` 資料夾
task: 進入 `folder2` 資料夾
requirements:
- cd-folder1
condition:
pwd:
- ^/home/commander/folder2$
command:
- ^cd \.\./folder2$
exceptions:
- condition:
not:
@@ -95,10 +93,8 @@ stages:
requirements:
- cd-folder2
condition:
pwd:
- ^/home/commander/folder2$
command:
- ^ls \.\.\/folder1$
output:
- file1.txt
exceptions:
- condition:
not:
@@ -107,7 +103,7 @@ stages:
responses:
- type: narrative
content:
- 請先回到 `folder2` 資料夾,並用指定的方式查看 `folder1` 資料夾的內容。
- 進到 `folder1` 資料夾並用 `ls` 查看內容。
responses:
- content:
- 很好,你現在知道如何運用相對路徑了。
+6 -6
View File
@@ -44,19 +44,19 @@ stages:
responses:
- content:
- 這個資料夾中有一個檔案和一個資料夾。
- 現在你可以使用 `cat` 指令來查看 `file.txt` 的內容。
- 現在你可以使用 `cat` 指令來查看 `file1.txt` 的內容。
hints:
- ➤ 請輸入 `cat file.txt` 來查看檔案的內容。
- ➤ 請輸入 `cat file1.txt` 來查看檔案的內容。
- id: cat-file
task: 查看 `file.txt` 的內容
- id: cat-file1
task: 查看 `file1.txt` 的內容
requirements:
- ls-~
condition:
pwd:
- ^/home/commander$
command:
- ^cat file.txt$
- ^cat file1.txt$
responses:
- content:
- 你應該能看到檔案的內容了。
@@ -68,7 +68,7 @@ stages:
- id: ls-folder
task: 查看 `folder` 資料夾
requirements:
- cat-file
- cat-file1
condition:
pwd:
- ^/home/commander$
+50 -32
View File
@@ -50,9 +50,18 @@ export default class CommandHandler extends SessionHandler {
}
async discoverHandler() {
const graph = new FileGraph(this.session.graph)
graph.discover(this.params.discover)
this.session.graph = graph
try {
const graph = new FileGraph(this.session.graph)
graph.discover(this.params.discover)
this.session.graph = graph
} catch (e) {
logger.error('Update file graph failed', {
error: e,
session: this.session.id,
graph: this.session.graph,
discover: this.params.discover,
})
}
}
async isMatch(condition) {
@@ -111,37 +120,46 @@ export default class CommandHandler extends SessionHandler {
}
async run() {
this.quest = await Quest.findById(this.session.quest)
const stages = this.getStages()
if (stages.length === 0) {
logger.warn('stage not found', this.session.tasks)
return {}
}
this.handleEvent()
this.handleCommand()
const matches = await Promise.all(
stages.map((stage) => this.isMatch(stage.condition))
)
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) {
return this.executeException(exception)
}
try {
this.quest = await Quest.findById(this.session.quest)
const stages = this.getStages()
if (stages.length === 0) {
logger.warn('stage not found', this.session.tasks)
return {}
}
return {}
}
const response = this.execute(stage)
return {
stage: stage.id,
end: this.session.status === 'finished',
...response,
this.handleEvent()
this.handleCommand()
const matches = await Promise.all(
stages.map((stage) => this.isMatch(stage.condition))
)
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) {
return this.executeException(exception)
}
}
return {}
}
const response = this.execute(stage)
return {
stage: stage.id,
end: this.session.status === 'finished',
...response,
}
} catch (err) {
logger.error('CommandHandler error', {
error: err,
session: this.session.id,
command: this.commandInput,
})
return {}
}
}
}