feat: load responses and tasks from existing session

This commit is contained in:
Justin Lin committed 2025-04-23 16:17:10 +08:00
1 parent 2fcca0c4b9
commit b4b8f8baee
9 files changed
+52 -28

No files matched your search

+16 -14
View File
@@ -43,7 +43,7 @@ const useSession = defineStore('session', {
},
async setSession(session: Session) {
console.log('set session', session)
this.session = { ...session, tasks: [] }
this.session = session
// this.session.graph = new FileGraph(session.graph)
term.reset()
await socket.connect(session)
@@ -55,20 +55,22 @@ const useSession = defineStore('session', {
socket.emit('terminal', 'echo start\n')
},
async getActiveSession() {
const session = await getActiveSession(this.questId)
const session = await trpc.session.getActiveSession.query({
questId: this.questId,
})
if (session) {
this.setSession(session)
}
},
updateGraph(event: { discover?: FileObject[]; pwd?: string }) {
if (!this.session) return
if (event.discover) {
this.session.graph.discover(event.discover)
}
if (event.pwd) {
this.session.pwd = event.pwd
}
},
// updateGraph(event: { discover?: FileObject[]; pwd?: string }) {
// if (!this.session) return
// if (event.discover) {
// this.session.graph.discover(event.discover)
// }
// if (event.pwd) {
// this.session.pwd = event.pwd
// }
// },
newUpdate(update: SessionUpdate) {
if (!this.session) return
this.session.responses = update.responses
@@ -103,9 +105,9 @@ const useSession = defineStore('session', {
term.onData((data: string) => {
socket.emit('terminal', data)
})
socket.on('graph', (event: { discover: FileObject[]; pwd: string }) => {
this.updateGraph(event)
})
// socket.on('graph', (event: { discover: FileObject[]; pwd: string }) => {
// this.updateGraph(event)
// })
socket.on('update', (update: SessionUpdate) => {
this.newUpdate(update)
})
+3 -3
View File
@@ -17,9 +17,9 @@ export interface StageResponse {
export interface Session {
_id: string
status: string
graph: FileGraph
pwd: string
hints: string[][]
// graph: FileGraph
// pwd: string
// hints: string[][]
tasks: ITask[]
responses: IResponse[]
}
+1 -1
View File
@@ -8,7 +8,7 @@ import {
ITask,
} from './schema'
export class Session implements ISession {
export class GameSession implements ISession {
private completed: string[] = []
private quest: Quest
+7
View File
@@ -35,3 +35,10 @@ export const conditionSchema: z.ZodType<ICondition> =
export interface IFileExistenceChecker {
exists(file: IFileInput): Promise<boolean>
}
export class VoidFileExistenceChecker implements IFileExistenceChecker {
// eslint-disable-next-line class-methods-use-this
async exists(_file: IFileInput): Promise<boolean> {
return false
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
import { expect, it, describe } from '@jest/globals'
import { IQuest } from '../src/schema'
import { Session } from '../src/Session'
import { GameSession } from '../src/Session'
import { MockFileChecker } from './asyncCondition.test'
const quest: IQuest = {
@@ -65,7 +65,7 @@ const quest: IQuest = {
describe('exceptions', () => {
it('should return the stage exception', async () => {
const session = new Session(
const session = new GameSession(
{ completedEvents: [] },
quest,
new MockFileChecker()
@@ -76,7 +76,7 @@ describe('exceptions', () => {
})
it('should return the catch all exception', async () => {
const session = new Session(
const session = new GameSession(
{ completedEvents: [] },
quest,
new MockFileChecker()
@@ -87,7 +87,7 @@ describe('exceptions', () => {
})
it('should return the global exception', async () => {
const session = new Session(
const session = new GameSession(
{ completedEvents: [] },
quest,
new MockFileChecker()
+5 -5
View File
@@ -1,6 +1,6 @@
import { expect, describe, it } from '@jest/globals'
import { IQuest } from '../src/schema'
import { Session } from '../src/Session'
import { GameSession } from '../src/Session'
import { MockFileChecker } from './asyncCondition.test'
const quest: IQuest = {
@@ -64,7 +64,7 @@ const quest: IQuest = {
describe('Session', () => {
it('should return active stages', () => {
const session = new Session(
const session = new GameSession(
{
completedEvents: [],
},
@@ -84,7 +84,7 @@ describe('Session', () => {
})
it('should run command', async () => {
const session = new Session(
const session = new GameSession(
{
completedEvents: [],
},
@@ -111,7 +111,7 @@ describe('Session', () => {
})
it('should return all responses', () => {
const session = new Session(
const session = new GameSession(
{
completedEvents: ['stage1'],
},
@@ -135,7 +135,7 @@ describe('Session', () => {
})
it('should return tasks', () => {
const session = new Session(
const session = new GameSession(
{
completedEvents: [],
},
@@ -1,4 +1,4 @@
import { Session as GameSession } from '@linux-odyssey/game'
import { GameSession } from '@linux-odyssey/game'
import { Command, Session } from '@linux-odyssey/models'
import { matchedData } from 'express-validator'
import type { Request, Response } from 'express'
+2
View File
@@ -2,6 +2,7 @@ import { router, publicProcedure } from '../trpc.js'
import { linkRouter } from './linkRouter.js'
import { questRouter } from './questRouter.js'
import { userRouter } from './userRouter.js'
import { sessionRouter } from './sessionRouter.js'
export const appRouter = router({
userList: publicProcedure.query(async (opts) => {
@@ -11,6 +12,7 @@ export const appRouter = router({
links: linkRouter,
quests: questRouter,
users: userRouter,
session: sessionRouter,
})
export type AppRouter = typeof appRouter
+13
View File
@@ -1,9 +1,11 @@
import { TRPCError } from '@trpc/server'
import { Session } from '@linux-odyssey/models'
import { GameSession, VoidFileExistenceChecker } from '@linux-odyssey/game'
import { z } from 'zod'
import { isQuestUnlocked } from '../models/sessionManager.js'
import config from '../config.js'
import { protectedProcedure, router } from '../trpc.js'
import { questManager } from '../models/quest.js'
export const sessionRouter = router({
getActiveSession: protectedProcedure
@@ -27,6 +29,15 @@ export const sessionRouter = router({
if (!session) {
return null
}
const quest = await questManager.get(questId)
if (!quest) {
return null
}
const gameSession = new GameSession(
session,
quest,
new VoidFileExistenceChecker()
)
return {
_id: session._id.toString(),
user: session.user,
@@ -35,6 +46,8 @@ export const sessionRouter = router({
createdAt: session.createdAt,
lastActivityAt: session.lastActivityAt,
completedEvents: session.completedEvents,
responses: gameSession.getResponses(),
tasks: gameSession.getTasks(),
}
}
throw new TRPCError({