mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 11:30:12 +08:00
feat: add pending signal to status
This commit is contained in:
1 parent
aec0cf84ad
commit
d724f97403
11 files changed
+90
-30
No files matched your search
@@ -15,6 +15,7 @@ class SessionManager {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
this.pwd = ref('')
|
this.pwd = ref('')
|
||||||
|
this.status = ref('inactive')
|
||||||
}
|
}
|
||||||
|
|
||||||
getSession() {
|
getSession() {
|
||||||
@@ -26,6 +27,7 @@ class SessionManager {
|
|||||||
this.session.value = session
|
this.session.value = session
|
||||||
this.graph.value = new FileGraph(session.graph)
|
this.graph.value = new FileGraph(session.graph)
|
||||||
this.hints.value = session.hints
|
this.hints.value = session.hints
|
||||||
|
this.status.value = session.status
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGraphUpdate(event) {
|
handleGraphUpdate(event) {
|
||||||
@@ -37,8 +39,12 @@ class SessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHintUpdate(event) {
|
handleHintUpdate(hints) {
|
||||||
this.hints.value = [...this.hints.value, ...event]
|
this.hints.value = [...this.hints.value, ...hints]
|
||||||
|
}
|
||||||
|
|
||||||
|
handleStatusUpdate(status) {
|
||||||
|
this.status.value = status
|
||||||
}
|
}
|
||||||
|
|
||||||
setTasks(tasks) {
|
setTasks(tasks) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue'
|
import { computed, onMounted } from 'vue'
|
||||||
import socket from '../utils/socket'
|
import socket from '../utils/socket'
|
||||||
import sessionManager from '../utils/session'
|
import sessionManager from '../utils/session'
|
||||||
import GameHeaderPart from '../components/GameHeaderPart.vue'
|
import GameHeaderPart from '../components/GameHeaderPart.vue'
|
||||||
@@ -11,7 +11,9 @@ import VisualizationPart from '../components/VisualizationPart.vue'
|
|||||||
import ControlPalette from '../components/ControlPalette.vue'
|
import ControlPalette from '../components/ControlPalette.vue'
|
||||||
import CompleteModal from '../components/CompleteModal.vue'
|
import CompleteModal from '../components/CompleteModal.vue'
|
||||||
|
|
||||||
const completed = ref(false)
|
const completed = computed(() => {
|
||||||
|
return sessionManager.status.value === 'finished'
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await sessionManager.lastOrCreate()
|
await sessionManager.lastOrCreate()
|
||||||
@@ -33,12 +35,7 @@ onMounted(async () => {
|
|||||||
})
|
})
|
||||||
socket.on('message', console.log)
|
socket.on('message', console.log)
|
||||||
socket.on('status', (event) => {
|
socket.on('status', (event) => {
|
||||||
console.log('status', event)
|
sessionManager.handleStatusUpdate(event)
|
||||||
if (event === 'finished') {
|
|
||||||
setTimeout(() => {
|
|
||||||
completed.value = true
|
|
||||||
}, 5000)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -48,6 +45,12 @@ onMounted(async () => {
|
|||||||
<div class="h-[5vh] w-full">
|
<div class="h-[5vh] w-full">
|
||||||
<GameHeaderPart />
|
<GameHeaderPart />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- current status indicator -->
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
id="currentStatus"
|
||||||
|
:value="sessionManager.status.value"
|
||||||
|
/>
|
||||||
<!-- main -->
|
<!-- main -->
|
||||||
<div id="main" class="h-[95vh] w-full flex p-3 space-x-3">
|
<div id="main" class="h-[95vh] w-full flex p-3 space-x-3">
|
||||||
<!-- Topic and Command List -->
|
<!-- Topic and Command List -->
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ services:
|
|||||||
- BASE_URL=http://localhost:5173
|
- BASE_URL=http://localhost:5173
|
||||||
- MONGO_URL=mongodb://db:27017/odyssey-test
|
- MONGO_URL=mongodb://db:27017/odyssey-test
|
||||||
- DOCKER_NETWORK=linux-odyssey-players
|
- DOCKER_NETWORK=linux-odyssey-players
|
||||||
# - HOST_PWD=${PWD}
|
- HOST_PWD=${PWD}
|
||||||
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
||||||
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
||||||
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
|
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
|
||||||
|
|||||||
+17
-14
@@ -2,6 +2,7 @@
|
|||||||
const fs = require('fs').promises
|
const fs = require('fs').promises
|
||||||
const { exit } = require('process')
|
const { exit } = require('process')
|
||||||
const minimist = require('minimist')
|
const minimist = require('minimist')
|
||||||
|
const axios = require('axios')
|
||||||
const { colorize, printResponses } = require('./print.js')
|
const { colorize, printResponses } = require('./print.js')
|
||||||
const discoverFiles = require('./discover.js')
|
const discoverFiles = require('./discover.js')
|
||||||
|
|
||||||
@@ -40,6 +41,13 @@ async function main() {
|
|||||||
} = process.env
|
} = process.env
|
||||||
if (!CMD_NAME) exit(0)
|
if (!CMD_NAME) exit(0)
|
||||||
|
|
||||||
|
const api = axios.create({
|
||||||
|
baseURL: `${API_ENDPOINT}/api/v1`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${TOKEN}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const additionalData = await handleCommand(CMD_NAME)
|
const additionalData = await handleCommand(CMD_NAME)
|
||||||
|
|
||||||
const output = await readOrNone(CMD_OUTPUT_FILE)
|
const output = await readOrNone(CMD_OUTPUT_FILE)
|
||||||
@@ -53,24 +61,19 @@ async function main() {
|
|||||||
...additionalData,
|
...additionalData,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_ENDPOINT}/api/v1/commands`, {
|
const res = await api.post('/commands', payload)
|
||||||
method: 'POST',
|
if (!res.data) return
|
||||||
headers: {
|
const { responses, hints, end } = res.data
|
||||||
'Content-Type': 'application/json',
|
if (responses) {
|
||||||
Authorization: `Bearer ${TOKEN}`,
|
await printResponses(responses, 60)
|
||||||
},
|
await api.post('/commands/completed')
|
||||||
body: JSON.stringify(payload),
|
|
||||||
})
|
|
||||||
const data = await res.json()
|
|
||||||
if (data.responses) {
|
|
||||||
await printResponses(data.responses, 60)
|
|
||||||
}
|
}
|
||||||
if (data.hints) {
|
if (hints) {
|
||||||
for (const hint of data.hints) {
|
for (const hint of hints) {
|
||||||
console.log(colorize(hint, 'yellow'))
|
console.log(colorize(hint, 'yellow'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.end) {
|
if (end) {
|
||||||
console.log(colorize('Quest completed!', 'blue'))
|
console.log(colorize('Quest completed!', 'blue'))
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^3.5.3",
|
"axios": "^1.6.0",
|
||||||
"minimist": "^1.2.8"
|
"minimist": "^1.2.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
import { Command, Session } from '@linux-odyssey/models'
|
import { Command, Session } from '@linux-odyssey/models'
|
||||||
import CommandHandler from '../../game/commandHandler.js'
|
import CommandHandler from '../../game/commandHandler.js'
|
||||||
|
import { pushToSession } from '../socket.js'
|
||||||
|
|
||||||
|
const commandCompleteCallbacks = new Map()
|
||||||
|
|
||||||
export async function newCommand(req, res) {
|
export async function newCommand(req, res) {
|
||||||
console.log('new command:', req.body)
|
console.log('new command:', req.body)
|
||||||
@@ -44,8 +46,35 @@ export async function newCommand(req, res) {
|
|||||||
if (response) {
|
if (response) {
|
||||||
c.stage = response.stage
|
c.stage = response.stage
|
||||||
await c.save()
|
await c.save()
|
||||||
|
commandCompleteCallbacks.set(session.id, response.callback)
|
||||||
|
pushToSession(session.id, 'status', 'pending')
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(201).json(response)
|
res.status(201).json(response)
|
||||||
await session.save()
|
await session.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function completedCommand(req, res) {
|
||||||
|
const sessionId = req.user.session_id
|
||||||
|
|
||||||
|
const session = await Session.findById(sessionId)
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
res.status(404).json({ message: 'session not found' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.status === 'inactive') {
|
||||||
|
res.status(400).json({ message: 'session is not active' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const callback = commandCompleteCallbacks.get(session.id)
|
||||||
|
if (!callback) {
|
||||||
|
res.status(400).json({ message: 'no callback found' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
commandCompleteCallbacks.delete(session.id)
|
||||||
|
res.json({ message: 'ok' })
|
||||||
|
}
|
||||||
@@ -44,6 +44,12 @@ export async function createSession(req, res) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deactive all active sessions
|
||||||
|
await Session.updateMany(
|
||||||
|
{ user: req.user._id, quest, status: 'active' },
|
||||||
|
{ status: 'inactive' }
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const container = await createContainer(
|
const container = await createContainer(
|
||||||
`quest-${quest.id}-${req.user.username}-${Date.now()}`
|
`quest-${quest.id}-${req.user.username}-${Date.now()}`
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ import * as commandController from '../controllers/commandController.js'
|
|||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router.post('/', commandController.newCommand)
|
router.post('/', commandController.newCommand)
|
||||||
|
router.post('/completed', commandController.completedCommand)
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
@@ -19,6 +19,7 @@ router.use('/sessions', authRequired, sessions)
|
|||||||
router.use(
|
router.use(
|
||||||
'/commands',
|
'/commands',
|
||||||
passport.authenticate('jwt', { session: false }),
|
passport.authenticate('jwt', { session: false }),
|
||||||
|
authRequired,
|
||||||
commands
|
commands
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ export default class SessionHandler {
|
|||||||
addNewTasks() {
|
addNewTasks() {
|
||||||
const newTasks = this.getNewTasks()
|
const newTasks = this.getNewTasks()
|
||||||
this.session.tasks.push(...newTasks)
|
this.session.tasks.push(...newTasks)
|
||||||
pushToSession(this.session.id, 'tasks', this.session.tasks)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(stage) {
|
execute(stage) {
|
||||||
@@ -45,12 +44,10 @@ export default class SessionHandler {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.session.hints.push(...stage.hints)
|
this.session.hints.push(...stage.hints)
|
||||||
pushToSession(this.session.id, 'hints', stage.hints)
|
|
||||||
|
|
||||||
if (stage.id === 'END') {
|
if (stage.id === 'END') {
|
||||||
this.session.status = 'finished'
|
this.session.status = 'finished'
|
||||||
this.session.finishedAt = new Date()
|
this.session.finishedAt = new Date()
|
||||||
pushToSession(this.session.id, 'status', 'finished')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addNewTasks()
|
this.addNewTasks()
|
||||||
@@ -58,6 +55,11 @@ export default class SessionHandler {
|
|||||||
return {
|
return {
|
||||||
responses: stage.responses,
|
responses: stage.responses,
|
||||||
hints: stage.hints,
|
hints: stage.hints,
|
||||||
|
callback: () => {
|
||||||
|
pushToSession(this.session.id, 'tasks', this.session.tasks)
|
||||||
|
pushToSession(this.session.id, 'hints', stage.hints)
|
||||||
|
pushToSession(this.session.id, 'status', this.session.status)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1407,6 +1407,15 @@ axios@^1.5.0:
|
|||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
proxy-from-env "^1.1.0"
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
|
axios@^1.6.0:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
|
||||||
|
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.15.0"
|
||||||
|
form-data "^4.0.0"
|
||||||
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
babel-jest@^29.6.1:
|
babel-jest@^29.6.1:
|
||||||
version "29.6.1"
|
version "29.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a"
|
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a"
|
||||||
|
|||||||
Reference in new issue
Block a user