poem_game_component
Version:
468 lines (454 loc) • 15.2 kB
JavaScript
"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
});