UNPKG

poem_game_component

Version:

468 lines (454 loc) 15.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { Game: () => Game, GameController: () => GameController, GameFactory: () => GameFactory, GameService: () => GameService, GameStatus: () => GameStatus, GameType: () => GameType, Player: () => Player, RuleFactory: () => RuleFactory, createRoutes: () => createRoutes }); module.exports = __toCommonJS(index_exports); // src/infrastructure/services/RestGameRuleService.ts var import_axios = __toESM(require("axios")); // src/domain/enums/GameType.ts var GameType = /* @__PURE__ */ ((GameType2) => { GameType2["POEM_MATCHING"] = "POEM_MATCHING"; GameType2["FLOWER_POEM"] = "FLOWER_POEM"; GameType2["CHAIN_POEM"] = "CHAIN_POEM"; return GameType2; })(GameType || {}); // src/infrastructure/services/RestGameRuleService.ts var RestGameRuleService = class { constructor(gameType) { this.gameType = gameType; this.baseUrl = this.getBaseUrl(gameType); } getBaseUrl(gameType) { switch (gameType) { case "CHAIN_POEM" /* CHAIN_POEM */: return process.env.CHAIN_POEM_API_URL || "http://localhost:3001/api/chain-poem"; case "FLOWER_POEM" /* FLOWER_POEM */: return process.env.FLOWER_POEM_API_URL || "http://localhost:3001/api/flying-flower"; case "POEM_MATCHING" /* POEM_MATCHING */: return process.env.POEM_MATCHING_API_URL || "http://localhost:3001/api/poem-matching"; default: throw new Error("\u65E0\u6548\u7684\u6E38\u620F\u7C7B\u578B"); } } async validateAnswer(historyAnswers, currentAnswer, initialCondition) { try { const response = await import_axios.default.post(`${this.baseUrl}/check-answer`, { answer: currentAnswer, historyAnswers, initialCondition }); return response.data.isCorrect; } catch (error) { console.error("\u9A8C\u8BC1\u7B54\u6848\u65F6\u53D1\u751F\u9519\u8BEF:", error); return false; } } async validateInitialCondition(initialCondition) { try { const response = await import_axios.default.post(`${this.baseUrl}/check-creation`, { initialCondition }); return response.data.isValid; } catch (error) { console.error("\u9A8C\u8BC1\u521D\u59CB\u6761\u4EF6\u65F6\u53D1\u751F\u9519\u8BEF:", error); return false; } } }; // src/application/RuleFactory.ts var RuleFactory = class { createRule(gameType) { return new RestGameRuleService(gameType); } }; // src/domain/enums/GameStatus.ts var GameStatus = /* @__PURE__ */ ((GameStatus2) => { GameStatus2["PREPARING"] = "PREPARING"; GameStatus2["PLAYING"] = "PLAYING"; GameStatus2["FINISHED"] = "FINISHED"; return GameStatus2; })(GameStatus || {}); // src/domain/Game.ts var Game = class { constructor(id, gameType, initialCondition) { this.id = id; this.gameType = gameType; this.initialCondition = initialCondition; this.players = []; this.currentPlayerIndex = 0; this.historyAnswers = []; this.status = "PREPARING" /* PREPARING */; } getId() { return this.id; } getGameType() { return this.gameType; } getInitialCondition() { return this.initialCondition; } getPlayers() { return this.players; } // setPlayers(players: Player[]): void { // this.players = players; // } getCurrentPlayerIndex() { return this.currentPlayerIndex; } getCurrentPlayer() { return this.players[this.currentPlayerIndex]; } getHistoryAnswers() { return this.historyAnswers; } getStatus() { return this.status; } addPlayer(player) { if (this.status !== "PREPARING" /* PREPARING */) { throw new Error("\u6E38\u620F\u5DF2\u7ECF\u5F00\u59CB\u6216\u7ED3\u675F\uFF0C\u4E0D\u80FD\u6DFB\u52A0\u73A9\u5BB6"); } if (this.players.some((p) => p.getName() === player.getName())) { throw new Error("\u73A9\u5BB6\u5DF2\u5B58\u5728"); } this.players.push(player); } async submitAnswer(answer, rule) { if (this.status === "PREPARING" /* PREPARING */) { throw new Error("\u6E38\u620F\u5C1A\u672A\u5F00\u59CB\uFF0C\u4E0D\u80FD\u63D0\u4EA4\u7B54\u6848"); } if (this.status === "FINISHED" /* FINISHED */) { throw new Error("\u6E38\u620F\u5DF2\u7ED3\u675F\uFF0C\u4E0D\u80FD\u63D0\u4EA4\u7B54\u6848"); } const isValid = await rule.validateAnswer(this.historyAnswers, answer, this.initialCondition); if (isValid) { this.historyAnswers.push(answer); this.currentPlayerIndex = this.getNextPlayer(); } else { const player = this.getCurrentPlayer(); console.log(answer, player); this.getCurrentPlayer().eliminate(); this.currentPlayerIndex = this.getNextPlayer(); } if (this.isGameOver()) { this.status = "FINISHED" /* FINISHED */; } return isValid; } startGame() { if (this.status !== "PREPARING" /* PREPARING */) { throw new Error("\u6E38\u620F\u5DF2\u7ECF\u5F00\u59CB\u6216\u7ED3\u675F"); } if (this.players.length < 2) { throw new Error("\u81F3\u5C11\u9700\u8981\u4E24\u540D\u73A9\u5BB6\u624D\u80FD\u5F00\u59CB\u6E38\u620F"); } this.status = "PLAYING" /* PLAYING */; } isGameOver() { const activePlayers = this.players.filter((player) => !player.isPlayerEliminated()); return activePlayers.length <= 1; } getWinner() { if (!this.isGameOver()) { return null; } return this.players.find((player) => !player.isPlayerEliminated()) || null; } getNextPlayer() { let nextIndex = (this.currentPlayerIndex + 1) % this.players.length; while (this.players[nextIndex].isPlayerEliminated()) { nextIndex = (nextIndex + 1) % this.players.length; } return nextIndex; } }; // src/application/GameFactory.ts var import_uuid = require("uuid"); var GameFactory = class { constructor(gameRepository, ruleFactory) { this.gameRepository = gameRepository; this.ruleFactory = ruleFactory; } async createGame(gameType, initialCondition) { const rule = this.ruleFactory.createRule(gameType); const isValid = await rule.validateInitialCondition(initialCondition); if (!isValid) { throw new Error("\u65E0\u6548\u7684\u521D\u59CB\u6761\u4EF6"); } const game = new Game((0, import_uuid.v4)(), gameType, initialCondition); await this.gameRepository.save(game); return game; } }; // src/domain/entities/Player.ts var Player = class { constructor(id, name) { this.id = id; this.name = name; this.score = 0; this.isEliminated = false; } getId() { return this.id; } getName() { return this.name; } getScore() { return this.score; } isPlayerEliminated() { return this.isEliminated; } addScore(points) { this.score += points; } eliminate() { this.isEliminated = true; } }; // src/application/GameService.ts var import_uuid2 = require("uuid"); var GameService = class { constructor(gameFactory, gameRepository, ruleFactory) { this.gameFactory = gameFactory; this.gameRepository = gameRepository; this.ruleFactory = ruleFactory; } async createGame(gameType, initialCondition) { return await this.gameFactory.createGame(gameType, initialCondition); } async getPreparingGames() { const games = await this.gameRepository.findAll(); return games.filter((game) => game.getStatus() === "PREPARING" /* PREPARING */); } async getNotFinishedGames() { const games = await this.gameRepository.findAll(); return games.filter((game) => game.getStatus() !== "FINISHED" /* FINISHED */); } async getFinishedGames() { const games = await this.gameRepository.findAll(); return games.filter((game) => game.getStatus() === "FINISHED" /* FINISHED */); } async joinGame(gameId, playerName) { const game = await this.gameRepository.findById(gameId); if (!game) { throw new Error("\u6E38\u620F\u4E0D\u5B58\u5728"); } if (game.getStatus() !== "PREPARING" /* PREPARING */) { throw new Error("\u6E38\u620F\u5DF2\u7ECF\u5F00\u59CB\u6216\u7ED3\u675F\uFF0C\u4E0D\u80FD\u52A0\u5165"); } const player = new Player((0, import_uuid2.v4)(), playerName); game.addPlayer(player); await this.gameRepository.update(game); return game; } async startGame(gameId) { const game = await this.gameRepository.findById(gameId); if (!game) { throw new Error("\u6E38\u620F\u4E0D\u5B58\u5728"); } if (game.getStatus() !== "PREPARING" /* PREPARING */) { throw new Error("\u6E38\u620F\u5DF2\u7ECF\u5F00\u59CB\u6216\u7ED3\u675F"); } game.startGame(); await this.gameRepository.update(game); return game; } async submitAnswer(gameId, answer) { const game = await this.gameRepository.findById(gameId); if (!game) { throw new Error("\u6E38\u620F\u4E0D\u5B58\u5728"); } const rule = this.ruleFactory.createRule(game.getGameType()); const isValid = await game.submitAnswer(answer, rule); await this.gameRepository.update(game); return isValid; } async getGame(gameId) { const game = await this.gameRepository.findById(gameId); if (!game) { throw new Error("\u6E38\u620F\u4E0D\u5B58\u5728"); } return game; } }; // src/infrastructure/web/controllers/GameController.ts var GameController = class { constructor(gameService) { this.gameService = gameService; } async createGame(req, res) { try { const { gameType, initialCondition } = req.body; if (!gameType || !initialCondition) { res.status(400).json({ error: "\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570" }); return; } const game = await this.gameService.createGame(gameType, initialCondition); res.status(201).json(game); } catch (error) { res.status(400).json({ error: error.message }); } } async getPreparingGames(req, res) { try { const games = await this.gameService.getPreparingGames(); res.json(games); } catch (error) { res.status(500).json({ error: error.message }); } } async getNotFinishedGames(req, res) { try { const games = await this.gameService.getNotFinishedGames(); res.json(games); } catch (error) { res.status(500).json({ error: error.message }); } } async getFinishedGames(req, res) { try { const games = await this.gameService.getFinishedGames(); res.json(games); } catch (error) { res.status(500).json({ error: error.message }); } } async joinGame(req, res) { try { const { gameId } = req.params; console.log(req.user); const user = req.user; if (!user) { res.status(401).json({ error: "\u672A\u767B\u5F55" }); return; } const game = await this.gameService.joinGame(gameId, user.username); res.json(game); } catch (error) { res.status(400).json({ error: error.message }); } } async startGame(req, res) { try { const { gameId } = req.params; const game = await this.gameService.startGame(gameId); res.json(game); } catch (error) { res.status(400).json({ error: error.message }); } } async submitAnswer(req, res) { try { const { gameId } = req.params; const { answer } = req.body; const user = req.user; if (!user) { res.status(401).json({ error: "\u672A\u767B\u5F55" }); return; } if (!answer) { res.status(400).json({ error: "\u7F3A\u5C11\u7B54\u6848" }); return; } const game = await this.gameService.getGame(gameId); const currentPlayer = game.getCurrentPlayer(); if (currentPlayer.getName() !== user.username) { res.status(403).json({ error: "\u4E0D\u662F\u4F60\u7684\u56DE\u5408" }); return; } const isValid = await this.gameService.submitAnswer(gameId, answer); if (isValid) { res.json({ isValid }); } else { res.status(400).json({ error: "\u7B54\u6848\u9519\u8BEF" }); } } catch (error) { res.status(400).json({ error: error.message }); } } async getGame(req, res) { try { const { gameId } = req.params; const game = await this.gameService.getGame(gameId); res.json(game); } catch (error) { res.status(404).json({ error: error.message }); } } }; // src/infrastructure/web/routes/gameRoutes.ts var import_express = require("express"); function createGameRoutes(gameController) { const router = (0, import_express.Router)(); router.post("/", (req, res) => gameController.createGame(req, res)); router.get("/preparing", (req, res) => gameController.getPreparingGames(req, res)); router.get("/not-finished", (req, res) => gameController.getNotFinishedGames(req, res)); router.get("/finished", (req, res) => gameController.getFinishedGames(req, res)); router.get("/:gameId", (req, res) => gameController.getGame(req, res)); router.post("/:gameId/join", (req, res) => gameController.joinGame(req, res)); router.post("/:gameId/start", (req, res) => gameController.startGame(req, res)); router.post("/:gameId/answer", (req, res) => gameController.submitAnswer(req, res)); return router; } // src/index.ts function createRoutes(gameRepository) { const ruleFactory = new RuleFactory(); const gameFactory = new GameFactory(gameRepository, ruleFactory); const gameService = new GameService(gameFactory, gameRepository, ruleFactory); const gameController = new GameController(gameService); const routes = createGameRoutes(gameController); return routes; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Game, GameController, GameFactory, GameService, GameStatus, GameType, Player, RuleFactory, createRoutes });