From b4b8f8baeea8e6c4286a3e67def41c0d83d0ad42 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Wed, 23 Apr 2025 16:17:10 +0800 Subject: [PATCH] feat: load responses and tasks from existing session --- app/src/store/session.ts | 30 ++++++++++--------- app/src/types.ts | 6 ++-- packages/game/src/Session.ts | 2 +- packages/game/src/schema/condition.ts | 7 +++++ packages/game/test/exceptions.test.ts | 8 ++--- packages/game/test/session.test.ts | 10 +++---- .../src/api/controllers/commandController.ts | 2 +- server/src/routers/index.ts | 2 ++ server/src/routers/sessionRouter.ts | 13 ++++++++ 9 files changed, 52 insertions(+), 28 deletions(-) diff --git a/app/src/store/session.ts b/app/src/store/session.ts index 613e104..aaa6512 100644 --- a/app/src/store/session.ts +++ b/app/src/store/session.ts @@ -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) }) diff --git a/app/src/types.ts b/app/src/types.ts index b5630c2..e59e4c7 100644 --- a/app/src/types.ts +++ b/app/src/types.ts @@ -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[] } diff --git a/packages/game/src/Session.ts b/packages/game/src/Session.ts index 0ad6b6b..c0c72c6 100644 --- a/packages/game/src/Session.ts +++ b/packages/game/src/Session.ts @@ -8,7 +8,7 @@ import { ITask, } from './schema' -export class Session implements ISession { +export class GameSession implements ISession { private completed: string[] = [] private quest: Quest diff --git a/packages/game/src/schema/condition.ts b/packages/game/src/schema/condition.ts index e32a6af..090eb2a 100644 --- a/packages/game/src/schema/condition.ts +++ b/packages/game/src/schema/condition.ts @@ -35,3 +35,10 @@ export const conditionSchema: z.ZodType = export interface IFileExistenceChecker { exists(file: IFileInput): Promise } + +export class VoidFileExistenceChecker implements IFileExistenceChecker { + // eslint-disable-next-line class-methods-use-this + async exists(_file: IFileInput): Promise { + return false + } +} diff --git a/packages/game/test/exceptions.test.ts b/packages/game/test/exceptions.test.ts index f801077..4ba77a9 100644 --- a/packages/game/test/exceptions.test.ts +++ b/packages/game/test/exceptions.test.ts @@ -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() diff --git a/packages/game/test/session.test.ts b/packages/game/test/session.test.ts index ccc5d79..b1d633f 100644 --- a/packages/game/test/session.test.ts +++ b/packages/game/test/session.test.ts @@ -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: [], }, diff --git a/server/src/api/controllers/commandController.ts b/server/src/api/controllers/commandController.ts index 2af7b48..b02feb1 100644 --- a/server/src/api/controllers/commandController.ts +++ b/server/src/api/controllers/commandController.ts @@ -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' diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts index 7e18636..9e1fdf9 100644 --- a/server/src/routers/index.ts +++ b/server/src/routers/index.ts @@ -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 diff --git a/server/src/routers/sessionRouter.ts b/server/src/routers/sessionRouter.ts index 9277103..7c4333b 100644 --- a/server/src/routers/sessionRouter.ts +++ b/server/src/routers/sessionRouter.ts @@ -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({