UNPKG

rubiks-cube-mcp-server

Version:
131 lines (130 loc) 4.99 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VisualizationServer = void 0; const express_1 = __importDefault(require("express")); const http_1 = require("http"); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const WebSocketHandler_js_1 = require("./WebSocketHandler.js"); const APIRoutes_js_1 = require("./APIRoutes.js"); class VisualizationServer { app; server; webSocketHandler; apiRoutes; sessions; constructor() { this.app = (0, express_1.default)(); this.server = (0, http_1.createServer)(this.app); this.sessions = new Map(); this.setupTemplateEngine(); this.webSocketHandler = new WebSocketHandler_js_1.WebSocketHandler(this.server, this.sessions); this.apiRoutes = new APIRoutes_js_1.APIRoutes(this.sessions); this.setupRoutes(); } setupTemplateEngine() { // EJS 템플릿 엔진 설정 this.app.set('view engine', 'ejs'); // 패키지 루트 디렉토리 찾기 const packageRoot = this.findPackageRoot(); this.app.set('views', path_1.default.join(packageRoot, 'views')); // 정적 파일 서빙 this.app.use(express_1.default.static(path_1.default.join(packageRoot, 'public'))); this.app.use(express_1.default.json()); } findPackageRoot() { // 현재 실행 파일의 위치에서 package.json이 있는 디렉토리를 찾음 let currentDir = __dirname; while (currentDir !== path_1.default.dirname(currentDir)) { try { const packageJsonPath = path_1.default.join(currentDir, 'package.json'); if (fs_1.default.existsSync(packageJsonPath)) { const packageJson = require(packageJsonPath); if (packageJson.name === 'rubiks-cube-mcp-server') { return currentDir; } } } catch (e) { // continue searching } currentDir = path_1.default.dirname(currentDir); } // 기본값: 현재 디렉토리에서 2레벨 위 return path_1.default.join(__dirname, '../..'); } setupRoutes() { // API 라우트 this.app.use('/api', this.apiRoutes.getRouter()); // 메인 페이지 this.app.get('/', (req, res) => { const games = Array.from(this.sessions.entries()).map(([id, session]) => ({ id, title: `Game ${id.split('_')[1]}`, status: session.status, moveCount: session.cubeState.moveHistory.length, createdAt: new Date(session.createdAt).toLocaleString(), statusIcon: session.status === 'completed' ? '🎉' : '🎲', statusText: session.status === 'completed' ? 'SOLVED' : 'Active' })); res.render('gameList', { games }); }); // 게임 페이지 this.app.get('/game/:gameId', (req, res) => { const { gameId } = req.params; const session = this.sessions.get(gameId); if (!session) { return res.status(404).send(` <html> <body style="font-family: Arial; text-align: center; padding: 50px;"> <h1>Game Not Found</h1> <p>Game session "${gameId}" not found.</p> <a href="/">← Back to Games</a> </body> </html> `); } res.render('gameView', { gameId, session, cubeState: session.cubeState }); }); } // 세션 등록 registerSession(session) { this.sessions.set(session.id, session); } // 세션 업데이트 updateSession(gameId, cubeState) { const session = this.sessions.get(gameId); if (session) { session.cubeState = cubeState; session.lastActivity = Date.now(); if (cubeState.solved) { session.status = 'completed'; } this.webSocketHandler.broadcastGameState(gameId, cubeState, session.status); } } // 서버 시작 start(port = 3000) { this.server.listen(port, () => { console.error(`🎲 3D Cube visualization server running on http://localhost:${port}`); console.error(`🌐 WebSocket enabled for real-time updates`); }); } // 서버 종료 stop() { if (this.server) { this.server.close(() => { console.error("✅ Visualization server closed"); }); this.webSocketHandler.close(); } } } exports.VisualizationServer = VisualizationServer;